Kiểm tra đơn vị Java, bố cục thư mục [đã đóng]


76

Khi xây dựng một bộ kiểm thử đơn vị cho mã Java, có quy ước về vị trí đặt mã kiểm tra liên quan đến mã nguồn không?

Ví dụ: nếu tôi có một thư mục /javachứa một loạt các .javatệp nguồn, thì tốt hơn là đặt các trường hợp thử nghiệm vào /javachính nó hoặc sử dụng một cái gì đó như thế /java/test.

Nếu cái sau được ưu tiên, làm cách nào để bạn kiểm tra phần bên trong của mã khi private / protectedcác thành viên của một lớp không có sẵn bên ngoài gói?

Câu trả lời:


73

Bạn có thể đặt các bài kiểm tra trong cùng một gói với các lớp gốc, ngay cả khi mã nguồn nằm trong thư mục gốc của chính nó:

PROJECT_ROOT
    +--- src/
    +----test/

Bạn có thể khai báo một lớp com.foo.MyClassdưới srcvà kiểm tra của nó com.foo.MyClassTestdưới test.

Đối với quyền truy cập vào các thành viên riêng tư, bạn có thể sử dụng phản chiếu để gọi các phương thức (thay đổi khả năng truy cập của họ thông qua Class.getDeclaredMethod.setAccessible) hoặc bạn có thể sử dụng một cái gì đó như testng / junit5 để đặt một số thử nghiệm theo hướng chú thích trên chính mã nguồn (cá nhân tôi nghĩ rằng đây là một ý kiến ​​tồi).

Tại sao không kiểm tra một số dự án java.netđể xem họ đã tổ chức mọi thứ như thế nào, ví dụ như swinglabs (kho lưu trữ SVN khá chậm, tôi e rằng)?


117

Tôi khuyên bạn nên làm theo cấu trúc thư mục tiêu chuẩn của Apache Software Foundation, cấu trúc này mang lại kết quả như sau:

module/
  src/
    main/
      java/
    test/
      java/

Điều này giữ cho các bài kiểm tra tách biệt với nguồn, nhưng ở cùng cấp độ trong cấu trúc thư mục. Nếu bạn đọc qua cách Apache xác định cấu trúc của chúng, bạn sẽ thấy nó cũng giúp phân vùng các mối quan tâm khác ra ngoài, bao gồm tài nguyên, tệp cấu hình, ngôn ngữ khác, v.v.

Cấu trúc này cũng cho phép các bài kiểm tra đơn vị kiểm tra các phương pháp gói và mức được bảo vệ của các đơn vị được kiểm tra, giả sử bạn đặt các trường hợp kiểm thử của mình trong cùng một gói với những gì chúng kiểm tra. Về việc thử nghiệm các phương pháp riêng tư - tôi sẽ không bận tâm. Một cái gì đó khác, công khai, gói hoặc được bảo vệ gọi chúng và bạn sẽ có thể nhận được toàn bộ phạm vi kiểm tra thử nghiệm những thứ đó.

Nhân tiện, liên kết ở trên là đến Maven, công cụ xây dựng tiêu chuẩn của Apache. Mọi dự án Java mà họ có đều tuân theo tiêu chuẩn này, cũng như mọi dự án tôi gặp phải đều được xây dựng bằng Maven.


6
+1 Ngay cả khi bạn không sử dụng maven, bạn nên tuân theo bố cục này (một loại tiêu chuẩn thực tế dựa trên các phương pháp hay nhất trong ngành).
Pascal Thivent

7
Lý do duy nhất mà Maven được đề cập ở đây là vì trang web của nó là một nơi chứa bố cục thư mục tiêu chuẩn Apache được ghi lại. Việc bạn thích hay không thích nó không liên quan đến việc cấu trúc thư mục được đề cập có phải là cấu trúc tốt hay không. Có lẽ bạn có thể nhận xét về một câu trả lời phù hợp với ý kiến ​​của bạn để chỉ ra lý do tại sao cấu trúc thư mục đó ưu việt hơn.
SingleShot

