Không thử nghiệm đơn vị khẳng định phá vỡ nguyên tắc DRY?


12

Bất cứ khi nào tôi viết bài kiểm tra đơn vị, tôi luôn cố gắng có một xác nhận duy nhất cho mỗi bài kiểm tra để làm cho việc gỡ lỗi dễ dàng hơn khi các bài kiểm tra thất bại. Tuy nhiên, khi tôi tuân theo quy tắc này, tôi cảm thấy như tôi liên tục sao chép cùng một mã trong mỗi bài kiểm tra và bằng cách có nhiều bài kiểm tra hơn, việc quay lại đọc và duy trì trở nên khó khăn hơn.

Vì vậy, thử nghiệm đơn khẳng định có vi phạm DRY không?

có một quy tắc tốt để tuân theo để tìm sự cân bằng tốt, như chỉ có một thử nghiệm cho mỗi phương pháp ? *

* Tôi nhận ra có lẽ không có một kích thước phù hợp với tất cả các giải pháp cho vấn đề này nhưng có cách nào được đề xuất để tiếp cận vấn đề này không?


5
Bạn có thể trích xuất mã bạn sao chép vào các phương thức
Ismail Badawi

@IsmailBadawi nghe có vẻ là một ý kiến ​​hay. Tôi sẽ giả sử các phương thức này sẽ trả về một thể hiện của đối tượng lớp mà tôi đang thử nghiệm
Korey Hinton

1
Bạn đang tạo ra một cái gì đó trong một trạng thái nhất định để được thử nghiệm? Nghe có vẻ như một vật cố định.
Dave Hillier

@DaveHillier vâng, hôm nay tôi đã học được một từ mới. Cảm ơn :)
Korey Hinton

phụ thuộc vào cách bạn diễn giải 1 khẳng định cho mỗi thử nghiệm, nếu bạn có nghĩa là một cuộc gọi Assert * thì vâng nếu bạn cũng muốn đảm bảo các bất biến vẫn giữ (sau đó lại trích xuất nó thành một phương thức) hoặc nếu có nhiều hiệu ứng mà bạn có thể ' Thử nghiệm trong một Assert duy nhất (hoặc nếu bạn đã làm thì sẽ không rõ lý do tại sao nó thất bại)
ratchet freak

Câu trả lời:


14

Các bài kiểm tra đơn vị phù hợp có quy ước đặt tên giúp bạn xác định ngay những gì đã thất bại:

public void AddNewCustomer_CustomerExists_ThrowsException()

Đây là lý do tại sao bạn có một xác nhận cho mỗi thử nghiệm, sao cho mỗi phương thức (và tên của nó) tương ứng với điều kiện mà bạn đang khẳng định.

Như bạn đã chỉ ra một cách chính xác, mỗi thử nghiệm mới sẽ có mã thiết lập tương tự. Như với bất kỳ mã nào, bạn có thể cấu trúc lại mã chung thành phương thức riêng của mình để giảm hoặc loại bỏ sự trùng lặp và làm cho mã của bạn trở nên DRY hơn. Một số khung kiểm tra được thiết kế đặc biệt để cho phép bạn đặt mã thiết lập đó ở một nơi .

Trong TDD, không có bài kiểm tra nào là YAGNI, bởi vì bạn viết bài kiểm tra chỉ dựa trên những gì bạn yêu cầu mã của mình để làm. Nếu bạn không cần nó, bạn sẽ không viết bài kiểm tra.


Tái cấu trúc thành một phương pháp duy nhất nghe có vẻ tốt. Nếu tôi cần một thể hiện của lớp ở trạng thái nhất định, tôi có thể tạo và trả về một thể hiện mới của đối tượng đó trong phương thức được cấu trúc lại hoặc như bạn đề nghị sử dụng các phương thức được cung cấp bởi khung kiểm tra để thiết lập thử nghiệm ban đầu.
Korey Hinton

ở điểm cuối cùng của bạn, tôi chắc chắn rằng tôi có thể viết các bài kiểm tra cho các chức năng tôi thích mã phải có, chứ không phải là chức năng nó cần thiết
Joel B

5

