2010-10-01 27 views
39

Đọc this question đã giúp tôi củng cố một số vấn đề mà tôi luôn gặp phải với thử nghiệm đơn vị, TDD, et al.Các mẫu thiết kế hữu ích cho thử nghiệm đơn vị/TDD?

Kể từ khi tiếp cận phương pháp TDD để phát triển, tôi biết rằng đó là con đường phù hợp để theo dõi. Đọc các hướng dẫn khác nhau đã giúp tôi hiểu cách bắt đầu, nhưng chúng luôn rất đơn giản - không thực sự là thứ mà người ta có thể áp dụng cho một dự án đang hoạt động. Điều tốt nhất tôi đã quản lý là viết các bài kiểm tra xung quanh các phần nhỏ của mã của tôi - những thứ như thư viện, được sử dụng bởi ứng dụng chính nhưng không được tích hợp theo bất kỳ cách nào. Mặc dù điều này hữu ích nhưng nó tương đương với khoảng 5% mã cơ bản. Có rất ít trên đó làm thế nào để đi đến bước tiếp theo, để giúp tôi nhận được một số xét nghiệm vào các ứng dụng chính.

Các nhận xét như "Most code without unit tests is built with hard dependencies (i.e.'s new's all over the place) or static methods." và "...it's not rare to have a high level of coupling between classes, hard-to-configure objects inside your class [...] and so on." đã làm cho tôi nhận ra rằng bước tiếp theo là tìm hiểu cách tách cặp để làm cho mã có thể kiểm chứng.

Tôi nên xem xét điều gì để giúp tôi thực hiện việc này? Có một tập hợp các mẫu thiết kế cụ thể mà tôi cần phải hiểu và bắt đầu triển khai để cho phép thử nghiệm dễ dàng hơn không?

Trả lời

45

Ở đây, Mike Clifton mô tả 24 mẫu thử nghiệm từ năm 2004. Đây là mẫu thử nghiệm hữu ích khi thiết kế thử nghiệm đơn vị.

http://www.codeproject.com/Articles/5772/Advanced-Unit-Test-Part-V-Unit-Test-Patterns

đèo/Fail Patterns

Những mẫu là dòng đầu tiên của bạn bảo vệ (hay tấn công, tùy thuộc vào quan điểm của bạn) để đảm bảo mã tốt. Nhưng được cảnh báo, họ là lừa đảo trong những gì họ nói với bạn về mã.

  • The Simple-Kiểm tra mẫu
  • Bộ luật-Path Pattern
  • Các Parameter cấp Pattern

Patterns giao dịch dữ liệu

mẫu giao dịch dữ liệu là một sự khởi đầu tại ôm các vấn đề về sự kiên trì và truyền thông dữ liệu. Thêm về chủ đề này được thảo luận trong "Mô hình mô phỏng". Ngoài ra, các mẫu này cố ý bỏ qua kiểm tra căng thẳng, ví dụ, tải trên máy chủ. Điều này sẽ được thảo luận trong "Stress-Test Patterns".

  • The Simple-Data-I/O mẫu
  • Các Constraint-Data Pattern
  • Các mẫu Rollback

Patterns Quản lý Bộ sưu tập

Rất nhiều những ứng dụng làm là quản lý bộ sưu tập thông tin. Trong khi có nhiều bộ sưu tập có sẵn cho lập trình viên, điều quan trọng là phải xác minh (và do đó tài liệu) rằng mã đang sử dụng bộ sưu tập chính xác. Điều này ảnh hưởng đến trật tự và ràng buộc.

  • Bộ sưu tập bậc mẫu
  • Các mẫu Enumeration Các
  • Collection-Hạn chế Pattern
  • Các mẫu Collection-Indexing

Performance Patterns

Đơn vị kiểm tra nên không chỉ quan tâm đến chức năng mà còn với biểu mẫu. Mã dưới kiểm thử hiệu quả thực hiện chức năng của nó như thế nào? Nhanh như thế nào? Bộ nhớ sử dụng bao nhiêu bộ nhớ? Nó có hỗ trợ việc chèn dữ liệu để truy xuất dữ liệu một cách hiệu quả không? Nó có giải phóng tài nguyên một cách chính xác không? Đây là tất cả những thứ đang trong quá trình kiểm tra đơn vị. Bằng cách bao gồm các mẫu hiệu suất trong thử nghiệm đơn vị, người triển khai có mục tiêu để tiếp cận, kết quả là mã tốt hơn, ứng dụng tốt hơn và khách hàng hạnh phúc hơn.

  • Các mẫu Performance-Test

