SlideShare uma empresa Scribd logo
1 de 13
Testing with JUnit

                TRƯỜNG ĐẠI HỌC DUY TÂN
                   KHOA ĐÀO TẠO QUỐC TẾ
                        »»»»««««




        KIỂM THỬPHẦ MỀM VỚ
                    N     I
                JUnit
         APPLICATION DEVELOPMENT PRACTICES




                                     GVHD: Thầy Võ Văn Lường
                                       Thành viên: Mai Văn Minh
                                              Huỳnh Ngọc Khoa
                                                Hoàng Duy Hưng
                                                 Trần Thành Tâm




JUnit testing                                             Page 1
Testing with JUnit



Mục lục
1) Giới thiệu .................................................................................................................................................. 3
2) Ví dụ test các chức năng của một lớp ....................................................................................................... 3
4) Thế nào là một unit test tốt ....................................................................................................................... 6
5) Set Up và Tear Down ............................................................................................................................... 7
6) Tổ chức các test vào các test suite .......................................................................................................... 10
7) Chạy các test lặp đi lặp lại ...................................................................................................................... 11
9) Giới thiệu một số công cụ, thư viện nguồn mở hỗ trợ việc test phần mềm ............................................ 12
   a) Cactus ................................................................................................................................................. 12
   b) HttpUnit .............................................................................................................................................. 12
   c) NUnit .................................................................................................................................................. 12
10) Tham khảo ............................................................................................................................................ 13




JUnit testing                                                                                                                                          Page 2
Testing with JUnit




KIỂM THỬ PHẦN MỀM VỚI JUnit
JUnit là một framework đơn giản dùng cho việc tạo các unit testing tự động, và chạy các
test có thể lặp đi lặp lại. Nó chỉ là một phần của họ kiến trúc xUnit cho việc tạo các unit
testing. JUnit là một chuẩn trên thực tế cho unit testing trong Java. JUnit về nguồn gốc
được viết bởi 2 tác giả Erich Gamma và Kent Beck


1) Giới thiệ u
JUnit có thể được tải xuống từ địa chỉ http://www.junit.org.
JUnit có những đặc điểm đáng lưu tâm như sau:
• Xác nhận (assert) việc kiểm tra kết quả được mong đợi
• Các Test Suite cho phép chúng ta dễ dàng tổ chức và chạy các test
• Hỗ trợ giao diện đồ họa và giao diện dòng lệnh
Các test case của JUnit là các lớp của Java, các lớp này bao gồm một hay nhiều các phương thức unit
testing, và những test này lại được nhóm thành các Test Suite.
Mỗi phương thức test trong JUnit phải được thực thi nhanh chóng. Tốc độ là điều tối quan trọng vì càng
nhiều test được viết và tích hợp vào bên trong quá trình xây dựng phần mềm, cần phải tốn nhiều thời
gian hơn cho việc chạy toàn bộ Test Suite. Các lập trình viên không muốn bị ngắt quãng trong một
khoãng thời gian dài trong khi các test chạy, vì thế các test mà chạy càng lâu thì sẽ có nhiều khả năng là
các lập trình viên sẽ bỏ qua bước cũng không kém phần quan trọng này.
Các test trong JUnit có thể là các test được chấp nhận hay thất bại, các test này được thiết kế để khi
chạy mà không cần có sự can thiệp của con người. Từ những thiết kế như thế, bạn có thể thêm các bộ
test vào quá trình tích hợp và xây dựng phần mềm một cách liên tục và để cho các test chạy một cách tự
động




2) Ví dụ test các chức năng của một lớp
Bạn muốn viết các unit test với JUnit. Việc đầu tiên bạn phải tạo một lớp con thừa kế từ lớp
junit.framework.TestCase. Mỗi unit test được đại diện bởi một phương thức testXXX() bên trong lớp con
của lớp TestCase


Ta có một lớp Person như sau:


public class Person {
private String firstName;
private String lastName;

public Person(String firstName, String lastName) {
if (firstName == null && lastName == null) {

JUnit testing                                                                                       Page 3
Testing with JUnit
throw new IllegalArgumentException("Both names cannot be null");
}
this.firstName = firstName;
this.lastName = lastName;
}

public String getFullName() {
String first = (this.firstName != null) ? this.firstName : "?";
String last = (this.lastName != null) ? this.lastName : "?";

return first + last;
}

public String getFirstName() {
return this.firstName;
}

public String getLastName() {
return this.lastName;
}
}


Sau đó ta sẽ viết một test case đơn giản để test một số phương thức của lớp trên
import junit.framework.TestCase;

public class TestPerson extends TestCase {
public TestPerson(String name) {
super(name);
}

/**
* Xac nhan rang name duoc the hien dung dinh dang
*/
public void testGetFullName() {
Person p = new Person("Aidan", "Burke");
assertEquals("Aidan Burke", p.getFullName());
}

/**
* Xac nhan rang nulls da duoc xu ly chinh xac
*/
public void testNullsInName() {
Person p = new Person(null, "Burke");
assertEquals("? Burke", p.getFullName());

p = new Person("Tanner", null);
assertEquals("Tanner ?", p.getFullName());
}
}


Lưu ý: mỗi unit test là một phương thức public và không có tham số được bắt đầu bằng tiếp đầu ngữ
test. Nếu bạn không tuân theo quy tắc đặt tên này thì JUnit sẽ không xác định được các phương thức
test một các tự động.



JUnit testing                                                                                  Page 4
Testing with JUnit
Để biên dịch TestPerson, chúng ta phải khai báo gói thư viện junit trong biến đường môi trường
classpath
set classpath=%classpath%;.;junit.jar
javac TestPerson
Để chạy một JUnit TestCase, ta có 2 cách


• Chạy với môi trường text, các bạn gõ lệnh
java junit.textui.TestRunner TestPerson


Sau khi chạy sẽ có kết quả như hình trên.

• Chạy với môi trường đồ họa
java junit.swingui.TestRunner TestPerson

Chúng ta có thể chạy trực tiếp các TestCase mà không muốn kích hoạt một trong các test runner của
JUnit. Chúng ta sẽ thêm phương thức main() vào test case. Ví dụ
public class TestGame extends TestCase {
…
public static void main(String []args) {
junit.textui.TestRunner.run(new TestSuite(TestGame.class))
}
}


3) Các phương thức assertXXX()
Các phương thức assertXXX() được dùng để kiểm tra các điều kiện khác nhau.
junit.framework.TestCase, lớp cha cho tất cả các test case, thừa kế từ lớp junit.framework.Assert. Lớp
này định nghĩa khá nhiều các phương thức assertXXX(). Các phương thức test hoạt động bằng cách gọi
những phương thức này.
Bảng sau mô tả các phương thức assertXXX() khác nhau có trong lớp junit.framework.Assert.

Phương thức Mô tả
assertEquals() So sánh 2 giá trị để kiểm tra bằng nhau. Test sẽ được chấp nhận nếu các giá trị bằng
nhau
assertFalse() Đánh giá biểu thức luận lý. Test sẽ được chấp nhận nếu biểu thức sai
assertNotNull() So sánh tham chiếu của một đối tượng với null. Test sẽ được chấp nhận nếu tham chiếu
đối tượng khác null
assertNotSame() So sánh địa chỉ vùng nhớ của 2 tham chiếu đối tượng bằng cách sử dụng toán tử
==. Test sẽ được chấp nhận nếu cả 2 đều tham chiếu đến các đối tượng khác nhau
assertNull() So sánh tham chiếu của một đối tượng với giá trị null. Test sẽ được chấp nhận nếu
tham chiếu là null
assertSame() So sánh địa chỉ vùng nhớ của 2 tham chiếu đối tượng bằng cách sử dụng toán tử ==.
Test sẽ được chấp nhận nếu cả 2 đều tham chiếu đến cùng một đối tượng
assertTrue() Đánh giá một biểu thức luận lý. Test sẽ được chấp nhận nếu biểu thức đúng
fail() Phương thức này làm cho test hiện hành thất bại, phương thức này thường được sử dụng khi
xử lý các biệt lệ


