2010-04-14 39 views
124

Tôi đã tìm thấy việc sử dụng thích hợp (hoặc ít nhất là tài liệu) của JUnit rất khó hiểu. Câu hỏi này phục vụ cho cả hai tham chiếu trong tương lai và là một câu hỏi thực tế.Sự nhầm lẫn JUnit: sử dụng 'extends TestCase' hoặc '@Test'?

Nếu tôi đã hiểu một cách chính xác, có hai phương pháp chính để tạo và chạy thử nghiệm JUnit:

Cách tiếp cận A (JUnit 3 kiểu): tạo ra một lớp mà kéo dài TestCase, và bắt đầu phương pháp thử với từ test. Khi chạy lớp như một JUnit Test (trong Eclipse), tất cả các phương thức bắt đầu với từ test sẽ tự động chạy.

import junit.framework.TestCase; 

public class DummyTestA extends TestCase { 

    public void testSum() { 
     int a = 5; 
     int b = 10; 
     int result = a + b; 
     assertEquals(15, result); 
    } 
} 

Cách tiếp cận B (JUnit 4 kiểu): tạo ra một lớp 'bình thường' và thêm vào trước một chú thích @Test đến phương pháp này. Lưu ý rằng bạn KHÔNG phải khởi động phương thức với từ test.

import org.junit.*; 
import static org.junit.Assert.*; 

public class DummyTestB { 

    @Test 
    public void Sum() { 
     int a = 5; 
     int b = 10; 
     int result = a + b; 
     assertEquals(15, result); 
    } 
} 

Trộn hai dường như không phải là ý tưởng hay, xem ví dụ: this stackoverflow question:

Bây giờ, câu hỏi của tôi (s):

  1. phương pháp ưa thích là gì, hoặc khi bạn sẽ sử dụng một thay vì của người kia?
  2. Phương pháp B cho phép thử nghiệm ngoại lệ bằng cách mở rộng chú thích @Test như trong @Test(expected = ArithmeticException.class). Nhưng làm thế nào để bạn kiểm tra ngoại lệ khi sử dụng phương pháp A?
  3. Khi sử dụng phương pháp A, bạn có thể nhóm một số các lớp học thử nghiệm trong một bộ kiểm tra như thế này:

    TestSuite suite = new TestSuite("All tests");
    suite.addTestSuite(DummyTestA.class);
    suite.addTestSuite(DummyTestAbis.class);

    Nhưng điều này không thể được sử dụng với phương pháp B (vì mỗi lớp con nên phân lớp TestCase). Cách thích hợp để nhóm các xét nghiệm cho phương pháp tiếp cận B là gì?

Edit: Tôi đã thêm các phiên bản JUnit cho cả hai phương pháp tiếp cận

Trả lời

96

Sự khác biệt là khá dễ dàng:

  • mở rộng TestCase là kiểm tra đơn vị cách được viết bằng JUnit 3 (tất nhiên nó vẫn được hỗ trợ trong JUnit 4)
  • sử dụng chú thích @Test là cách được giới thiệu bởi JUnit 4

Nói chung bạn nên chọn đường dẫn chú thích, trừ khi khả năng tương thích với JUnit 3 (và/hoặc phiên bản Java sớm hơn Java 5) là cần thiết. Cách mới có nhiều ưu điểm:

  • các @Test annotaton là rõ ràng hơn và dễ dàng hơn để hỗ trợ trong các công cụ (ví dụ thật dễ dàng để tìm kiếm tất cả các bài kiểm tra theo cách này)
  • Nhiều phương pháp có thể được chú thích với @Before/@BeforeClass@After/@AfterClass cung cấp linh hoạt hơn
  • Hỗ trợ cho @Rule annotations trên những thứ như ExpectedException
  • Hỗ trợ cho các @Ignored chú thích
  • Hỗ trợ cho vận động viên kiểm tra thay thế sử dụng @RunWith

Để kiểm tra cho trường hợp ngoại lệ mong chờ ở một JUnit 3 TestCase bạn phải làm cho văn bản rõ ràng.

public void testMyException() { 
    try { 
    objectUnderTest.myMethod(EVIL_ARGUMENT); 
    fail("myMethod did not throw an Exception!"); 
    } catch (MyException e) { 
    // ok! 
    // check for properties of exception here, if desired 
    } 
} 
+0

Câu trả lời hữu ích và kỹ lưỡng, nhưng tôi hoàn toàn không hiểu "kiểm tra thông báo ngoại lệ". Kiểm tra với một chuỗi hardcoded sẽ là một cơn ác mộng bảo trì. Bạn phải có nghĩa là "kiểm tra các thuộc tính của loại ngoại lệ cụ thể của bạn". – thSoft