1
Nếu bạn đang mã hóa trong tinh khiết Java, javathư mục là một sự bổ sung cần thiết
oxbow_lakes

6
Vâng, cần lưu ý rằng thông thường cả thư mục maintestthư mục đều có resourcesthư mục nguồn biên dịch vào cùng thư mục đầu ra mà javathư mục đó làm, cho phép dễ dàng tách mã Java và tệp tài nguyên ở cấp nguồn. Tôi cũng thích cấu trúc này vì nó giữ cho cấp cao nhất không có nhiều thư mục nguồn ... đó là một tổ chức rất hợp lý. Và vâng, điều này không liên quan đến việc một người có thích Maven hay không.
ColinD

3
Tôi đã đưa ra nhận xét đó tám năm trước. Kể từ đó, tôi đã hiểu và yêu Maven. Tôi sẽ không làm việc nếu không có nó bây giờ. Con người có thể thay đổi.
duffymo

8

Hầu hết các lần được thực hiện như thế này:

<SOME_DIR>/project/src/com/foo/Application.java
<SOME_DIR>/project/test/com/foo/ApplicationTest.java

Vì vậy, bạn giữ chúng được tách biệt và bạn vẫn có thể kiểm tra gói / chức năng được bảo vệ vì thử nghiệm nằm trong cùng một gói.

Bạn không thể kiểm tra nội dung riêng tư, trừ khi nó được tự khai báo bên trong lớp.

Khi giao hàng, bạn chỉ đóng gói .classđược tạo bởi src, không phải kiểm tra


1
kiểm tra phải nằm trong thư mục src. maven.apache.org/guides/introduction/…
Philip Rego

5

Trên thực tế, rất có ý nghĩa khi tách dự án Sản xuất và Thử nghiệm thành 2 thực thể riêng biệt, nhưng có cấu trúc gói giống nhau trong cả hai dự án.

Vì vậy, nếu tôi có một dự án 'my-project', tôi cũng tạo 'my-project-test', vì vậy tôi có cấu trúc thư mục sau:

my-project
  +--- src/com/foo
my-project-test
  +---test/com/foo

Cách tiếp cận này đảm bảo rằng các phụ thuộc mã thử nghiệm không gây ô nhiễm mã sản xuất.

Theo ý kiến ​​cá nhân của tôi, nên thử nghiệm các phương thức riêng tư và được bảo vệ của gói cũng như các phương thức công khai. Do đó, tôi muốn các lớp thử nghiệm của mình trong cùng một gói với các lớp sản xuất.


2

Đây là cách chúng tôi thiết lập nó và chúng tôi thích nó.

build/
src/
test/build/
test/src/

Tất cả mã thử nghiệm biên dịch vào thư mục xây dựng của riêng nó. Điều này là do chúng tôi không muốn sản xuất chứa nhầm các lớp thử nghiệm.


1

Khi tạo mô-đun thư viện Java trong Android Studio, nó sẽ tạo một lớp mặc định dưới:

[module]
   + src/main/java/[com/foo/bar]

Nếu bạn nhìn vào [module].imltệp, bạn sẽ tìm thấy đường dẫn đó cũng như đường dẫn cho các bài kiểm tra mà bạn có thể sử dụng. Dưới đây là tóm tắt:

<module>
  <component>
    <content>
      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
    </content>
  </component>
</module>

Điều bạn có thể làm cụ thể là tạo một thư mục cho các bài kiểm tra có cấu trúc sau:

[module]
   + src/main/java/[com/foo/bar]
   + src/test/java/[com/foo/bar]

Cấu trúc trên sẽ được Android Studio nhận dạng và các tệp của bạn bên dưới sẽ được đưa vào mô-đun.

Tôi giả định rằng cấu trúc đó là một bố cục được đề xuất cho mã và thử nghiệm.

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.