JUnit testing                                                                                    Page 5
Testing with JUnit
Mặc dù bạn có thể chỉ cần sử dụng phương thức assertTrue() cho gần như hầu hết các test, tuy nhiên thì
việc sử dụng một trong các phương thức assertXXX() cụ thể sẽ làm cho các test của bạn dễ hiểu hơn và
cung cấp các thông điệp thất bại rõ ràng hơn.
Tất cả các phương thức của bảng trên đều nhận vào một String không bắt buộc làm tham số đầu tiên.
Khi được xác định, tham số này cung cấp một thông điệp mô tả test thất bại.
Ví dụ:
assertEquals(employeeA, employeeB);
assertEquals(“Employees should be equal after the clone() operation.”,
employeeA, employeeB).
Phiên bản thứ 2 được ưa thích hơn vì nó mô tả tại sao test thất bại, điều này sẽ giúp cho việc sửa lỗi
được dễ dàng hơn




4) Thế nào là một unit test tốt
Mỗi unit test chỉ nên kiểm tra phần cụ thể của một chức năng nào đó. Chúng ta không nên kết hợp nhiều
test không liên quan với nhau lại vào trong một phương thức testXXX()
Ta có một lớp Game như sau
public class Game {
private Map ships = new HashMap();

public Game() throws BadGameException {
}

public void shutdown() {
// dummy method
}

public synchronized Ship createFighter(String fighterId) {
Ship s = (Ship) this.ships.get(fighterId);
if (s == null) {
s = new Ship(fighterId);
this.ships.put(fighterId, s);
}
return s;
}

public boolean isPlaying() {
return false;
}
}

public class BadGameException extends Exception {
public BadGameException(String s) {
super(s);
}
}

Sau đó ta viết một đoạn test sau đây:
public void testGame() throws BadGameException{
Game game = new Game();

JUnit testing                                                                                      Page 6
Testing with JUnit
Ship fighter = game.createFighter(“001”);
assertEquals("Fighter did not have the correct identifier", "001",
this.fighter.getId());
Ship fighter2 = this.game.createFighter("001");
assertSame("createFighter with same id should return same object", fighter,
fighter2);
assertTrue("A new game should not be started yet", !this.game.isPlaying());
}

Đây là một thiết kế không tốt vì mỗi phương thức assertXXX() đang kiểm tra phần không liên quan của
chức năng. Nếu phương thức assertEquals thất bại, phần còn lại của test sẽ không được thi hành. Khi
xảy ra điều này thì chúng ta sẽ không biết các test khác có đúng chức năng hay không
Tiếp theo chúng ta sẽ sửa test trên lại để kiểm tra các khía cạnh khác nhau của trò chơi một cách độc
lập.
public void testCreateFighter() {
System.out.println("Begin testCreateFigher()");
assertEquals("Fighter did not have the correct identifier", "001",
this.fighter.getId());
System.out.println("End testCreateFighter()");
}

public void testSameFighters() {
System.out.println("Begin testSameFighters()");
Ship fighter2 = this.game.createFighter("001");
assertSame("createFighter with same id should return same object",
this.fighter, fighter2);
System.out.println("End testSameFighters()");
}

public void testGameInitialState() {
System.out.println("Begin testGameInitialState()");
assertTrue("A new game should not be started yet", !this.game.isPlaying());
System.out.println("End testGameInitialState()");
}

Với cách tiếp cận này, khi một test thất bại sẽ không làm cho các mệnh đề assertXXX() còn lại bị bỏ qua.
Có thể bạn sẽ đặt ra câu hỏi có khi nào một phương thức test chứa nhiều hơn một các phương thức
assertXXX() hay không? Câu trả lời là có. Nếu bạn cần kiểm tra một dãy các điều kiện và các test theo
sau sẽ luôn thất bại nếu có một test đầu tiên thất bại, khi đó bạn có thể kết hợp nhiều phương thức
assert vào trong một test




5) Set Up và Tear Down
Hai phương thức setUp() và tearDown() là một phần của lớp junit.framework.TestCase Bằng cách sử
dụng các phương thức setUp và tearDown. Khi sử dụng 2 phương thức setUp() và tearDown() sẽ giúp
chúng ta tránh được việc trùng mã khi nhiều test cùng chia sẻ nhau ở phần khởi tạo và dọn dẹp các biến.
JUnit tuân thủ theo một dãy có thứ tự các sự kiện khi chạy các test. Đầu tiên, nó tạo ra một thể hiện mới
của test case ứng với mỗi phương thức test. Từ đó, nếu bạn có 5 phương thức test thì JUnit sẽ tạo ra 5
thể hiện của test case. Vì lý do đó, các biến thể hiện không thể được sử dụng để chia sẻ trạng thái giữa
các phương thức test. Sau khi tạo xong tất cả các đối tượng test case, JUnit tuân theo các bước sau cho
mỗi phương thức test:


JUnit testing                                                                                     Page 7
Testing with JUnit
• Gọi phương thức setUp() của test case
• Gọi phương thức test
• Gọi phương thức tearDown() của test case
Quá trình này được lặp lại đối với mỗi phương thức test trong test case.
Sau đây chúng ta sẽ xem xét 1 ví dụ
public class Ship {
private String id;

public Ship(String id) {
this.id = id;
}

public String getId() {
return this.id;
}
}

public class TestGame extends TestCase {
private Game game;
private Ship fighter;

public void setUp() throws BadGameException {
this.game = new Game();
this.fighter = this.game.createFighter("001");
}

public void tearDown() {
this.game.shutdown();
}

public void testCreateFighter() {
System.out.println("Begin testCreateFigher()");
assertEquals("Fighter did not have the correct identifier",
"001", this.fighter.getId());
System.out.println("End testCreateFighter()");
}

public void testSameFighters() {
System.out.println("Begin testSameFighters()");
Ship fighter2 = this.game.createFighter("001");
assertSame("createFighter with same id should return same object",
this.fighter, fighter2);
System.out.println("End testSameFighters()");
}

public void testGameInitialState() {
System.out.println("Begin testGameInitialState()");
assertTrue("A new game should not be started yet",
!this.game.isPlaying());
System.out.println("End testGameInitialState()");
}
}
Thông thường bạn có thể bỏ qua phương thức tearDown() vì mỗi unit test riêng không phải là những tiến
trình chạy tốn nhiều thời gian, và các đối tượng được thu dọn khi JVM thoát. tearDown() có thể được sử

JUnit testing                                                                                  Page 8
Testing with JUnit
dụng khi test của bạn thực hiện những thao tác như mở kết nối đến cơ sở dữ liệu hay sử dụng các loại
tài nguyên khác của hệ thống và bạn cần phải dọn dẹp ngay lập tức. Nếu bạn chạy một bộ bao gồm một
số lượng lớn các unit test, thì khi bạn trỏ tham chiếu của các đối tượng đến null bên trong thân phương
thức tearDown() sẽ giúp cho bộ dọn rác lấy lại bộ nhớ khi các test khác chạy
Đôi khi bạn muốn chạy vài đoạn mã khởi tạo chỉ một lần, sau đó chạy các phương thức test, và bạn chỉ
muốn chạy các đoạn mã dọn dẹp chỉ sau khi tất cả test kết thúc. Ở phần trên, JUnit gọi phương thức
setUp() trước mỗi test và gọi tearDown() sau khi mỗi test kết thúc, vì thế để làm được điều như trên,
chúng ta sẽ sử dụng lớp junit.extension.TestSetup để đạt được yêu cầu trên.
Ví dụ sau sẽ minh họa việc sử dụng lớp trên
import junit.extensions.TestSetup;
import junit.framework.*;