Process Patterns

Đơn vị kiểm tra được thiết kế để kiểm tra, tốt, đơn vị ... các chức năng cơ bản của ứng dụng. Có thể lập luận rằng các quá trình thử nghiệm nên được chuyển xuống các thủ tục kiểm tra chấp nhận, tuy nhiên tôi không mua vào đối số này. Quy trình chỉ là một loại đơn vị khác. Các quy trình thử nghiệm với bộ kiểm thử đơn vị cung cấp các ưu điểm giống như kiểm tra đơn vị khác - nó ghi lại cách quy trình được thiết kế để hoạt động và bộ kiểm thử đơn vị có thể hỗ trợ người thực hiện bằng cách kiểm tra quá trình. tốt. Thuật ngữ "quy trình" cũng bao gồm các quá trình chuyển đổi trạng thái và quy tắc kinh doanh, cả hai quy tắc này phải được xác thực.

  • Các mẫu Process-Chuỗi
  • Các mẫu Process-State
  • Quá trình-Rule Pattern

Patterns Simulation

giao dịch dữ liệu rất khó để kiểm tra vì họ thường yêu cầu cấu hình cài sẵn, kết nối mở và/hoặc thiết bị trực tuyến (để đặt tên một vài). Các đối tượng giả có thể đến để giải cứu bằng cách mô phỏng cơ sở dữ liệu, dịch vụ web, sự kiện người dùng, kết nối và/hoặc phần cứng mà mã đang giao dịch. các đối tượng giả cũng có khả năng tạo điều kiện thất bại mà rất khó để tái tạo trong thế giới thực - một kết nối lossy, một máy chủ chậm, một trung tâm mạng thất bại vv

  • Mock-Object Pattern
  • Dịch vụ-mô phỏng mẫu
  • các mẫu Bit-Error-Simulation
  • các Component-mô phỏng mẫu

Patterns Multithreading

Đơn vị thử nghiệm các ứng dụng đa luồng có lẽ là một trong những điều khó làm nhất vì bạn phải thiết lập một điều kiện do bản chất của nó được dự định là không đồng bộ và do đó không xác định. Chủ đề này có lẽ là một bài viết lớn trong chính nó, vì vậy tôi sẽ chỉ cung cấp một mô hình rất chung chung ở đây. Bên cạnh đó, để thực hiện nhiều thử nghiệm luồng một cách chính xác, việc áp dụng đơn vị kiểm tra phải tự thực hiện kiểm tra theo chủ đề riêng biệt để các tester đơn vị không bị vô hiệu hóa khi một thread kết thúc trong trạng thái chờ đợi

  • Các mẫu hiệu
  • các Deadlock-Nghị quyết Pattern

Patterns Căng thẳng-Test

Hầu hết các ứng dụng được thử nghiệm trong môi trường lý tưởng - các lập trình viên đang sử dụng một machin nhanh e với lưu lượng mạng nhỏ, sử dụng các tập dữ liệu nhỏ. Thế giới thực rất khác biệt. Trước khi một cái gì đó hoàn toàn phá vỡ, ứng dụng có thể bị suy thoái và phản hồi kém hoặc có lỗi cho người dùng. Các xét nghiệm đơn vị xác minh hiệu suất của mã dưới sự căng thẳng phải được đáp ứng với sự nhiệt tình bằng nhau (nếu không nhiều hơn) so với các xét nghiệm đơn vị trong một môi trường lý tưởng.

  • Các Bulk-Data-Stress-Kiểm tra mẫu
  • Pattern
  • Các Resource Căng Thẳng-Test
  • Các tải-Kiểm tra mẫu

Presentation Lớp Patterns