Vì vậy, thử nghiệm đơn khẳng định có vi phạm DRY không?

Không, nhưng nó thúc đẩy vi phạm.

Điều đó nói rằng, thiết kế hướng đối tượng tốt có xu hướng đi ra ngoài cửa sổ cho các bài kiểm tra đơn vị - chủ yếu là vì lý do tốt. Điều quan trọng hơn là các bài kiểm tra đơn vị phải được cách ly với nhau để bài kiểm tra có thể được thẩm vấn một cách cô lập và nếu cần, hãy cố định với sự tự tin rằng bạn không phá vỡ các bài kiểm tra khác. Về cơ bản, kiểm tra tính chính xác và khả năng đọc là quan trọng hơn kích thước hoặc khả năng bảo trì của nó.

Thành thật mà nói, tôi chưa bao giờ là người hâm mộ của một quy tắc khẳng định cho mỗi quy tắc kiểm tra vì những lý do bạn mô tả: nó dẫn đến rất nhiều mã soạn sẵn khó đọc, dễ bị nhầm lẫn và khó sửa nếu bạn tái cấu trúc (điều này thúc đẩy bạn tái cấu trúc ít hơn).

Nếu một hàm được cho là trả về một danh sách "foo" và "bar" cho một đầu vào nhất định, nhưng theo bất kỳ thứ tự nào, việc sử dụng hai xác nhận để kiểm tra xem cả hai đều nằm trong tập kết quả. Trường hợp bạn gặp rắc rối là khi một thử nghiệm duy nhất đang kiểm tra hai đầu vào hoặc hai tác dụng phụ và bạn không biết cái nào trong hai nguyên nhân gây ra lỗi.

Tôi xem nó như một biến thể của Nguyên tắc Trách nhiệm duy nhất: chỉ có một điều có thể khiến thử nghiệm thất bại, và trong một thế giới lý tưởng, sự thay đổi chỉ nên phá vỡ một thử nghiệm.

Nhưng cuối cùng, đó là một sự đánh đổi. Bạn có nhiều khả năng dành nhiều thời gian hơn để duy trì tất cả các mã pastey sao chép, hoặc bạn sẽ dành nhiều thời gian hơn để tìm kiếm nguyên nhân gốc rễ khi các bài kiểm tra có thể bị phá vỡ bởi nhiều nguồn. Miễn là bạn viết các bài kiểm tra, có lẽ nó không quá quan trọng. Mặc dù tôi khinh miệt đối với các bài kiểm tra đơn khẳng định, tôi có xu hướng sai ở phía các bài kiểm tra khác. Số dặm của bạn có thể thay đổi.


1
Đối với các bài kiểm tra, điều quan trọng là DAMP hơn DRY (Cụm từ mô tả và có ý nghĩa).
Jörg W Mittag

2

Không. Đây dường như chỉ là cách bạn đang làm. Trừ khi bạn tìm thấy một tài liệu tham khảo đáng chú ý nơi họ cho rằng đây là một thực tiễn tốt.

Sử dụng một vật cố thử nghiệm (mặc dù trong thuật ngữ XUnit, bộ thử nghiệm, thiết lập và phá bỏ là vật cố định), nghĩa là, một số thiết lập hoặc ví dụ áp dụng cho tất cả các thử nghiệm của bạn.

Sử dụng các phương thức như bạn thường làm để cấu trúc mã của bạn. Khi tái cấu trúc kiểm tra, TDD Red-Green-Refactor thông thường không áp dụng, thay vào đó áp dụng, "Tái cấu trúc trong màu đỏ". Đó là,

  1. cố tình phá vỡ bài kiểm tra của bạn,
  2. tái cấu trúc của bạn
  3. sửa bài kiểm tra của bạn

Bằng cách này bạn biết rằng các xét nghiệm vẫn cho kết quả dương tính và âm tính.

Có một số định dạng tiêu chuẩn cho các bài kiểm tra. Ví dụ: Sắp xếp, hành động, khẳng định hoặc đưa ra khi, sau đó (BDD) . Xem xét sử dụng một chức năng riêng cho từng bước. Bạn sẽ có thể gọi hàm để giảm nồi hơi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.