2012-02-20 23 views
7

Tôi đang viết một loạt các lớp sưu tập trong C#, mỗi lớp trong số đó triển khai các giao diện tùy chỉnh tương tự. Có thể viết một bộ sưu tập các bài kiểm tra đơn vị cho một giao diện và tự động chạy tất cả trên một số triển khai khác nhau không? Tôi muốn tránh bất kỳ mã thử nghiệm trùng lặp nào cho từng triển khai.Tôi có thể triển khai một loạt các thử nghiệm có thể sử dụng lại để kiểm tra việc triển khai giao diện không?

Tôi sẵn sàng xem xét bất kỳ khung công tác (NUnit, v.v.) hoặc tiện ích Visual Studio nào để thực hiện việc này.


Đối với những ai muốn làm như vậy, tôi gửi giải pháp cụ thể của tôi, dựa tắt của avandeursen's accepted solution, như an answer.

+1

Đã thêm [lsp] (http://stackoverflow.com/questions/tagged/lsp) làm thẻ vì câu hỏi & câu trả lời áp dụng cho bất kỳ phân cấp lớp nào tuân thủ LSP. – avandeursen

Trả lời

6

Có, điều đó là có thể. Bí quyết là để cho hệ thống phân cấp thử nghiệm đơn vị của bạn tuân theo hệ thống phân cấp lớp của mã của bạn.

Giả sử bạn có giao diện Itf khi triển khai lớp học C1C2.

Trước tiên, bạn tạo một lớp thử nghiệm cho Itf (ItfTest). Để thực sự thực hiện bài kiểm tra, bạn cần phải tạo triển khai thử nghiệm giao diện Itf của mình.

Tất cả các thử nghiệm trong số ItfTest này sẽ chuyển sang bất kỳ việc triển khai nào Itf (!). Nếu không, thực hiện của bạn không phù hợp với các Liskov Substitution Principle (chữ "L" trong Martin SOLID nguyên tắc thiết kế OO)

Vì vậy, để tạo ra một trường hợp thử nghiệm cho C1, lớp C1Test bạn có thể mở rộng ItfTest. Tiện ích mở rộng của bạn sẽ thay thế việc tạo đối tượng giả bằng việc tạo đối tượng C1 (tiêm vào hoặc sử dụng GoF factory method). Theo cách này, tất cả các trường hợp ItfTest được áp dụng cho các trường hợp loại C1. Hơn nữa, lớp học C1Test của bạn có thể chứa các trường hợp kiểm tra bổ sung cụ thể cho C1.

Tương tự như vậy đối với C2. Và bạn có thể lặp lại mẹo cho các lớp và giao diện lồng nhau sâu hơn.

Tham khảo: Mẫu mã số Polymorphic Server Test của Binder, và McGregor's PACT - Kiến trúc song song để kiểm tra thành phần.

+1

Để tránh việc triển khai thực hiện giả, tôi đã khai báo lớp 'ItfTest' của tôi là trừu tượng và khai báo một' stub trừu tượng được bảo vệ Itf CreateInstance(); '. (Lưu ý rằng cả 'ItfTest' và' C1Test' cần phải có thuộc tính '[TestClass]'.) – dlras2

+1

Có, tôi cũng đã sử dụng phương thức factory cho nó vì nó đơn giản hơn. Tôi đã sử dụng phương pháp thử nghiệm này trong JUnit, nơi không có thuộc tính '[TestClass]', nhưng trong đó các chú thích '@ Test' trong các lớp bậc trên được kế thừa khiến các trường hợp kiểm tra siêu lớp được chạy lại trong các lớp con. Và: cảm ơn vì đã chỉnh sửa. – avandeursen

2

Bạn có thể sử dụng các thuộc tính [RowTest] trong MBUnit để thực hiện việc này. Ví dụ dưới đây cho thấy nơi bạn vượt qua phương pháp này một chuỗi để chỉ ra thực hiện giao diện lớp học mà bạn muốn nhanh chóng, và sau đó tạo ra lớp này thông qua phản ánh:

[RowTest] 
[Row("Class1")] 
[Row("Class2")] 
[Row("Class3")] 
public void TestMethod(string type) 
{ 
    IMyInterface foo = Activator.CreateInstance(Type.GetType(type)) as IMyInterface; 

    //Do tests on foo: 
} 

Trong [Row] thuộc tính, bạn có thể vượt qua bất kỳ số tùy ý các tham số đầu vào, chẳng hạn như các giá trị đầu vào để kiểm tra hoặc các giá trị dự kiến ​​sẽ được trả về bởi các lời gọi phương thức. Bạn sẽ cần thêm đối số của các kiểu tương ứng làm đối số đầu vào của phương thức thử nghiệm.

+0

Bạn có thể chỉnh sửa câu trả lời của mình để giải thích chính xác cách tôi sẽ thử nghiệm triển khai theo cách này không? Bạn dường như nói rằng mỗi bài kiểm tra đơn vị cần một câu lệnh chuyển đổi cho tất cả các triển khai, đó không phải là những gì tôi muốn. – dlras2

+0

Bạn không cần sử dụng câu lệnh chuyển đổi nếu bạn không muốn. Tôi đã đề cập rằng bạn cũng có thể sử dụng sự phản chiếu. Xem câu trả lời của Anthony cho một ví dụ về điều này. Tôi cũng đã cập nhật bài đăng của mình để bao gồm một ví dụ về cách sử dụng sự phản chiếu để khởi tạo các triển khai cụ thể khác nhau của giao diện. –

+0

Tôi có lẽ sẽ viết này để có các trường hợp của 'IMyInterface' thay vì chỉ tên, nhưng vẫn +1. – dlras2

2

Mở rộng trên câu trả lời Joe's, bạn có thể sử dụng thuộc tính [TestCaseSource] trong NUnit theo cách tương tự với RowTest của MBUnit. Bạn có thể tạo nguồn trường hợp thử nghiệm với tên lớp của bạn trong đó. Sau đó bạn có thể trang trí mọi thử nghiệm mà thuộc tính TestCaseSource. Sau đó, sử dụng Activator.CreateInstance bạn có thể truyền tới giao diện và bạn sẽ được thiết lập.

Something như thế này (lưu ý - đầu biên soạn)

string[] MyClassNameList = { "Class1", "Class2" }; 

[TestCaseSource(MyClassNameList)] 
public void Test1(string className) 
{ 
    var instance = Activator.CreateInstance(Type.FromName(className)) as IMyInterface; 

    ... 
} 
1

này được thực hiện cụ thể của tôi dựa tắt của avandeursen's answer:

[TestClass] 
public abstract class IMyInterfaceTests 
{ 
    protected abstract IMyInterface CreateInstance(); 

    [TestMethod] 
    public void SomeTest() 
    { 
     IMyInterface instance = CreateInstance(); 
     // Run the test 
    } 
} 

Mỗi thực hiện giao diện sau đó định nghĩa các lớp thử nghiệm sau đây:

[TestClass] 
public class MyImplementationTests : IMyInterfaceTests 
{ 
    protected override IMyInterface CreateInstance() 
    { 
     return new MyImplementation(); 
    } 
} 

SomeTest được chạy một lần cho mỗi bê tông TestClass bắt nguồn từ IMyInterfaceTests. Bằng cách sử dụng một lớp cơ sở trừu tượng, tôi tránh sự cần thiết cho bất kỳ triển khai mô hình nào. Đảm bảo thêm TestClassAttribute vào cả hai lớp hoặc cách này sẽ không hoạt động. Cuối cùng, bạn có thể thêm bất kỳ bài kiểm tra thực hiện cụ thể nào (chẳng hạn như các hàm tạo) vào lớp con nếu muốn.

+0

bạn có đang sử dụng một khung kiểm tra cụ thể không? Tôi đang sử dụng các bài kiểm tra đơn vị bao gồm trong VS2012, và các bài kiểm tra kế thừa từ một dự án thử nghiệm "chia sẻ" khác (không gian tên) không được chọn. – drzaus

+0

kỳ lạ - thử nghiệm kế thừa trong cùng một dự án, không gian tên khác nhau hiển thị tốt. chỉ khi họ ở trong một dự án khác mà họ không đăng ký. tôi đang thiếu gì? – drzaus

Các vấn đề liên quan