2009-06-19 44 views
11

Tôi hiện đang sử dụng một quy ước đơn giản cho các bài kiểm tra đơn vị của mình. Nếu tôi có một lớp có tên là "EmployeeReader", tôi tạo ra một lớp thử nghiệm có tên là "EmployeeReader.Tests sau đó tôi có thể tạo tất cả các bài kiểm tra cho các lớp trong lớp thử nghiệm với những cái tên như:.Tôi có nên thay đổi quy ước đặt tên cho các bài kiểm tra đơn vị của mình không?

  • Reading_Valid_Employee_Data_Correctly_Generates_Employee_Object
  • Reading_Missing_Employee_Data_Throws_Invalid_Employee_ID_Exception

và vân vân.

Gần đây tôi đã được đọc về một different type of naming convention sử dụng trong BDD. tôi thích khả năng đọc đặt tên này, t o kết thúc với một danh sách kiểm tra cái gì đó như:

  • When_Reading_Valid_Employee (cố định)
    • Employee_Object_Is_Generated (phương pháp)
    • Employee_Has_Correct_ID (phương pháp)
  • When_Reading_Missing_Employee (cố định)
    • An_Invalid_Employee_ID_Exception_Is_Thrown (phương pháp)

v.v.

Có ai đã sử dụng cả hai kiểu đặt tên không? Bạn có thể cung cấp bất kỳ lời khuyên, lợi ích, hạn chế, gotchas, vv để giúp tôi quyết định có nên chuyển đổi hay không cho dự án tiếp theo của tôi?

Trả lời

3

Ví dụ thứ hai của bạn (có một vật cố định cho mỗi "nhiệm vụ" hợp lý), có lợi thế là bạn có thể có logic SetUp và TearDown khác nhau cho mỗi tác vụ, do đó đơn giản hóa các phương pháp thử riêng của bạn và làm cho chúng dễ đọc hơn.

Bạn không cần phải giải quyết bằng một hoặc tiêu chuẩn khác. Chúng tôi sử dụng một hỗn hợp của cả hai, tùy thuộc vào bao nhiêu "nhiệm vụ" khác nhau mà chúng tôi phải kiểm tra cho mỗi lớp.

2

Tôi cảm thấy thứ hai là tốt hơn vì nó làm cho các bài kiểm tra đơn vị của bạn dễ đọc hơn với người khác vì các dòng dài khiến mã trông khó đọc hơn hoặc khó đọc hơn. Nếu bạn vẫn cảm thấy có bất kỳ sự mơ hồ nào đối với thử nghiệm, bạn có thể thêm nhận xét để làm rõ điều này.

6

Quy ước đặt tên Tôi đã sử dụng là:

functionName_shouldDoThis_whenThisIsTheSituation

Ví dụ, đây sẽ là một số tên thử nghiệm cho 'pop' chức năng

pop_shouldThrowEmptyStackException_whenTheStackIsEmpty của chồng

pop _shouldReturnTheObjectOnTheTopOfTheStack_whenThereIsAnObjectOnTheStack

1

Một phần lý do đằng sau quy ước đặt tên thứ hai mà bạn tham chiếu là bạn đang tạo thử nghiệm và thông số hành vi cùng một lúc. Bạn thiết lập bối cảnh trong đó mọi thứ đang xảy ra và những gì thực sự sẽ xảy ra trong bối cảnh đó. (Theo kinh nghiệm của tôi, các quan sát/phương pháp thử nghiệm thường bắt đầu bằng "should_", do đó bạn sẽ có định dạng "When_the_invoicing_system_is_told_to_email_the_client", "should_initiate_connection_to_mail_server".)

Có các công cụ sẽ phản ánh trên đồ đạc thử nghiệm và xuất ra tờ spec html được định dạng độc đáo, loại bỏ các dấu gạch dưới. Bạn kết thúc với tài liệu có thể đọc được bằng con người được đồng bộ với mã thực tế (miễn là bạn giữ phạm vi kiểm tra của mình cao và chính xác).

Tùy thuộc vào câu chuyện/tính năng/hệ thống con mà bạn đang làm việc, các thông số kỹ thuật này có thể được hiển thị và hiểu bởi các bên liên quan không lập trình để xác minh và phản hồi, là trung tâm của nhanh nhẹn và BDD nói riêng.

1

tôi sử dụng phương pháp thứ hai, và nó thực sự giúp với mô tả những gì phần mềm của bạn nên làm. Tôi cũng sử dụng các lớp lồng nhau để mô tả ngữ cảnh chi tiết hơn.

Thực chất, các lớp thử nghiệm là các ngữ cảnh, có thể lồng nhau và các phương thức là tất cả các xác nhận một dòng. Ví dụ,

public class MyClassSpecification 
{ 
    protected MyClass instance = new MyClass(); 

    public class When_foobar_is_42 : MyClassSpecification 
    { 
     public When_foobar_is_42() { 
      this.instance.SetFoobar(42); 
     } 

     public class GetAnswer : When_foobar_is_42 
     { 
      private Int32 result; 

      public GetAnswer() { 
       this.result = this.GetAnswer(); 
      } 

      public void should_return_42() { 
       Assert.AreEqual(42, result); 
      } 
     } 
    } 
} 

đó sẽ cho tôi sau đầu ra trong runner thử nghiệm của tôi:

MyClassSpecification+When_foobar_is_42+GetAnswer 
    should_return_42 
1

Tôi đã xuống hai con đường mà bạn mô tả trong câu hỏi của bạn cũng như một vài khác ... Cách thay thế đầu tiên của bạn khá dễ hiểu và dễ hiểu đối với hầu hết mọi người. Cá nhân tôi thích phong cách BDD (ví dụ thứ hai của bạn) nhiều hơn vì nó tách biệt các ngữ cảnh và nhóm khác nhau dựa trên các bối cảnh đó. Chỉ có nhược điểm thực sự là nó tạo ra nhiều mã hơn để bắt đầu làm nó cảm thấy hơi cồng kềnh hơn cho đến khi bạn thấy các bài kiểm tra gọn gàng. Ngoài ra nếu bạn sử dụng thừa kế để tái sử dụng thiết lập fixture bạn muốn có một testrunner mà kết quả đầu ra chuỗi thừa kế. Hãy xem xét một lớp "An_empty_stack" và bạn muốn sử dụng lại nó để bạn sau đó làm một lớp khác: "When_five_is_pushed_on: An_empty_stack" bạn muốn đó là đầu ra và không chỉ "When_five_is_pushed_on". Nếu testrunner của bạn không hỗ trợ điều này, các test của bạn sẽ chứa các thông tin dư thừa như: "When_five_is_pushed_on_empty_stack: An_empty_stack" chỉ để làm cho đầu ra tốt đẹp.

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