Code coverage là một số liệu dùng để đánh giá bao nhiêu line of code của chúng ta đã được cover bằng Unit Test. Số liệu này rất có ích, giúp chúng ta có thể đánh giá được chất lượng code của chúng ta như thế nào, bao nhiêu code của chúng ta đã được và chưa được cover bởi Unit Test. Trong bài viết này, mình giới thiệu với các bạn một plugin của Apache Maven tên là JaCoCo Maven Plugin giúp chúng ta có thể đo được số liệu code coverage này các bạn nhé.
Mình sẽ tạo mới một Maven project với một ví dụ đơn giản có Unit Test như sau:
JUnit dependency như sau:
1 2 3 4 5 6 |
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> |
Class Calculation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.huongdanjava.mavenjacocoplugin; public class Calculation { public int add(int a, int b) { return a + b; } public int sub(int a, int b) { if (a >= b) { return a - b; } return b - a; } } |
Class CalculationTest:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.huongdanjava.mavenjacocoplugin; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; public class CalculationTest { private Calculation calculation; @Before public void init() { calculation = new Calculation(); } @Test public void testAdd() { assertEquals(4, calculation.add(1, 3)); } @Test public void testSub() { assertEquals(2, calculation.sub(7, 5)); assertEquals(9, calculation.sub(3, 12)); } } |
JaCoCo Maven Plugin:
1 2 3 4 5 |
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.2</version> </plugin> |
OK, bắt đầu nào các bạn!
JaCoCo Maven Plugin định nghĩa rất nhiều goal, nhưng có một goal mà chúng ta cần phải khai báo để plugin này có thể tính toán được số liệu code coverage cho chúng ta, đó là goal: prepare-agent. Giả sử bây giờ mình khai báo goal này trong project example ở trên:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.1</version> <executions> <execution> <id>agent-for-ut</id> <goals> <goal>prepare-agent</goal> </goals> </execution> </executions> </plugin> |
rồi click chuột phải vào project, chọn Run As rồi chọn Maven test thì các bạn sẽ thấy kết quả trong Console tab của Eclipse như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
[INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building maven-jacoco-plugin 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- jacoco-maven-plugin:0.8.2:prepare-agent (agent-for-ut) @ maven-jacoco-plugin --- [INFO] argLine set to "-javaagent:/Users/Khanh/.m2/repository/org/jacoco/org.jacoco.agent/0.8.2/org.jacoco.agent-0.8.2-runtime.jar=destfile=/Users/khanh/Working/Workspace Eclipse/maven-jacoco-plugin/target/jacoco.exec" [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-jacoco-plugin --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ maven-jacoco-plugin --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-jacoco-plugin --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ maven-jacoco-plugin --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-jacoco-plugin --- [INFO] Surefire report directory: /Users/khanh/Working/Workspace Eclipse/maven-jacoco-plugin/target/surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- objc[1640]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/bin/java (0x1052214c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10531b4e0). One of the two will be used. Which one is undefined. Running com.huongdanjava.mavenjacocoplugin.CalculationTest Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.095 sec Results : Tests run: 2, Failures: 0, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.771 s [INFO] Finished at: 2018-10-12T20:59:30+07:00 [INFO] Final Memory: 15M/220M [INFO] ------------------------------------------------------------------------ |
Như các bạn thấy ở dòng:
1 2 |
[INFO] --- jacoco-maven-plugin:0.8.2:prepare-agent (agent-for-ut) @ maven-jacoco-plugin --- [INFO] argLine set to "-javaagent:/Users/Khanh/.m2/repository/org/jacoco/org.jacoco.agent/0.8.2/org.jacoco.agent-0.8.2-runtime.jar=destfile=/Users/khanh/Working/Workspace Eclipse/maven-jacoco-plugin/target/jacoco.exec" |
một tập tin tên là jacoco.exec đã được tạo ra trong thư mục target của project. Đây chính là tập tin chứa kết quả report code coverage mà JaCoCo Maven Plugin đã tạo ra. Tập tin này ở dạng binary nên chúng ta không thể xem trực tiếp được nhưng chúng ta vẫn có một cách khác để xem kết quả report này bằng cách sử dụng goal report của JaCoCo Maven Plugin này.
Các bạn hãy chạy project Maven với goal jacoco:report để xem kết quả như thế nào nhé:
Lúc này, nếu các bạn kiểm tra thư mục target của project, các bạn sẽ thấy một thư mục tên là site chứa thông tin về code coverage mà JaCoCo Maven Plugin đã tạo ra sau khi chúng ta chạy project với goal report trên:
Mở tập tin index.html trong thư mục target/site/jacoco các bạn sẽ thấy kết quả như sau:
Đây chính là tất cả các thông tin về code coverage trong project của chúng ta. Các bạn có thể dễ dàng thấy bao nhiêu % code coverage cho từng package trong project của chúng ta phải không?
Các bạn có thể click vào từng package để xem chi tiết:
Như các bạn thấy, chúng ta có thể xem chi tiết code coverage đến từng method. Các bạn cũng có thể click vào từng method để xem chúng ta đã coverage những đoạn code nào.
Mặc định, những đoạn code nào đã được coverage thì đoạn code đó sẽ được high light bằng màu xanh lá cây, còn ngược lại sẽ là màu đỏ. Ở đây chúng ta còn trường hợp nữa là code Unit Test của chúng ta chưa cover hết tất cả các case có thể xảy ra trong một dòng code nào đó. Lúc này, đoạn code này sẽ được hight light bằng màu vàng.
Ví dụ như, nếu bây giờ mình sửa lại code của CalculationTest, remove:
1 |
assertEquals(9, calculation.sub(3, 12)); |
trong method testSub() thì các bạn sẽ thấy code coverage report cho class Calculation như sau:
Kết quả như trên cho thấy, code Unit Test của chúng ta chưa chạy qua dòng code “return b – a” (nên bị high light bằng màu đỏ) và ở dòng code “if (a >= b)”, còn một case nữa mà chúng ta chưa cover (do đó, đoạn code này high light bằng màu vàng).
Ha Nguyen
jacoco này chạy khi unit test,
Có cách nào cho nó chạy lúc test end to end không bạn nhỉ.
Khanh Nguyen
Không đâu bạn ơi! Code coverage có cần cho test end to end không bạn nhỉ?
Long
code coverage nằm trong whitebox, test end to end thì không tính code coverage được đâu bạn.