Một trong các khía cạnh thách thức nhất của thử nghiệm đơn vị là xác minh rằng thông tin đang nhận được cho người dùng ngay tại chính lớp trình bày và rằng nội bộ wor các vị vua của ứng dụng được thiết lập chính xác trạng thái lớp trình bày.Thông thường, các lớp trình bày được vướng víu với các đối tượng nghiệp vụ, các đối tượng dữ liệu và logic điều khiển. Nếu bạn đang lập kế hoạch kiểm thử đơn vị lớp trình bày, bạn phải nhận ra rằng việc tách biệt mối quan tâm là bắt buộc. Một phần của giải pháp bao gồm việc phát triển một kiến ​​trúc Model-View-Controller (MVC) thích hợp. Kiến trúc MVC cung cấp một phương tiện để phát triển các thực hành thiết kế tốt khi làm việc với lớp trình bày. Tuy nhiên, nó dễ bị lạm dụng. Một số lượng nhất định của kỷ luật là cần thiết để đảm bảo rằng bạn đang, trên thực tế, thực hiện các kiến ​​trúc MVC một cách chính xác, chứ không phải chỉ trong từ một mình.

  • The View-State mẫu thử nghiệm
  • Các thử nghiệm Model-State Pattern
2

Mẫu thiết kế không liên quan trực tiếp đến TDD vì chúng là chi tiết triển khai. Bạn không nên cố gắng phù hợp với các mẫu mã của bạn chỉ vì chúng tồn tại, nhưng thay vào đó chúng có xu hướng xuất hiện khi mã của bạn phát triển. Chúng cũng trở nên hữu ích nếu mã của bạn có mùi, vì chúng giúp giải quyết các vấn đề như vậy. Không phát triển mã với các mẫu thiết kế trong tâm trí, chỉ cần viết mã. Sau đó, có được các bài kiểm tra đi qua, và refactor.

1

Rất nhiều vấn đề như thế này có thể được giải quyết bằng cách đóng gói thích hợp. Hoặc, bạn có thể gặp phải vấn đề này nếu bạn đang trộn lẫn những lo ngại của mình. Giả sử bạn đã có mã xác nhận người dùng, xác thực đối tượng miền, sau đó lưu đối tượng miền tất cả trong một phương thức hoặc lớp. Bạn đã trộn lẫn mối quan tâm của bạn, và bạn sẽ không được hạnh phúc. Bạn cần phải tách riêng những mối quan tâm đó (xác thực/ủy quyền, logic nghiệp vụ, sự kiên trì) để bạn có thể kiểm tra chúng một cách riêng biệt.

Mẫu thiết kế trợ giúp, nhưng rất nhiều mẫu kỳ lạ có những vấn đề rất hẹp mà chúng có thể được áp dụng. Các mẫu như composite, command, được sử dụng thường xuyên, và rất đơn giản.

Nguyên tắc là: nếu rất khó để kiểm tra điều gì đó, bạn có thể tái cấu trúc nó thành các vấn đề nhỏ hơn và kiểm tra các bit được cấu trúc lại riêng biệt. Vì vậy, nếu bạn có một phương pháp 200 dòng với 5 cấp độ của báo cáo nếu và một vài cho vòng, bạn có thể muốn phá vỡ sucker đó lên.

Vì vậy, hãy bắt đầu bằng cách xem liệu bạn có thể làm cho mã phức tạp đơn giản hơn bằng cách tách mối quan tâm của bạn và sau đó xem liệu bạn có thể làm cho mã phức tạp trở nên đơn giản hơn hay không. Tất nhiên nếu một mẫu thiết kế nhảy ra ngoài bạn, thì hãy tìm nó.

9

Tôi muốn nói bạn cần chủ yếu là hai điều để kiểm tra, và họ đi tay trong tay:

  • giao diện, giao diện, giao diện dependency injection
  • ; điều này kết hợp với các giao diện sẽ giúp bạn trao đổi các phần theo ý muốn để cô lập các mô-đun bạn muốn kiểm tra. Bạn muốn kiểm tra hệ thống giống như cron của mình để gửi thông báo đến các dịch vụ khác? instanciate nó và thay thế thực hiện mã thực của bạn cho mọi thứ khác bởi các thành phần tuân theo giao diện chính xác nhưng cứng có dây để phản ứng theo cách bạn muốn kiểm tra: thông báo thư? kiểm tra xem điều gì sẽ xảy ra khi máy chủ smtp ngừng hoạt động bằng cách ném một ngoại lệ

Bản thân tôi chưa nắm vững thử nghiệm đơn vị (và tôi ở xa nó), nhưng đây là nơi những nỗ lực chính của tôi hiện đang diễn ra .Vấn đề là tôi vẫn không thiết kế cho các bài kiểm tra, và kết quả là mã của tôi phải uốn cong ngược lại để chứa ...

6

Cuốn sách của Michael Feather Working Effectively With Legacy Code chính xác là những gì bạn đang tìm kiếm. Ông định nghĩa mã kế thừa là 'mã không có kiểm tra' và nói về cách làm cho nó được thử nghiệm.

