Skip to main content

Độ bao phủ code của unittest


Nếu bạn là một developer, chắc hẳn bạn phải thừa nhận rằng unittest đóng một vai trò cực kỳ quan trọng trong việc giúp ta phát hiện sớm các vấn đề của dự án trong quá trình phát triển, cả về mặt thực thi lẫn các requirement. Một yếu tố quan trọng của unittest chính là độ bao phủ code, thứ giúp ta đo lường được bao nhiêu phần trăm của code được test qua khi chạy unittest. Về mặt tổng quan, số phần trăm này càng cao thì mức độ đảm bảo của code càng cao, và đa số mọi người đều muốn vậy.
Vậy thì làm thế nào để đo lường được con số này? Từ version 7, Xcode đã có tính năng code coverage cho phép ta đo và hình dung được độ bao phủ code. Bài viết này sẽ giới thiệu cách đo đại lượng này và làm sao để tăng độ bao phủ lên.

Xem độ bao phủ code trong Xcode

Xcode cung cấp sẵn cho người dùng giao diện để xem được độ bao phủ một cách chi tiết nhất, để xem được chức năng này, vào Product > Scheme > Edit Scheme
Sau đó chọn tab Test > Options, tick chọn Code Coverage - Gather coverage
Tiếp theo, hãy chạy unittest, bài viết này sử dụng một demo projects để chạy test, bạn có thể sử dụng app của mình để thực hiện:
Tất cả các testcase đều đã pass, kích vào Report Navigator, ta sẽ thấy được báo cáo về độ bao phủ mà unittest đang đạt được:
Demo này đạt được 58.18%, ta còn có thể xem được chi tiết từng file đang được bao phủ bao nhiêu phần trăm:

Tăng độ bao phủ cho unittest

Để tăng độ bao phủ ta có thể rà soát toàn bộ dự án, kiểm tra những nơi unittest chưa chạy qua và viết test cho tất cả những nơi có thể.
Ta có thể áp dụng các cách sau:
  1. Viết test cho mọi phương thức public
  2. Tăng độ bao phủ cho các phương thức public bằng việc kiểm tra xem dòng code nào chưa được chạy qua.
Trong ví dụ trên, ta có 3 class, hai class AppDelegate và BullsEyeGame đều đạt 100%, chỉ còn class ViewController mới đạt được 45.88%, nếu tăng độ bảo phủ của class này thì sẽ tăng được giá trị của toàn app. Dòng màu xanh này đánh dấu đoạn code đã được test:
Và dòng màu đỏ đánh dấu đoạn code này chưa được test
Dựa vào những phân tích này ta có thể viết thêm các test case phù hợp để nâng code coverage lên.
Ngoài ra, còn có một cách để nâng độ bao phủ code rất hiệu quả đó là viết UI test, nếu ta chỉ viết logic, thì mới đảm bảo tầm 30-40% độ bao phủ, tuy nhiên, nếu sử dụng cả UI test thì hầu như có thể đạt được khoảng 80%, vì code UI chiếm một lượng khá lớn trong toàn app.
Để viết UI test, bạn có thể tham khảo một số framework như Quick and Nimble (https://github.com/Quick/Nimble), KIF (https://github.com/kif-framework/KIF).
Tuy nhiên, độ bao phủ cao chưa chắc đã đảm bảo được ứng dụng có chất lượng tốt, điều quan trọng là phải đảm bảo testcase cover được những luồng logic quan trọng của dự án, và cover được càng nhiều trường hợp càng tốt. Vì vậy ta cần đảm bảo cả về mặt chất lượng lẫn số lượng thì chất lượng của dự án càng được nâng cao.

Comments

Popular posts from this blog

Swift Tool Belt, Part 1: Adding a Border, Corner Radius, and Shadow to a UIView with Interface Builder

During my iOS work, I’ve assembled a set of code that I bring with me on every iOS project. I’m not talking about large frameworks or CocoaPods here. These are smaller Swift extensions or control overrides that are applicable to many projects. I think of them as my tool belt. In this post, I’ll show you an extension that will add a border, a corner radius, and a shadow to any UIView, UIButton, or UILabel and allow you to preview what it will look like in Interface Builder. Back in 2014, I wrote a blog post on Expanding User-Defined Runtime Attributes in Xcode where I added a border, corner radius, and shadow to a UIView using Interface Builder’s user-defined runtime attributes. This solution had no type checking—you had to type the property you wanted to modify by hand and often had to look up what it was called. You also had to run your project in order to see the effect of the runtime attribute. Starting with Xcode 6 , there is a new mech...

Alamofire vs URLSession

Alamofire vs URLSession: a comparison for networking in Swift Alamofire and URLSession both help you to make network requests in Swift. The URLSession API is part of the foundation framework, whereas Alamofire needs to be added as an external dependency. Many  developers  doubt  whether it’s needed to include an extra dependency on something basic like networking in Swift. In the end, it’s perfectly doable to implement a networking layer with the great URLSession API’s which are available nowadays. This blog post is here to compare both frameworks and to find out when to add Alamofire as an external dependency. Build better iOS apps faster Looking for a great mobile CI/CD solution that has tons of iOS-specific tools, smooth code signing, and even real device testing? Learn more about Bitrise’s iOS specific solutions! This shows the real power of Alamofire as the framework makes a lot of things easier. What is Alamofire? Where URLSession...

Frame vs Bounds in iOS

This article is a repost of an answer I wrote on Stack Overflow . Short description frame = a view’s location and size using the parent view’s coordinate system ( important for placing the view in the parent) bounds = a view’s location and size using its own coordinate system (important for placing the view’s content or subviews within itself) Details To help me remember frame , I think of a picture frame on a wall . The picture frame is like the border of a view. I can hang the picture anywhere I want on the wall. In the same way, I can put a view anywhere I want inside a parent view (also called a superview). The parent view is like the wall. The origin of the coordinate system in iOS is the top left. We can put our view at the origin of the superview by setting the view frame’s x-y coordinates to (0, 0), which is like hanging our picture in the very top left corner of the wall. To move it right, increase x, to move it down increase y. To help me remember bound...