2010-06-08 29 views
14

Vì vậy, tôi đã bắt đầu kiểm tra đơn vị bố trí cho các bit mã sau đây:Unit Tests Kiến trúc Câu hỏi

public interface MyInterface { 
    void MyInterfaceMethod1(); 
    void MyInterfaceMethod2(); 
} 

public class MyImplementation1 implements MyInterface { 
    void MyInterfaceMethod1() { 
    // do something 
    } 

    void MyInterfaceMethod2() { 
    // do something else 
    } 

    void SubRoutineP() { 
    // other functionality specific to this implementation 
    } 
} 

public class MyImplementation2 implements MyInterface { 
    void MyInterfaceMethod1() { 
    // do a 3rd thing 
    } 

    void MyInterfaceMethod2() { 
    // do something completely different 
    } 

    void SubRoutineQ() { 
    // other functionality specific to this implementation 
    } 
} 

với một số hiện thực và sự mong đợi của hơn sắp tới.

suy nghĩ ban đầu của tôi là tự cứu lấy mình kiểm tra lại viết đơn vị thời gian với một cái gì đó như thế này:

public abstract class MyInterfaceTester { 
    protected MyInterface m_object; 

    @Setup 
    public void setUp() { 
    m_object = getTestedImplementation(); 
    } 

    public abstract MyInterface getTestedImplementation(); 

    @Test 
    public void testMyInterfaceMethod1() { 
    // use m_object to run tests 
    } 

    @Test 
    public void testMyInterfaceMethod2() { 
    // use m_object to run tests 
    } 
} 

mà tôi sau đó có thể phân lớp một cách dễ dàng để kiểm tra việc thực hiện phương pháp bổ sung cụ thể như sau:

public class MyImplementation1Tester extends MyInterfaceTester { 
    public MyInterface getTestedImplementation() { 
    return new MyImplementation1(); 
    } 

    @Test 
    public void testSubRoutineP() { 
    // use m_object to run tests 
    } 
} 

và tương tự như vậy cho implmentation 2 trở đi.

Vì vậy, câu hỏi của tôi thực sự là: có lý do nào để không làm điều này không? JUnit dường như thích nó tốt, và nó phục vụ nhu cầu của tôi, nhưng tôi đã không thực sự nhìn thấy bất cứ điều gì giống như nó trong bất kỳ cuốn sách kiểm tra đơn vị và ví dụ tôi đã đọc.

Có một số phương pháp hay nhất mà tôi vô tình vi phạm không? Tôi có thể đặt mình lên vì đau khổ trên đường không? Có cách nào đơn giản hơn nhiều ra khỏi đó tôi đã không xem xét?

Cảm ơn bạn đã được trợ giúp.

Trả lời

17

có lý do nào để không làm điều này không?

No. Thực hiện. Các bài kiểm tra là các lớp cho chính xác là lý do này.

Tôi chưa từng thấy bất kỳ thứ gì giống như trong bất kỳ cuốn sách và ví dụ kiểm tra đơn vị nào mà tôi đã đọc.

Tiếp tục đọc. Giới thiệu không bao gồm điều này.

Có một số phương pháp hay nhất mà tôi vô tình vi phạm không?

số

Am tôi thiết lập bản thân mình lên cho đau lòng xuống đường?

số

Một số người cảm thấy lo lắng về "kiểm tra giòn". Bạn có thể tìm thấy một số câu hỏi ở đây tìm cách để làm cho nó như vậy một sự thay đổi cho phần mềm cũng không dẫn đến những thay đổi cho các bài kiểm tra. Về lâu dài, cố gắng để tạo ra các thử nghiệm "mạnh mẽ" là ngớ ngẩn. Bạn muốn các bài kiểm tra được viết sao cho mọi thay đổi nhỏ đối với mức hiển thị, giao diện của phần mềm yêu cầu viết lại bài kiểm tra.

Bạn muốn thử nghiệm để các thay đổi nội bộ vô hình không yêu cầu viết lại thử nghiệm.

Sử dụng các lớp và lớp con là trực giao với những cân nhắc đó.

Chỉ đơn giản là cách tốt hơn tôi chưa xem xét?

No. Hướng đối tượng điểm. Kiểm tra là một lớp học cho chính xác lý do này.

5

Trong khi tôi hỗ trợ SLott 100% tôi cũng sẽ xem xét JUnit parametrized kiểm tra thay vì hệ thống phân cấp lớp thử nghiệm cho việc này:

@RunWith(Parameterized.class) 
public class MyInterfaceTester { 
    private MyInterface m_object; 

    public void MyInterfaceTester(MyInterface object) { 
    m_object = object; 
    } 

    @Parameters 
    public static Collection<Object[]> data() { 
    List<Object[]> list = new ArrayList<Object[]>(); 

    list.add(new Object[]{new MyImplementation1()}); 
    list.add(new Object[]{new MyImplementation2()}); 

    return list; 
    } 

    @Test 
    public void testMyInterfaceMethod1() { 
    // use m_object to run tests 
    } 

    @Test 
    public void testMyInterfaceMethod2() { 
    // use m_object to run tests 
    } 
} 

Không cần trong hệ thống phân cấp lớp thử nghiệm: chỉ cần thêm thực hiện mới bằng cách thêm một yếu tố danh sách trong data phương pháp.

+0

Không biết về tính năng này, cảm ơn bạn đã chia sẻ. Thông tin thêm và ví dụ hoạt động tại đây: http://www.devx.com/Java/Article/31983/0/page/3 cho bất kỳ ai quan tâm. –

1

Nếu bạn thực sự làm cùng một thiết lập và xé nhỏ trong mỗi lớp thử nghiệm, thì điều bạn đang làm là tốt, nhưng tôi thấy rằng trong thực tế điều này gần như không bao giờ xảy ra. Trong thực tế, hầu hết thời gian có một phương pháp thiết lập mà instantiates kiểm tra dữ liệu, như bạn có ở đây, thậm chí không phải là những gì bạn muốn. Thay vào đó, trong một lớp thử nghiệm bạn thiết lập bất kỳ cơ sở hạ tầng nào, và mỗi phương thức thử nghiệm thiết lập cá thể riêng của một đối tượng để kiểm tra một số khía cạnh của nó.

+0

Đúng, di chuyển lệnh getTestedImplementation() đến dòng đầu tiên của mỗi bài kiểm tra, và đưa kết quả vào một địa phương có thể là những gì tôi muốn xuống dòng. Có lẽ an toàn hơn để bắt đầu với một đối tượng mới. Ngay bây giờ, mặc dù không có trạng thái trong các lớp thực hiện, vì vậy chúng chỉ cần được tạo một lần. –