public class TestPerson extends TestCase {
public TestPerson(String name) {
super(name);
}

public void testGetFullName() {
Person p = new Person("Aidan", "Burke");
assertEquals("Aidan Burke", p.getFullName());
}

public void testNullsInName() {
Person p = new Person(null, "Burke");
assertEquals("? Burke", p.getFullName());

p = new Person("Tanner", null);
assertEquals("Tanner ?", p.getFullName());
}

public static Test suite() {
TestSetup setup = new TestSetup(new TestSuite(TestPerson.class)) {
protected void setUp() throws Exception {
//Thực hiện các đoạn mã khởi tạo một lần ở đây
}

protected void tearDown() throws Exception {
//Thực hiện các đoạn mã dọn dẹp ở đây
}
};
return setup;
}
}


TestSetup là một lớp thừa kế từ lớp junit.extension.TestDecorator, Lớp TestDecorator là lớp cơ sở cho
việc định nghĩa các test biến thể. Lý do chính để mở rộng TestDecorator là để có được khả năng thực thi
đoạn mã trước và sau khi một test chạy. Các phương thức setUp() và tearDown() của lớp TestSetup
được gọi trước và sau khi bất kỳ Test nào được truyền vào constructor,
Trong ví dụ trên chúng ta đã truyền một tham số có kiểu TestSuite vào constructor của lớp TestSetup
TestSetup setup = new TestSetup(new TestSuite(TestPerson.class)) {
Điều này có nghĩa là 2 phương thức setUp() được gọi chỉ một lần trước toàn bộ bộ test và tearDown()
được gọi chỉ một lần sau khi các test trong bộ test kết thúc.


JUnit testing                                                                                    Page 9
Testing with JUnit
Chú ý: các phương thức setUp() và tearDown() bên trong lớp TestPerson vẫn được thực thi trước và sau
mỗi phương thức test bên trong lớp TestPerson.




6) Tổ chức các test vào các test suite
Thông thường JUnit tự động tạo ra các Test Suite ứng với mỗi Test Case. Tuy nhiên bạn muốn tự tạo
các Test Suite của riêng mình bằng cách tổ chức các Test vào Test Suite. JUnit cung cấp lớp
junit.framework.TestSuite hỗ trợ việc tạo các Test Suite
Khi bạn sử dụng giao diện text hay graphic, JUnit sẽ tìm phương thức sau trong test case của bạn
public static Test suite() { … }
Nếu không thấy phương thức trên, JUnit sẽ sử dụng kỹ thuật reflection để tự động xác định tất cả các
phương thức testXXX() trong test case của bạn, rồi thêm chúng vào một test suite. Sau đó nó sẽ chạy tất
cả các test trong suite này. Bạn có thể tạo ra bản sao hành vi của phương thức suite() mặc định như sau


public class TestGame extends TestCase{
…
public static Test suite() {
return new TestSuite(TestGame.class);
}
}


Bằng cách truyền đối tượng TestGame.class vào construtor TestSuite, bạn đang thông báo cho JUnit biết
để xác định tất cả các phương thức testXXX() trong lớp đó và thêm chúng vào suite. Đoạn mã trên không
làm khác gì so với việc JUnit tự động làm, tuy nhiên bạn có thể thêm các test cá nhân để chỉ chạy các
test nhất định nào đó hay là điều khiển thứ tự thực thi


import junit.framework.*;

public class TestGame extends TestCase {
private Game game;
private Ship fighter;

public TestGame(String name) {
super(name);
}
…
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new TestGame("testCreateFighter"));
suite.addTest(new TestGame("testSameFighters"));
return suite;
}
}

Bạn có thể kết hợp nhiều suite vào các suite khác. Bạn có ra ở đây đã sử dụng mẩu Composite. Ví dụ:
public static Test suite() {
TestSuite suite = new TestSuite(TestGame.class);
suite.addTest(new TestSuite(TestPerson.class));


JUnit testing                                                                                  Page 10
Testing with JUnit
return suite;
}


Bây giờ khi bạn chạy test case này, bạn sẽ chạy tất cả các test bên trong lớp TestGame và lớp
TestPeson




7) Chạ y các test lặp đi lặ p lạ i
Trong một vài trường hợp, chúng ta muốn chạy một test nào đó lặp đi lặp lại nhiều lần để đo hiệu suất
hay phân tích các vấn đề trục trặc. JUnit cung cấp cho chúng ta lớp junit.extension.RepeatedTest để làm
được điều này. Lớp RepeatedTest giúp chúng ta thực hiện điều này một cách dễ dàng


public static Test suite() {
//Chạy toàn bộ test suite 10 lần
return new RepeatedTest(new TestSuite(TestGame.class), 10);
}


Tham số đầu tiên của RepeatedTest là một Test cần chạy, tham số thứ 2 là số lần lặp lại. Vì TestSuite
cài đặt interface Test nên chúng ta có thể lặp lại toàn bộ test như trên. Tiếp theo là ví dụ mô tả cách xây
dựng một test suite mà trong đó các test khác nhau được lặp đi lặp lại khác nhau:

public static Test suite() {
TestSuite suite = new TestSuite();
//Lặp lại testCreateFighter 100 lần
suite.addTest(new RepeatedTest(new TestGame("testCreateFighter"), 100));
//Chạy testSameFighters 1 lần
suite.addTest(new TestGame("testSameFighters"));
//Lặp lại testGameInitialState 20 lần
suite.addTest(new RepeatedTest(new TestGame("testGameInitialState"), 20);
return suite;
}

8) Test các exception
Phần tiếp đến chúng ta sẽ xem xét đến một phần test cũng quan trọng không kém trong lập trình là test
các exception. Chúng ta sử dụng cặp từ khóa try/catch để bắt các exception như mong đợi, chúng ta sẽ
gọi phương thức fail() khi exception chúng ta mong đợi không xảy ra. Trong ví dụ sau, constructor của
lớp Person nên tung ra IllegalArgumentException khi cả 2 tham số của nó đều mang giá trị null. Test sẽ
thất bại nếu nó không tung ra exception.
public void testPassNullsToConstructor() {
try {
Person p = new Person(null, null);
fail("Expected IllegalArgumentException because both args are null");
}
catch (IllegalArgumentException expected) {
//Bỏ qua phần này không xử lý vì có nghĩa là test được chấp nhận
}
}




JUnit testing                                                                                       Page 11
Testing with JUnit

Nói chung bạn chỉ nên sử dụng kỹ thuật này khi bạn mong đợi một exception xảy ra. Đối với các điều
kiện lỗi khác bạn nên để exception chuyển sang cho JUnit. Khi đó JUnit sẽ bắt lấy và tường trình 1 lỗi
test.