Như với hầu hết mọi thứ, đó là một bước tại một thời điểm. Khi bạn thực hiện thay đổi hoặc sửa chữa, hãy thử tăng phạm vi kiểm tra. Thời gian trôi qua bạn sẽ có một bộ kiểm tra hoàn chỉnh hơn. Nó nói về các kỹ thuật để giảm khớp nối và làm thế nào để phù hợp với các mảnh thử nghiệm giữa logic ứng dụng.

Như đã lưu ý trong câu trả lời phụ thuộc tiêm khác là một cách tốt để viết có thể kiểm tra (và lỏng lẻo cùng nói chung) mã.

3

Mẫu kiểm tra xUnit của Gerard Meszaros: Mã kiểm tra tái cấu trúc là mã đầy đủ các mẫu để kiểm tra đơn vị. Tôi biết bạn đang tìm kiếm các mẫu trên TDD, nhưng tôi nghĩ bạn sẽ tìm thấy rất nhiều tài liệu hữu ích trong cuốn sách này

Cuốn sách đang ở trên safari để bạn có thể xem nội dung bên trong hữu ích: http://my.safaribooksonline.com/9780131495050

2

đã làm cho tôi nhận ra rằng bước tiếp theo là hiểu cách tách cặp để làm cho nó có thể kiểm chứng.

Tôi nên xem xét điều gì để giúp tôi thực hiện việc này? Có một tập hợp các mẫu thiết kế cụ thể mà tôi cần phải hiểu và bắt đầu triển khai để cho phép thử nghiệm dễ dàng hơn không?

Right on! SOLID là những gì bạn đang tìm kiếm (có, thực sự). Tôi tiếp tục giới thiệu các 2 ebooks, đặc biệt là một trong SOLID cho vấn đề ở bàn tay.

Bạn cũng phải hiểu rằng nó rất khó nếu bạn đang giới thiệu thử nghiệm đơn vị cho một cơ sở mã hiện có. Thật không may mã kết hợp chặt chẽ là quá phổ biến. Điều này không có nghĩa là không làm điều đó, nhưng trong một thời điểm tốt nó sẽ giống như bạn đã đề cập, các bài kiểm tra sẽ tập trung hơn trong những phần nhỏ.

Theo thời gian, chúng phát triển thành phạm vi lớn hơn, nhưng nó phụ thuộc vào kích thước của cơ sở mã hiện có, kích thước của nhóm và số lượng thực sự thực hiện thay vì thêm vào vấn đề.

0

Dependency Injection/IoC. Cũng đọc lên trên khuôn khổ tiêm phụ thuộc như SpringFramework và google-guice. Họ cũng nhắm mục tiêu cách viết mã có thể thử nghiệm.

1

Sắp xếp, Luật, Khẳng định là một ví dụ tốt về một mô hình giúp bạn cấu trúc mã thử nghiệm của bạn xung quanh đặc biệt trường hợp sử dụng.

Dưới đây là một số mã C# giả định thể hiện mẫu.

[TestFixture] 
public class TestSomeUseCases() { 

    // Service we want to test 
    private TestableServiceImplementation service; 

    // IoC-injected mock of service that's needed for TestableServiceImplementation 
    private Mock<ISomeService> dependencyMock; 

    public void Arrange() { 
     // Create a mock of auxiliary service 
     dependencyMock = new Mock<ISomeService>(); 
     dependencyMock.Setup(s => s.GetFirstNumber(It.IsAny<int>)).Return(1); 

     // Create a tested service and inject the mock instance 
     service = new TestableServiceImplementation(dependencyMock.Object); 
    } 

    public void Act() { 
     service.ProcessFirstNumber(); 
    } 

    [SetUp] 
    public void Setup() { 
     Arrange(); 
     Act(); 
    } 

    [Test] 
    public void Assert_That_First_Number_Was_Processed() { 
     dependencyMock.Verify(d => d.GetFirstNumber(It.IsAny<int>()), Times.Exactly(1)); 
    } 
} 

Nếu bạn có rất nhiều kịch bản để kiểm tra, bạn có thể trích xuất một lớp trừu tượng chung với bê tông Sắp xếp & bit Act (hoặc chỉ cần Sắp xếp) và thực hiện các bit trừu tượng còn lại & chức năng kiểm tra trong các lớp thừa hưởng nhóm chức năng kiểm tra.

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