**TestNG** và **JUnit** đều là các framework dùng trong kiểm thử, đặc biệt là kiểm thử đơn vị (unit testing) và na ná nhau. TestNG có thêm nhiều tính năng giúp nó mạnh hơn khi so sánh với JUnit. Bài viết này tập trung chủ yếu phân tích một vài đặc điểm của JUnit4 và TestNG, giúp developer và tester lựa chọn framework phù hợp cho công việc kiểm thử. **Bảng so sánh** chức năng giữa TestNG và JUnit4. Hiện nay JUnit đã phát hành phiên bản JUnit4 vượt trội hơn so với các bản cũ, JUnit4 có khá nhiều tính năng giống TestNG. ![alt](http://i.imgur.com/8vpb43z.jpg) **Annotation** Các annotations sử dụng trong TestNG và Junit hầu hết tương tự nhau. Ví dụ như TestNG dùng `@BeforeMethod` , `@AfterMethod` giống như cách mà Junit dùng `@Before` , `@After` . | STT | Tính năng | TestNG | JUnit | | -------- | -------- | -------- | -------- | | 1 | Test annotation | `@Test` | `@Test` | | 2 | Chạy trước method test đầu tiên trong class hiện tại | `@BeforeClass` | `@BeforeClass` | | 3 | Chạy trước tất cả method test trong class hiện tại | `@AfterClass` | `@AfterClass`| | 4 | Chạy trước mỗi method test | `@BeforeMethod` | `@Before` | | 5 | Chạy sau mỗi method test | `@AfterMethod` | `@After` | | 6 | Bỏ qua test | `@Test(enbale=false)` | `@ignore` | | 7 | Bắt ngoại lệ | `@Test(expectedExceptions = ArithmeticException.class)` | `@Test(expected = ArithmeticException.class)` | | 8 | Timeout | `@Test(timeout = 1000)` | `@Test(timeout = 1000)`| | 9 | Chạy trước tất cả test trong suite | `@BeforeSuite`| `-`| | 10 | Chạy trước tất cả test trong suite | `@AfterSuite`| `-`| | 11 | Chạy trước các `@Test` | `@BeforeTest` | `-`| | 12 | Chạy sau các `@Test`| `@AfterTest` | `-`| | 13 | Chạy trước test method đầu tiên bất kỳ trong test group | `@BeforeGroups` |` -`| | 14 | Chạy sacu last method cuối cùng bất kỳ trong test group | `@AfterGroups`|`-`| Có 2 điểm cần chú ý là: 1. Trong JUnit4, chúng ta phải khai báo `@BeforeClass` và `@AfterClass` là các phương thức tĩnh (static method), đối với TestNG thì không cần làm điều này. 2. TestNG cung cấp thêm 3 mức độ Before/AfterSuite, Before/AfterTest, Before/AfterGroup cho phép linh hoạt hơn khi chạy test. **Suite Test - Chạy bộ test** Suite được dùng khi chạy gộp nhiều test và có thể được tạo bằng 2 framework trên. _Dùng Junit_ JUnit sử dụng `@RunWith` và `@Suite` để chạy các suite. Ví dụ dưới đây dùng để nhóm "JunitTest1" và "JunitTest2" chạy đồng thời. ``` @RunWith(Suite.class) @Suite.SuiteClasses({ JunitTest1.class, JunitTest2.class }) public class JunitTest5 { } ``` _Dùng TestNG_ TestNG sử dụng file XML để định nghĩa "TestNGTest1" và "TestNGTest2" sẽ chạy cùng nhau ``` <!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" > <suite name="My test suite"> <test name="testing"> <classes> <class name="com.trangvt.TestNGTest1" /> <class name="com.trangvt.TestNGTest2" /> </classes> </test> </suite> ``` Ngoài chạy test suite, chúng ta có thể định nghĩa group, cũng trong file XML, để nhóm các method test. **Ignore Test - Bỏ qua test** _Dùng Junit_ ``` @Ignore public void method1() { System.out.println("Using @Ignore , this execution is ignored"); } ``` _Dùng TestNG_ ``` @Test(enabled=false) public void TestWithException() { System.out.println("Method should be ignored as it's not ready yet"); } ``` **Parameterized Test - Truyền tham số test** _Dùng Junit_ Sử dụng `@RunWith` và `@Parameter` để truyền giá trị tham số cho test. `@Parameter` trả về một mảng List[], các tham số (parameter) được truyền dưới dạng đối số (argument) vào hàm khởi tạo lớp. ``` @RunWith(value = Parameterized.class) public class JunitTest6 { private int number; public JunitTest6(int number) { this.number = number; } @Parameters public static Collection<Object[]> data() { Object[][] data = new Object[][] { { 1 }, { 2 }, { 3 }, { 4 } }; return Arrays.asList(data); } @Test public void pushTest() { System.out.println("Parameterized Number is : " + number); } } ``` _Dùng TestNG_ Trong TestNG, sử dụng file XML hoặc `@DataProvider` để ra hiệu rằng ta đang cung cấp tham số cho test. ``` public class Test1 { @Test @Parameters(value="number") public void parameterTest(int number) { System.out.println("Parameterized Number is : " + number); } } ``` Ở đây `@Parameters` được định nghĩa trong method test. Data được lưu tại file XML như bên dưới, mỗi lần chạy test thì giá trị number sẽ được truyền vào hàm test và in ra kết quả. Bằng cách này, chúng ta có thể tái sử dụng một test case với các tập dữ liệu khác nhau và cho ra kết quả khác nhau. ``` <!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" > <suite name="My test suite"> <test name="testing"> <parameter name="number" value="2"/> <classes> <class name="com.guru99.Test1" /> </classes> </test> </suite> ``` **Timeout** JUnit dùng từ khóa "timeout" để truyền thời gian đợi vào hàm test trong khi TestNG dùng "timeOut", đơn vị đều là miliseconds. **Exception Test** JUnit dùng từ khóa "expected" để truyền thời gian đợi vào hàm test trong khi TestNG dùng "expectedExceptions", đơn vị đều là miliseconds. _Dùng Junit_ ``` @Test(expected = ArithmeticException.class) public void divideByZero() { Int i = 1/0; } ``` _Dùng TestNG_ ``` @Test(expectedExceptions = ArithmeticException.class) public void divideByZero() { Int i = 1/0; } ``` **Dependency Test** Tham số test chỉ ra các test chạy phụ thuộc lẫn nhau. Nếu một hàm test chạy bị lỗi thì các hàm test khác phụ thuộc nó sẽ bị bỏ qua khi chạy. TestNG sử dụng tham số mang tên "dependOnMethods" để cài đặt các test phụ thuộc, JUnit chưa hỗ trợ tính năng này. ``` @Test public void method1() { System.out.println("This is method 1"); } @Test(dependsOnMethods={"method1"}) public void method2() { System.out.println("This is method 2"); } ``` Hàm “method2()” sẽ được chạy khi và chỉ khi hàm “method1()” chạy ok, nếu không “method2()” bỏ qua. **Kết luận** Về cơ bản TestNG và JUnit khá là giống nhau, theo tôi bạn nên sử dụng TestNG testing framework cho dự án, vì TestNG cung cấp nhiều tính năng hỗ trợ mạnh mẽ như đưa tham số vào hàm test, dependency testing hoặc test theo suite. TestNG thích hợp cho kiểm thử ở mức độ trừu tượng (high-level) và kiểm thử tích hợp phức tạp. Ngoài ra, TestNG cũng bao gồm toàn bộ các chức năng cốt lõi Junit và nó có thể kết hợp với các framwork như Selenium hỗ trợ cho công việc kiểm thử được hoàn thiện hơn. **Tham khảo** [TestNG](http://testng.org/doc/index.html) [Compare JUnit & TestNG](https://www.mkyong.com/unittest/junit-4-vs-testng-comparison/)