9) Giới thiệ u một số công cụ, thư viện nguồn mở hỗ trợ việ c test phần
mề m
a) Cactus
Cactus là một framework unit testing nguồn mở dùng để test cho các đoạn mã phía bên server của Java.
Đặc biệt là Cactus cho phép bạn test Servlet, JSP, và Servlet filter. Cactus thừa kế từ JUnit để cung cấp
3 lớp con của lớp junit.framework.TestCase là các lớp:
• org.apache.cactus.ServletTestCase
• org.apache.cactus.JspTestCase
• org.apache.cactus.FilterTestCase
Mỗi test case của Cactus cung cấp 1 chức năng đặc biệt. Cactus test thực thi trên cả client và server. Khi
sử dụng Cactus bạn chỉ cần tạo một lớp thừa kế từ 1 trong 3 lớp trên. Sau đó Cactus sẽ tạo ra và chạy 2
thể hiện của test case. Một chạy trên JVM ở phía client, cái còn lại chạy bên trong JVM của môi trường
chạy servlet (servlet container) phía server. Bên client phía client cho phép HTTP headers và các tham
số HTTP được thêm vào các yêu cầu đi ra. Bên phía server gọi thực thi các phương thức bên trong
servlet của bạn để thực hiện bất kỳ xác nhận nào, và sau đó sẽ gởi phản hồi ngược trở lại cho phía
client. Tíếp đến bên phía client xác nhận phản hồi từ bên server gởi về có chứa thông tin mong muốn
hay không.
Bạn có thể download Cactus từ địa chỉ http://jakarta.apache.org/cactus

b) HttpUnit
HttpUnit là một thư viện nguồn mở của Java được dùng để tương tác với các server HTTP. Với HttpUnit,
chương trình Java của bạn có thể truy xuất trực tiếp đến server mà không cần thiết phải sử dụng đến
trình duyệt.
HttpUnit cung cấp các API để phân tích HTML, nhận thông tin của biểu mẫu trang web, theo dõi các siêu
liên kết, thiết lập cookie và thực hiện các tác vụ khác có liên quan đến trình duyệt web.
Ngoài ra nó cũng gồm cả một thư viện để thao tác trực tiếp đến servlet, đôi khi không cần thiết phải khởi
động web server
Thông thường chúng ta sử dụng kết hợp HttpUnit và JUnit để viết các tét. JUnit định nghĩa các
framework dùng để kiểm tra, và các phương thức testXXX() của bạn sẽ sử dụng các hàm API của thư
viện HttpUnit để truy cập và kiểm tra trang web
Bạn có thể download HttpUnit từ địa chỉ http://www.httpunit.org

c) NUnit
NUnit là một framework dành cho việc testing unit trong tất cả các ngôn ngữ .NET. Khởi đầu nó cũng
được bắt đầu từ JUnit, nó là một công cụ hỗ trợ việc unit testing cho Microsoft.NET. Nó được viết hoàn
toàn bằng C#




JUnit testing                                                                                     Page 12
Testing with JUnit


10) Tham khả o
  http://www.junit.org
  Java eXtreme Programming Cookbook – Eric M. Burke & Brian M. Coyner, O’Reilly
  Test Driven Development By Example – Addison Wesley




JUnit testing                                                                     Page 13

Mais conteúdo relacionado

Mais procurados

Ứng dụng công cụ test tự động kiểm thử website
Ứng dụng công cụ test tự động kiểm thử websiteỨng dụng công cụ test tự động kiểm thử website
Ứng dụng công cụ test tự động kiểm thử website
Dotnet Open Group
 
Bai05 thiet ketestcase-k-trpm@softtesting-nntu
Bai05 thiet ketestcase-k-trpm@softtesting-nntuBai05 thiet ketestcase-k-trpm@softtesting-nntu
Bai05 thiet ketestcase-k-trpm@softtesting-nntu
Van Pham
 

Mais procurados (20)

6 câu hỏi phỏng vấn tester thông dụng năm 2021
6 câu hỏi phỏng vấn tester thông dụng năm 20216 câu hỏi phỏng vấn tester thông dụng năm 2021
6 câu hỏi phỏng vấn tester thông dụng năm 2021
 
Unit Test with test JUNIT
Unit Test with test JUNIT Unit Test with test JUNIT
Unit Test with test JUNIT
 
Luận văn: Kiểm thử tự động tương tác giao diện người dùng, 9đ
Luận văn: Kiểm thử tự động tương tác giao diện người dùng, 9đLuận văn: Kiểm thử tự động tương tác giao diện người dùng, 9đ
Luận văn: Kiểm thử tự động tương tác giao diện người dùng, 9đ
 
Ứng dụng công cụ test tự động kiểm thử website
Ứng dụng công cụ test tự động kiểm thử websiteỨng dụng công cụ test tự động kiểm thử website
Ứng dụng công cụ test tự động kiểm thử website
 
Kiem thu
Kiem thuKiem thu
Kiem thu
 
Cac kythuatktpm
Cac kythuatktpmCac kythuatktpm
Cac kythuatktpm
 
TÌM HIỂU CÁC KỸ THUẬT KIỂM THỬ PHẦN MỀM
TÌM HIỂU CÁC KỸ THUẬT KIỂM THỬ PHẦN MỀMTÌM HIỂU CÁC KỸ THUẬT KIỂM THỬ PHẦN MỀM
TÌM HIỂU CÁC KỸ THUẬT KIỂM THỬ PHẦN MỀM
 
Đồ Án Tìm Hiểu Phần Mềm Loadrunner Kiểm Tra Hiệu Năng Website
Đồ Án Tìm Hiểu Phần Mềm Loadrunner Kiểm Tra Hiệu Năng Website Đồ Án Tìm Hiểu Phần Mềm Loadrunner Kiểm Tra Hiệu Năng Website
Đồ Án Tìm Hiểu Phần Mềm Loadrunner Kiểm Tra Hiệu Năng Website
 
2014/07/07 Software Testing - Truong Anh Hoang
2014/07/07 Software Testing - Truong Anh Hoang 2014/07/07 Software Testing - Truong Anh Hoang
2014/07/07 Software Testing - Truong Anh Hoang
 
Báo cáo môn đảm bảo chất lượng phần mềm
Báo cáo môn đảm bảo chất lượng phần mềmBáo cáo môn đảm bảo chất lượng phần mềm
Báo cáo môn đảm bảo chất lượng phần mềm
 
Slide đồ án kiểm thử PM
Slide đồ án kiểm thử PMSlide đồ án kiểm thử PM
Slide đồ án kiểm thử PM
 
01 tester training - overview
01  tester training - overview01  tester training - overview
01 tester training - overview
 
[Seminar] Hướng dẫn viết test case
[Seminar] Hướng dẫn viết test case[Seminar] Hướng dẫn viết test case
[Seminar] Hướng dẫn viết test case
 
TÌM HIỂU CÁC KỸ THUẬT KIỂM THỬ PHẦN MỀM
TÌM HIỂU CÁC KỸ THUẬT KIỂM THỬ PHẦN MỀMTÌM HIỂU CÁC KỸ THUẬT KIỂM THỬ PHẦN MỀM
TÌM HIỂU CÁC KỸ THUẬT KIỂM THỬ PHẦN MỀM
 
Tìm Hiểu Các Kỹ Thuật Kiểm Thử Phần Mềm và Một Số Ứng Dụng Trong Thực Tế
Tìm Hiểu Các Kỹ Thuật Kiểm Thử Phần Mềm và Một Số Ứng Dụng Trong Thực Tế Tìm Hiểu Các Kỹ Thuật Kiểm Thử Phần Mềm và Một Số Ứng Dụng Trong Thực Tế
Tìm Hiểu Các Kỹ Thuật Kiểm Thử Phần Mềm và Một Số Ứng Dụng Trong Thực Tế
 
Kiem thu
Kiem thuKiem thu
Kiem thu
 