+3

@thSoft: nó không thường xuyên mà nó được sử dụng, nhưng đôi khi tôi muốn đảm bảo rằng các phương pháp ngoại lệ đề cập đến lĩnh vực vi phạm, ví dụ. Sau đó, một 'assertTrue (e.getMessage(). Chứa (" foo ")) đơn giản có thể hữu ích. –

+1

Ngay cả trong JUnit4 đây là một thành ngữ quan trọng khi bạn phải kiểm tra tin nhắn hoặc một số tài sản khác của ngoại lệ (chẳng hạn như nguyên nhân). Phương thức 'expected' chỉ kiểm tra kiểu. – Yishai

21

Tôi có một sở thích cho JUnit 4 (phương pháp chú giải) vì tôi thấy nó linh hoạt hơn.

Nếu bạn muốn xây dựng bộ kiểm tra trong JUnit 4, bạn phải tạo ra một lớp nhóm tất cả các xét nghiệm như thế này:

import org.junit.runner.RunWith; 
import org.junit.runners.Suite; 
import org.junit.runners.Suite.SuiteClasses; 


@RunWith(Suite.class) 
@SuiteClasses({ 
    Test1.class, 
    Test2.class, 
    Test3.class, 
    Test4.class 
})public class TestSuite 
{ 
/* empty class */ 
} 
1
  1. Cách tiếp cận "ưa thích" sẽ được sử dụng chú thích đã được giới thiệu từ năm Junit 4. Họ làm rất nhiều thứ dễ dàng hơn (xem câu hỏi thứ hai của bạn)

  2. Bạn có thể sử dụng một đơn giản khối try/catch cho rằng:


public void testForException() { 
    try { 
     Integer.parseInt("just a string"); 
     fail("Exception should have been thrown"); 
    } catch (final Exception e) { 
     // expected 
    } 
} 
3

Bạn nên sử dụng JUnit 4. đó là tốt hơn.

Nhiều khung công tác đã bắt đầu ngừng hỗ trợ JUnit 3.8.

Đây là từ mùa xuân tài liệu 3.0 tham khảo:

[Cảnh báo] Legacy JUnit 3,8 lớp hệ thống phân cấp được phản

Nói chung, bạn nên luôn luôn cố gắng sử dụng phiên bản ổn định mới nhất của một khuôn khổ khi bạn bắt đầu một cái gì đó mới.

14

Có một phần chưa được trả lời cho câu hỏi của bạn và đó là "Cách thích hợp để nhóm các bài kiểm tra cho phương pháp tiếp cận B là gì?"

Câu trả lời chính thức là bạn chú thích một lớp học với @RunWith (Suite.lớp) và sau đó sử dụng chú thích @ Suite.SuiteClasses để liệt kê các lớp. Đây là cách các nhà phát triển JUnit làm điều đó (liệt kê mọi lớp trong một bộ thủ công). Trong nhiều cách, cách tiếp cận này là một sự cải tiến, trong đó nó tầm thường và trực quan để thêm trước các hành vi của suite và sau khi suite (chỉ cần thêm một phương thức @BeforeClass và @AfterClass vào lớp được chú thích với @RunWith - tốt hơn nhiều so với TestFixture cũ).

Tuy nhiên, nó có một bước lùi, trong chú thích đó không cho phép bạn tự động tạo danh sách các lớp và làm việc xung quanh vấn đề đó có chút xấu xí. Bạn phải phân lớp lớp Suite và tự động tạo mảng các lớp trong lớp con và chuyển nó vào bộ dựng Suite, nhưng đây là giải pháp không đầy đủ trong các lớp con khác của Suite (chẳng hạn như Danh mục) không hoạt động với nó không hỗ trợ bộ sưu tập lớp học Thử nghiệm động.

+1

+1 cho điều này. Sau khi bắt tay vào một nhiệm vụ để viết một giải pháp năng động để thêm các bài kiểm tra vào một TestSuite, tôi đã phải mở rộng TestCase trong mỗi Bài kiểm tra của tôi. Điều này lần lượt đã phá vỡ trước đó đơn vị làm việc thử nghiệm mà sử dụng JUnit4 chú thích để xác định ngoại lệ dự kiến. Tìm kiếm của tôi cho một cách tự động cư trú một Test Suite đã dẫn tôi đến chủ đề này, và cụ thể câu trả lời của bạn, mà tôi tin là một trong số ít những lý do mong muốn còn lại để tiếp tục với JUnit 3. – 8bitjunkie