Câu trả lời:
Làm thế nào các bài kiểm tra của bạn được tổ chức là khá không quan trọng so với tầm quan trọng của việc có chúng ở tất cả.
Điều quan trọng nhất cho một bộ kiểm tra tốt là nó bao gồm tất cả các chức năng; đảm bảo rằng bất cứ khi nào một lỗi hồi quy được đưa ra, bạn sẽ nhận thấy ngay lập tức. Việc viết một thử nghiệm cho mỗi phương thức, một thử nghiệm cho mỗi kết hợp giá trị đầu vào của một phương thức, hoặc thậm chí một thử nghiệm cho mỗi đường dẫn mã có thể có trong phương thức đó ít quan trọng hơn. Việc tổ chức các bài kiểm tra này thành một vài hoặc nhiều lớp kiểm tra thậm chí còn ít quan trọng hơn: một bộ kiểm tra luôn luôn thành công đầy đủ, do đó, không thành vấn đề dù có thất bại một trong ba hoặc hai trong số mười bảy bài kiểm tra - cả hai đều sai và phải đã sửa.
Tất nhiên, mã kiểm thử cũng là mã, do đó, nó phải tuân theo các thực tiễn tốt nhất thông thường để có thể duy trì, mô đun, v.v. các lớp họ kiểm tra. Cả hai chính sách bạn đề cập đều có thể giúp bạn nhớ nơi tìm thấy mọi thứ nếu bạn tuân theo chúng một cách nhất quán, nhưng đối với đó, tính nhất quán quan trọng hơn sự lựa chọn chính sách.
Đối với câu hỏi cụ thể của bạn, quy ước JUnit, là có sự tương ứng 1: 1 giữa các lớp ứng dụng ( Foo1.java
, Foo2.java
) và các lớp kiểm tra JUnit ( Foo1Test.java
, Foo2Test.java
).
Điều đó nói rằng, tôi hoàn toàn đồng ý với việc nhấn mạnh của Kilian về tầm quan trọng của tinh thần / mục tiêu của thử nghiệm đơn vị đối với bất kỳ kế hoạch tổ chức nào có thể được sử dụng. Chọn một số quy ước và gắn bó với chúng hầu hết thời gian, trong khi bảo vệ cho phép các ngoại lệ đối với các quy ước của bạn, khi chúng được bảo đảm.
Là tốt hơn để có một lớp riêng cho mỗi phương thức, hoặc chỉ có một lớp kiểm tra cho mỗi lớp thực tế?
Nếu bạn có nhu cầu viết các lớp kiểm tra riêng cho các phương thức của một lớp, thì bạn có thiết kế sai. Phương pháp nên nhỏ, dễ đọc, dễ kiểm tra và dễ thay đổi. Các thử nghiệm có thể dài hơn một chút so với mã gốc do tạo ra testdata, chế nhạo, v.v., nhưng không nên dài hơn đáng kể. Nếu có, lớp của bạn đang được kiểm tra quá phức tạp và chắc chắn có nhiều hơn một điều ( nguyên tắc trách nhiệm duy nhất ): Làm việc trên thiết kế của bạn.
Tôi nghĩ rằng cả "một lớp kiểm tra cho mỗi phương thức" và "một lớp kiểm tra cho mỗi lớp" thường quá cực đoan.
Nói chung, bạn muốn có một kiểm tra cho mỗi phương pháp kiểm tra / đơn vị kiểm tra. Chẳng hạn, đây có thể là nhiều xác nhận để kiểm tra xem a list.isEmpty = true
và list.Length = 0
, do đó, một phương thức kiểm tra / đơn vị kiểm tra cho mỗi hành vi.
Điều này giúp dễ dàng đưa ra một tên phương thức thử nghiệm mô tả hành vi. Bạn muốn nhóm các phương thức kiểm tra trong một lớp kiểm tra, vì vậy khi bạn đọc test classname.test method
, nó có ý nghĩa. Thông thường, những người có một số mã thiết lập được chia sẻ sau đó dễ dàng đưa vào thiết lập / vật cố thử nghiệm. Tùy thuộc vào lớp được kiểm tra, đây có thể là một lớp kiểm tra cho cả lớp và nó cũng có thể là một lớp kiểm tra cho một phương thức. Nhưng thông thường, nó sẽ ở đâu đó ở giữa.
Như với mã thông thường, bạn muốn có các bài kiểm tra càng dễ đọc càng tốt. Điều giúp ích cho tôi là tuân theo phong cách tổ chức mã thử nghiệm được đưa ra khi đó hoặc sắp xếp hành động của BDD. Một lớp kiểm tra có thể được đưa ra, đó là thiết lập. Sau đó, mọi phương thức kiểm tra trong lớp đó sử dụng phương thức đã cho (hoặc một phần của nó) và có một phương thức khi và một sau đó.
Cũng nghĩ về các bài kiểm tra đơn vị như tài liệu về cách sử dụng chức năng của lớp được kiểm tra. Với các bài kiểm tra đơn vị tốt, bạn có thể đọc các bài kiểm tra để tìm hiểu cách sử dụng chức năng của lớp bạn muốn sử dụng, và các hiệu ứng sẽ chính xác là gì.
Khi một cái gì đó bị hỏng và một bài kiểm tra đơn vị thất bại, bạn muốn nó dễ dàng nhất có thể để hiểu những gì đã phá vỡ, một khẳng định cho mỗi bài kiểm tra sẽ giúp rất nhiều ở đây. Khi có nhiều xác nhận trong một thử nghiệm, chỉ có thử nghiệm đầu tiên thất bại và sau đó phương thức thoát ra, vì vậy bạn không biết liệu hành vi khác được thử nghiệm trong các thử nghiệm sau có bị hỏng hay không cho đến khi bạn khắc phục điều khiến cho khẳng định đầu tiên thất bại. Với một xác nhận, tất cả các phương pháp kiểm tra khác của bạn vẫn được thực hiện và nhanh hơn nhiều để hiểu được độ sâu của sự thất bại.
Tất nhiên, tôi đồng ý với Kilian Foth: trong thực tế, bạn có thể may mắn có một vài bài kiểm tra đơn vị cho mã bạn đang làm việc. Và bất kỳ thử nghiệm cục bộ nhỏ nào tốt hơn là không có thử nghiệm nào cả, hoặc chỉ các thử nghiệm tích hợp lớn chạy trên máy chủ xây dựng mất rất nhiều thời gian và thường không được bản địa hóa (chúng không cho bạn biết lỗi nhanh ở đâu - bạn Tôi sẽ phải làm việc với nó một chút).
Tôi nghĩ rằng mỗi lớp đều có lớp kiểm tra. Ý tưởng là tập trung tất cả các bài kiểm tra đơn vị liên quan đến lớp mục tiêu trong một lớp kiểm tra duy nhất. Sau đó, ví dụ, MyClass.java
sẽ có lớp thử nghiệm của nó được gọi MyClassTest.java
.