Bai05 thiet ketestcase-k-trpm@softtesting-nntu
Bai05 thiet ketestcase-k-trpm@softtesting-nntuBai05 thiet ketestcase-k-trpm@softtesting-nntu
Bai05 thiet ketestcase-k-trpm@softtesting-nntu
 
Kiểm thử phần mềm
Kiểm thử phần mềm Kiểm thử phần mềm
Kiểm thử phần mềm
 
Nghiên cứu chuẩn ISO/IEC 9126 trong đánh giá chất lượng phần mềm
Nghiên cứu chuẩn ISO/IEC 9126 trong đánh giá chất lượng phần mềmNghiên cứu chuẩn ISO/IEC 9126 trong đánh giá chất lượng phần mềm
Nghiên cứu chuẩn ISO/IEC 9126 trong đánh giá chất lượng phần mềm
 
TDD (Test Driven Development)
TDD (Test Driven Development)TDD (Test Driven Development)
TDD (Test Driven Development)
 

Semelhante a Adp junit

Automation Testing & TDD
Automation Testing & TDDAutomation Testing & TDD
Automation Testing & TDD
Nhật Nguyễn Khắc
 
Android Nâng cao-Bài 6-Multi theme-adb tool-jUnit
Android Nâng cao-Bài 6-Multi theme-adb tool-jUnitAndroid Nâng cao-Bài 6-Multi theme-adb tool-jUnit
Android Nâng cao-Bài 6-Multi theme-adb tool-jUnit
Phuoc Nguyen
 

Semelhante a Adp junit (20)

Unit Test
Unit TestUnit Test
Unit Test
 
Luận văn: Các kỹ thuật kiểm thử đột biến và ứng dụng, HAY, 9đ
Luận văn: Các kỹ thuật kiểm thử đột biến và ứng dụng, HAY, 9đLuận văn: Các kỹ thuật kiểm thử đột biến và ứng dụng, HAY, 9đ
Luận văn: Các kỹ thuật kiểm thử đột biến và ứng dụng, HAY, 9đ
 
Nunit framework for .NET application
Nunit framework for .NET applicationNunit framework for .NET application
Nunit framework for .NET application
 
Luận văn thạc sĩ
Luận văn thạc sĩLuận văn thạc sĩ
Luận văn thạc sĩ
 
CHUONG 2.pdf
CHUONG 2.pdfCHUONG 2.pdf
CHUONG 2.pdf
 
Tailieu.vncty.com t ke-testcase
Tailieu.vncty.com   t ke-testcaseTailieu.vncty.com   t ke-testcase
Tailieu.vncty.com t ke-testcase
 
chuong 5
chuong 5chuong 5
chuong 5
 
bao_cao_apache_jmeter.pdf
bao_cao_apache_jmeter.pdfbao_cao_apache_jmeter.pdf
bao_cao_apache_jmeter.pdf
 
Đề tài: Công cụ sinh dữ liệu thử tự động cho chương trình Java
Đề tài: Công cụ sinh dữ liệu thử tự động cho chương trình JavaĐề tài: Công cụ sinh dữ liệu thử tự động cho chương trình Java
Đề tài: Công cụ sinh dữ liệu thử tự động cho chương trình Java
 
chương03. kiểm thử hộp trắng.pdf
chương03. kiểm thử hộp trắng.pdfchương03. kiểm thử hộp trắng.pdf
chương03. kiểm thử hộp trắng.pdf
 
Oop 7
Oop 7Oop 7
Oop 7
 
Luận văn: Xây dựng công cụ hỗ trợ sinh ca kiểm thử cặp, 9đ
Luận văn: Xây dựng công cụ hỗ trợ sinh ca kiểm thử cặp, 9đLuận văn: Xây dựng công cụ hỗ trợ sinh ca kiểm thử cặp, 9đ
Luận văn: Xây dựng công cụ hỗ trợ sinh ca kiểm thử cặp, 9đ
 
Luận văn: Nghiên cứu tính toán sức chịu tải cọc khoan nhồi theo tiêu chuẩn TC...
Luận văn: Nghiên cứu tính toán sức chịu tải cọc khoan nhồi theo tiêu chuẩn TC...Luận văn: Nghiên cứu tính toán sức chịu tải cọc khoan nhồi theo tiêu chuẩn TC...
Luận văn: Nghiên cứu tính toán sức chịu tải cọc khoan nhồi theo tiêu chuẩn TC...
 
Jmeter tool
Jmeter toolJmeter tool
Jmeter tool
 
Automation Testing & TDD
Automation Testing & TDDAutomation Testing & TDD
Automation Testing & TDD
 
Selenium ide
Selenium ide Selenium ide
Selenium ide
 
Luận văn: Phương pháp sinh dữ liệu kiểm thử tự động từ biểu đồ
Luận văn: Phương pháp sinh dữ liệu kiểm thử tự động từ biểu đồLuận văn: Phương pháp sinh dữ liệu kiểm thử tự động từ biểu đồ
Luận văn: Phương pháp sinh dữ liệu kiểm thử tự động từ biểu đồ
 
Luận văn thạc sĩ
Luận văn thạc sĩLuận văn thạc sĩ
Luận văn thạc sĩ
 
Android Nâng cao-Bài 6-Multi theme-adb tool-jUnit
Android Nâng cao-Bài 6-Multi theme-adb tool-jUnitAndroid Nâng cao-Bài 6-Multi theme-adb tool-jUnit
Android Nâng cao-Bài 6-Multi theme-adb tool-jUnit
 
Luận văn: Công cụ để hỗ trợ kiểm thử phần mềm android, 9đ
Luận văn: Công cụ để hỗ trợ kiểm thử phần mềm android, 9đLuận văn: Công cụ để hỗ trợ kiểm thử phần mềm android, 9đ
Luận văn: Công cụ để hỗ trợ kiểm thử phần mềm android, 9đ
 

Adp junit

  • 1. Testing with JUnit TRƯỜNG ĐẠI HỌC DUY TÂN KHOA ĐÀO TẠO QUỐC TẾ »»»»«««« KIỂM THỬPHẦ MỀM VỚ N I JUnit APPLICATION DEVELOPMENT PRACTICES GVHD: Thầy Võ Văn Lường Thành viên: Mai Văn Minh Huỳnh Ngọc Khoa Hoàng Duy Hưng Trần Thành Tâm JUnit testing Page 1
  • 2. Testing with JUnit Mục lục 1) Giới thiệu .................................................................................................................................................. 3 2) Ví dụ test các chức năng của một lớp ....................................................................................................... 3 4) Thế nào là một unit test tốt ....................................................................................................................... 6 5) Set Up và Tear Down ............................................................................................................................... 7 6) Tổ chức các test vào các test suite .......................................................................................................... 10 7) Chạy các test lặp đi lặp lại ...................................................................................................................... 11 9) Giới thiệu một số công cụ, thư viện nguồn mở hỗ trợ việc test phần mềm ............................................ 12 a) Cactus ................................................................................................................................................. 12 b) HttpUnit .............................................................................................................................................. 12 c) NUnit .................................................................................................................................................. 12 10) Tham khảo ............................................................................................................................................ 13 JUnit testing Page 2
  • 3. Testing with JUnit KIỂM THỬ PHẦN MỀM VỚI JUnit JUnit là một framework đơn giản dùng cho việc tạo các unit testing tự động, và chạy các test có thể lặp đi lặp lại. Nó chỉ là một phần của họ kiến trúc xUnit cho việc tạo các unit testing. JUnit là một chuẩn trên thực tế cho unit testing trong Java. JUnit về nguồn gốc được viết bởi 2 tác giả Erich Gamma và Kent Beck 1) Giới thiệ u JUnit có thể được tải xuống từ địa chỉ http://www.junit.org. JUnit có những đặc điểm đáng lưu tâm như sau: • Xác nhận (assert) việc kiểm tra kết quả được mong đợi • Các Test Suite cho phép chúng ta dễ dàng tổ chức và chạy các test • Hỗ trợ giao diện đồ họa và giao diện dòng lệnh Các test case của JUnit là các lớp của Java, các lớp này bao gồm một hay nhiều các phương thức unit testing, và những test này lại được nhóm thành các Test Suite. Mỗi phương thức test trong JUnit phải được thực thi nhanh chóng. Tốc độ là điều tối quan trọng vì càng nhiều test được viết và tích hợp vào bên trong quá trình xây dựng phần mềm, cần phải tốn nhiều thời gian hơn cho việc chạy toàn bộ Test Suite. Các lập trình viên không muốn bị ngắt quãng trong một khoãng thời gian dài trong khi các test chạy, vì thế các test mà chạy càng lâu thì sẽ có nhiều khả năng là các lập trình viên sẽ bỏ qua bước cũng không kém phần quan trọng này. Các test trong JUnit có thể là các test được chấp nhận hay thất bại, các test này được thiết kế để khi chạy mà không cần có sự can thiệp của con người. Từ những thiết kế như thế, bạn có thể thêm các bộ test vào quá trình tích hợp và xây dựng phần mềm một cách liên tục và để cho các test chạy một cách tự động 2) Ví dụ test các chức năng của một lớp Bạn muốn viết các unit test với JUnit. Việc đầu tiên bạn phải tạo một lớp con thừa kế từ lớp junit.framework.TestCase. Mỗi unit test được đại diện bởi một phương thức testXXX() bên trong lớp con của lớp TestCase Ta có một lớp Person như sau: public class Person { private String firstName; private String lastName; public Person(String firstName, String lastName) { if (firstName == null && lastName == null) { JUnit testing Page 3
  • 4. Testing with JUnit throw new IllegalArgumentException("Both names cannot be null"); } this.firstName = firstName; this.lastName = lastName; } public String getFullName() { String first = (this.firstName != null) ? this.firstName : "?"; String last = (this.lastName != null) ? this.lastName : "?"; return first + last; } public String getFirstName() { return this.firstName; } public String getLastName() { return this.lastName; } } Sau đó ta sẽ viết một test case đơn giản để test một số phương thức của lớp trên import junit.framework.TestCase; public class TestPerson extends TestCase { public TestPerson(String name) { super(name); } /** * Xac nhan rang name duoc the hien dung dinh dang */ public void testGetFullName() { Person p = new Person("Aidan", "Burke"); assertEquals("Aidan Burke", p.getFullName()); } /** * Xac nhan rang nulls da duoc xu ly chinh xac */ public void testNullsInName() { Person p = new Person(null, "Burke"); assertEquals("? Burke", p.getFullName()); p = new Person("Tanner", null); assertEquals("Tanner ?", p.getFullName()); } } Lưu ý: mỗi unit test là một phương thức public và không có tham số được bắt đầu bằng tiếp đầu ngữ test. Nếu bạn không tuân theo quy tắc đặt tên này thì JUnit sẽ không xác định được các phương thức test một các tự động. JUnit testing Page 4
  • 5. Testing with JUnit Để biên dịch TestPerson, chúng ta phải khai báo gói thư viện junit trong biến đường môi trường classpath set classpath=%classpath%;.;junit.jar javac TestPerson Để chạy một JUnit TestCase, ta có 2 cách • Chạy với môi trường text, các bạn gõ lệnh java junit.textui.TestRunner TestPerson Sau khi chạy sẽ có kết quả như hình trên. • Chạy với môi trường đồ họa java junit.swingui.TestRunner TestPerson Chúng ta có thể chạy trực tiếp các TestCase mà không muốn kích hoạt một trong các test runner của JUnit. Chúng ta sẽ thêm phương thức main() vào test case. Ví dụ public class TestGame extends TestCase { … public static void main(String []args) { junit.textui.TestRunner.run(new TestSuite(TestGame.class)) } } 3) Các phương thức assertXXX() Các phương thức assertXXX() được dùng để kiểm tra các điều kiện khác nhau. junit.framework.TestCase, lớp cha cho tất cả các test case, thừa kế từ lớp junit.framework.Assert. Lớp này định nghĩa khá nhiều các phương thức assertXXX(). Các phương thức test hoạt động bằng cách gọi những phương thức này. Bảng sau mô tả các phương thức assertXXX() khác nhau có trong lớp junit.framework.Assert. Phương thức Mô tả assertEquals() So sánh 2 giá trị để kiểm tra bằng nhau. Test sẽ được chấp nhận nếu các giá trị bằng nhau assertFalse() Đánh giá biểu thức luận lý. Test sẽ được chấp nhận nếu biểu thức sai assertNotNull() So sánh tham chiếu của một đối tượng với null. Test sẽ được chấp nhận nếu tham chiếu đối tượng khác null assertNotSame() So sánh địa chỉ vùng nhớ của 2 tham chiếu đối tượng bằng cách sử dụng toán tử ==. Test sẽ được chấp nhận nếu cả 2 đều tham chiếu đến các đối tượng khác nhau assertNull() So sánh tham chiếu của một đối tượng với giá trị null. Test sẽ được chấp nhận nếu tham chiếu là null assertSame() So sánh địa chỉ vùng nhớ của 2 tham chiếu đối tượng bằng cách sử dụng toán tử ==. Test sẽ được chấp nhận nếu cả 2 đều tham chiếu đến cùng một đối tượng assertTrue() Đánh giá một biểu thức luận lý. Test sẽ được chấp nhận nếu biểu thức đúng fail() Phương thức này làm cho test hiện hành thất bại, phương thức này thường được sử dụng khi xử lý các biệt lệ JUnit testing Page 5
  • 6. Testing with JUnit Mặc dù bạn có thể chỉ cần sử dụng phương thức assertTrue() cho gần như hầu hết các test, tuy nhiên thì việc sử dụng một trong các phương thức assertXXX() cụ thể sẽ làm cho các test của bạn dễ hiểu hơn và cung cấp các thông điệp thất bại rõ ràng hơn. Tất cả các phương thức của bảng trên đều nhận vào một String không bắt buộc làm tham số đầu tiên. Khi được xác định, tham số này cung cấp một thông điệp mô tả test thất bại. Ví dụ: assertEquals(employeeA, employeeB); assertEquals(“Employees should be equal after the clone() operation.”, employeeA, employeeB). Phiên bản thứ 2 được ưa thích hơn vì nó mô tả tại sao test thất bại, điều này sẽ giúp cho việc sửa lỗi được dễ dàng hơn 4) Thế nào là một unit test tốt Mỗi unit test chỉ nên kiểm tra phần cụ thể của một chức năng nào đó. Chúng ta không nên kết hợp nhiều test không liên quan với nhau lại vào trong một phương thức testXXX() Ta có một lớp Game như sau public class Game { private Map ships = new HashMap(); public Game() throws BadGameException { } public void shutdown() { // dummy method } public synchronized Ship createFighter(String fighterId) { Ship s = (Ship) this.ships.get(fighterId); if (s == null) { s = new Ship(fighterId); this.ships.put(fighterId, s); } return s; } public boolean isPlaying() { return false; } } public class BadGameException extends Exception { public BadGameException(String s) { super(s); } } Sau đó ta viết một đoạn test sau đây: public void testGame() throws BadGameException{ Game game = new Game(); JUnit testing Page 6
  • 7. Testing with JUnit Ship fighter = game.createFighter(“001”); assertEquals("Fighter did not have the correct identifier", "001", this.fighter.getId()); Ship fighter2 = this.game.createFighter("001"); assertSame("createFighter with same id should return same object", fighter, fighter2); assertTrue("A new game should not be started yet", !this.game.isPlaying()); } Đây là một thiết kế không tốt vì mỗi phương thức assertXXX() đang kiểm tra phần không liên quan của chức năng. Nếu phương thức assertEquals thất bại, phần còn lại của test sẽ không được thi hành. Khi xảy ra điều này thì chúng ta sẽ không biết các test khác có đúng chức năng hay không Tiếp theo chúng ta sẽ sửa test trên lại để kiểm tra các khía cạnh khác nhau của trò chơi một cách độc lập. public void testCreateFighter() { System.out.println("Begin testCreateFigher()"); assertEquals("Fighter did not have the correct identifier", "001", this.fighter.getId()); System.out.println("End testCreateFighter()"); } public void testSameFighters() { System.out.println("Begin testSameFighters()"); Ship fighter2 = this.game.createFighter("001"); assertSame("createFighter with same id should return same object", this.fighter, fighter2); System.out.println("End testSameFighters()"); } public void testGameInitialState() { System.out.println("Begin testGameInitialState()"); assertTrue("A new game should not be started yet", !this.game.isPlaying()); System.out.println("End testGameInitialState()"); } Với cách tiếp cận này, khi một test thất bại sẽ không làm cho các mệnh đề assertXXX() còn lại bị bỏ qua. Có thể bạn sẽ đặt ra câu hỏi có khi nào một phương thức test chứa nhiều hơn một các phương thức assertXXX() hay không? Câu trả lời là có. Nếu bạn cần kiểm tra một dãy các điều kiện và các test theo sau sẽ luôn thất bại nếu có một test đầu tiên thất bại, khi đó bạn có thể kết hợp nhiều phương thức assert vào trong một test 5) Set Up và Tear Down Hai phương thức setUp() và tearDown() là một phần của lớp junit.framework.TestCase Bằng cách sử dụng các phương thức setUp và tearDown. Khi sử dụng 2 phương thức setUp() và tearDown() sẽ giúp chúng ta tránh được việc trùng mã khi nhiều test cùng chia sẻ nhau ở phần khởi tạo và dọn dẹp các biến. JUnit tuân thủ theo một dãy có thứ tự các sự kiện khi chạy các test. Đầu tiên, nó tạo ra một thể hiện mới của test case ứng với mỗi phương thức test. Từ đó, nếu bạn có 5 phương thức test thì JUnit sẽ tạo ra 5 thể hiện của test case. Vì lý do đó, các biến thể hiện không thể được sử dụng để chia sẻ trạng thái giữa các phương thức test. Sau khi tạo xong tất cả các đối tượng test case, JUnit tuân theo các bước sau cho mỗi phương thức test: JUnit testing Page 7
  • 8. Testing with JUnit • Gọi phương thức setUp() của test case • Gọi phương thức test • Gọi phương thức tearDown() của test case Quá trình này được lặp lại đối với mỗi phương thức test trong test case. Sau đây chúng ta sẽ xem xét 1 ví dụ public class Ship { private String id; public Ship(String id) { this.id = id; } public String getId() { return this.id; } } public class TestGame extends TestCase { private Game game; private Ship fighter; public void setUp() throws BadGameException { this.game = new Game(); this.fighter = this.game.createFighter("001"); } public void tearDown() { this.game.shutdown(); } public void testCreateFighter() { System.out.println("Begin testCreateFigher()"); assertEquals("Fighter did not have the correct identifier", "001", this.fighter.getId()); System.out.println("End testCreateFighter()"); } public void testSameFighters() { System.out.println("Begin testSameFighters()"); Ship fighter2 = this.game.createFighter("001"); assertSame("createFighter with same id should return same object", this.fighter, fighter2); System.out.println("End testSameFighters()"); } public void testGameInitialState() { System.out.println("Begin testGameInitialState()"); assertTrue("A new game should not be started yet", !this.game.isPlaying()); System.out.println("End testGameInitialState()"); } } Thông thường bạn có thể bỏ qua phương thức tearDown() vì mỗi unit test riêng không phải là những tiến trình chạy tốn nhiều thời gian, và các đối tượng được thu dọn khi JVM thoát. tearDown() có thể được sử JUnit testing Page 8
  • 9. Testing with JUnit dụng khi test của bạn thực hiện những thao tác như mở kết nối đến cơ sở dữ liệu hay sử dụng các loại tài nguyên khác của hệ thống và bạn cần phải dọn dẹp ngay lập tức. Nếu bạn chạy một bộ bao gồm một số lượng lớn các unit test, thì khi bạn trỏ tham chiếu của các đối tượng đến null bên trong thân phương thức tearDown() sẽ giúp cho bộ dọn rác lấy lại bộ nhớ khi các test khác chạy Đôi khi bạn muốn chạy vài đoạn mã khởi tạo chỉ một lần, sau đó chạy các phương thức test, và bạn chỉ muốn chạy các đoạn mã dọn dẹp chỉ sau khi tất cả test kết thúc. Ở phần trên, JUnit gọi phương thức setUp() trước mỗi test và gọi tearDown() sau khi mỗi test kết thúc, vì thế để làm được điều như trên, chúng ta sẽ sử dụng lớp junit.extension.TestSetup để đạt được yêu cầu trên. Ví dụ sau sẽ minh họa việc sử dụng lớp trên import junit.extensions.TestSetup; import junit.framework.*; public class TestPerson extends TestCase { public TestPerson(String name) { super(name); } public void testGetFullName() { Person p = new Person("Aidan", "Burke"); assertEquals("Aidan Burke", p.getFullName()); } public void testNullsInName() { Person p = new Person(null, "Burke"); assertEquals("? Burke", p.getFullName()); p = new Person("Tanner", null); assertEquals("Tanner ?", p.getFullName()); } public static Test suite() { TestSetup setup = new TestSetup(new TestSuite(TestPerson.class)) { protected void setUp() throws Exception { //Thực hiện các đoạn mã khởi tạo một lần ở đây } protected void tearDown() throws Exception { //Thực hiện các đoạn mã dọn dẹp ở đây } }; return setup; } } TestSetup là một lớp thừa kế từ lớp junit.extension.TestDecorator, Lớp TestDecorator là lớp cơ sở cho việc định nghĩa các test biến thể. Lý do chính để mở rộng TestDecorator là để có được khả năng thực thi đoạn mã trước và sau khi một test chạy. Các phương thức setUp() và tearDown() của lớp TestSetup được gọi trước và sau khi bất kỳ Test nào được truyền vào constructor, Trong ví dụ trên chúng ta đã truyền một tham số có kiểu TestSuite vào constructor của lớp TestSetup TestSetup setup = new TestSetup(new TestSuite(TestPerson.class)) { Điều này có nghĩa là 2 phương thức setUp() được gọi chỉ một lần trước toàn bộ bộ test và tearDown() được gọi chỉ một lần sau khi các test trong bộ test kết thúc. JUnit testing Page 9
  • 10. Testing with JUnit Chú ý: các phương thức setUp() và tearDown() bên trong lớp TestPerson vẫn được thực thi trước và sau mỗi phương thức test bên trong lớp TestPerson. 6) Tổ chức các test vào các test suite Thông thường JUnit tự động tạo ra các Test Suite ứng với mỗi Test Case. Tuy nhiên bạn muốn tự tạo các Test Suite của riêng mình bằng cách tổ chức các Test vào Test Suite. JUnit cung cấp lớp junit.framework.TestSuite hỗ trợ việc tạo các Test Suite Khi bạn sử dụng giao diện text hay graphic, JUnit sẽ tìm phương thức sau trong test case của bạn public static Test suite() { … } Nếu không thấy phương thức trên, JUnit sẽ sử dụng kỹ thuật reflection để tự động xác định tất cả các phương thức testXXX() trong test case của bạn, rồi thêm chúng vào một test suite. Sau đó nó sẽ chạy tất cả các test trong suite này. Bạn có thể tạo ra bản sao hành vi của phương thức suite() mặc định như sau public class TestGame extends TestCase{ … public static Test suite() { return new TestSuite(TestGame.class); } } Bằng cách truyền đối tượng TestGame.class vào construtor TestSuite, bạn đang thông báo cho JUnit biết để xác định tất cả các phương thức testXXX() trong lớp đó và thêm chúng vào suite. Đoạn mã trên không làm khác gì so với việc JUnit tự động làm, tuy nhiên bạn có thể thêm các test cá nhân để chỉ chạy các test nhất định nào đó hay là điều khiển thứ tự thực thi import junit.framework.*; public class TestGame extends TestCase { private Game game; private Ship fighter; public TestGame(String name) { super(name); } … public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(new TestGame("testCreateFighter")); suite.addTest(new TestGame("testSameFighters")); return suite; } } Bạn có thể kết hợp nhiều suite vào các suite khác. Bạn có ra ở đây đã sử dụng mẩu Composite. Ví dụ: public static Test suite() { TestSuite suite = new TestSuite(TestGame.class); suite.addTest(new TestSuite(TestPerson.class)); JUnit testing Page 10
  • 11. Testing with JUnit return suite; } Bây giờ khi bạn chạy test case này, bạn sẽ chạy tất cả các test bên trong lớp TestGame và lớp TestPeson 7) Chạ y các test lặp đi lặ p lạ i Trong một vài trường hợp, chúng ta muốn chạy một test nào đó lặp đi lặp lại nhiều lần để đo hiệu suất hay phân tích các vấn đề trục trặc. JUnit cung cấp cho chúng ta lớp junit.extension.RepeatedTest để làm được điều này. Lớp RepeatedTest giúp chúng ta thực hiện điều này một cách dễ dàng public static Test suite() { //Chạy toàn bộ test suite 10 lần return new RepeatedTest(new TestSuite(TestGame.class), 10); } Tham số đầu tiên của RepeatedTest là một Test cần chạy, tham số thứ 2 là số lần lặp lại. Vì TestSuite cài đặt interface Test nên chúng ta có thể lặp lại toàn bộ test như trên. Tiếp theo là ví dụ mô tả cách xây dựng một test suite mà trong đó các test khác nhau được lặp đi lặp lại khác nhau: public static Test suite() { TestSuite suite = new TestSuite(); //Lặp lại testCreateFighter 100 lần suite.addTest(new RepeatedTest(new TestGame("testCreateFighter"), 100)); //Chạy testSameFighters 1 lần suite.addTest(new TestGame("testSameFighters")); //Lặp lại testGameInitialState 20 lần suite.addTest(new RepeatedTest(new TestGame("testGameInitialState"), 20); return suite; } 8) Test các exception Phần tiếp đến chúng ta sẽ xem xét đến một phần test cũng quan trọng không kém trong lập trình là test các exception. Chúng ta sử dụng cặp từ khóa try/catch để bắt các exception như mong đợi, chúng ta sẽ gọi phương thức fail() khi exception chúng ta mong đợi không xảy ra. Trong ví dụ sau, constructor của lớp Person nên tung ra IllegalArgumentException khi cả 2 tham số của nó đều mang giá trị null. Test sẽ thất bại nếu nó không tung ra exception. public void testPassNullsToConstructor() { try { Person p = new Person(null, null); fail("Expected IllegalArgumentException because both args are null"); } catch (IllegalArgumentException expected) { //Bỏ qua phần này không xử lý vì có nghĩa là test được chấp nhận } } JUnit testing Page 11
  • 12. Testing with JUnit Nói chung bạn chỉ nên sử dụng kỹ thuật này khi bạn mong đợi một exception xảy ra. Đối với các điều kiện lỗi khác bạn nên để exception chuyển sang cho JUnit. Khi đó JUnit sẽ bắt lấy và tường trình 1 lỗi test. 9) Giới thiệ u một số công cụ, thư viện nguồn mở hỗ trợ việ c test phần mề m a) Cactus Cactus là một framework unit testing nguồn mở dùng để test cho các đoạn mã phía bên server của Java. Đặc biệt là Cactus cho phép bạn test Servlet, JSP, và Servlet filter. Cactus thừa kế từ JUnit để cung cấp 3 lớp con của lớp junit.framework.TestCase là các lớp: • org.apache.cactus.ServletTestCase • org.apache.cactus.JspTestCase • org.apache.cactus.FilterTestCase Mỗi test case của Cactus cung cấp 1 chức năng đặc biệt. Cactus test thực thi trên cả client và server. Khi sử dụng Cactus bạn chỉ cần tạo một lớp thừa kế từ 1 trong 3 lớp trên. Sau đó Cactus sẽ tạo ra và chạy 2 thể hiện của test case. Một chạy trên JVM ở phía client, cái còn lại chạy bên trong JVM của môi trường chạy servlet (servlet container) phía server. Bên client phía client cho phép HTTP headers và các tham số HTTP được thêm vào các yêu cầu đi ra. Bên phía server gọi thực thi các phương thức bên trong servlet của bạn để thực hiện bất kỳ xác nhận nào, và sau đó sẽ gởi phản hồi ngược trở lại cho phía client. Tíếp đến bên phía client xác nhận phản hồi từ bên server gởi về có chứa thông tin mong muốn hay không. Bạn có thể download Cactus từ địa chỉ http://jakarta.apache.org/cactus b) HttpUnit HttpUnit là một thư viện nguồn mở của Java được dùng để tương tác với các server HTTP. Với HttpUnit, chương trình Java của bạn có thể truy xuất trực tiếp đến server mà không cần thiết phải sử dụng đến trình duyệt. HttpUnit cung cấp các API để phân tích HTML, nhận thông tin của biểu mẫu trang web, theo dõi các siêu liên kết, thiết lập cookie và thực hiện các tác vụ khác có liên quan đến trình duyệt web. Ngoài ra nó cũng gồm cả một thư viện để thao tác trực tiếp đến servlet, đôi khi không cần thiết phải khởi động web server Thông thường chúng ta sử dụng kết hợp HttpUnit và JUnit để viết các tét. JUnit định nghĩa các framework dùng để kiểm tra, và các phương thức testXXX() của bạn sẽ sử dụng các hàm API của thư viện HttpUnit để truy cập và kiểm tra trang web Bạn có thể download HttpUnit từ địa chỉ http://www.httpunit.org c) NUnit NUnit là một framework dành cho việc testing unit trong tất cả các ngôn ngữ .NET. Khởi đầu nó cũng được bắt đầu từ JUnit, nó là một công cụ hỗ trợ việc unit testing cho Microsoft.NET. Nó được viết hoàn toàn bằng C# JUnit testing Page 12
  • 13. Testing with JUnit 10) Tham khả o http://www.junit.org Java eXtreme Programming Cookbook – Eric M. Burke & Brian M. Coyner, O’Reilly Test Driven Development By Example – Addison Wesley JUnit testing Page 13