Chạy thử nghiệm junit song song trong bản dựng Maven?


110

Tôi đang sử dụng JUnit 4.4 và Maven và tôi có một số lượng lớn các thử nghiệm tích hợp lâu dài.

Khi nói đến việc song song hóa các bộ thử nghiệm, có một số giải pháp cho phép tôi chạy song song từng phương pháp thử nghiệm trong một lớp thử nghiệm. Nhưng tất cả những điều này đòi hỏi tôi phải thay đổi các bài kiểm tra theo cách này hay cách khác.

Tôi thực sự nghĩ rằng sẽ là một giải pháp gọn gàng hơn nhiều nếu chạy song song X các lớp thử nghiệm khác nhau trong X luồng. Tôi có hàng trăm bài kiểm tra nên tôi không thực sự quan tâm đến việc phân luồng các lớp kiểm tra riêng lẻ.

Có cách nào để làm điều này?

Câu trả lời:


75

Sử dụng plugin maven:

<build>
    <plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.7.1</version>
        <configuration>
            <parallel>classes</parallel>
            <threadCount>5</threadCount>
        </configuration>
    </plugin>
    </plugins>
</build>

12
<parallel> thực sự được hỗ trợ bởi chắc chắn nếu bạn đang sử dụng Junit 4.7 trở lên. hướng dẫn chắc chắn
jontejj

42

Từ ngày 4.7, giờ đây có thể chạy thử nghiệm song song mà không cần sử dụng TestNG. Trên thực tế, nó đã có thể thực hiện từ phiên bản 4.6, nhưng có một số bản sửa lỗi được thực hiện trong phiên bản 4.7 sẽ khiến nó trở thành một lựa chọn khả thi. Bạn cũng có thể chạy các bài kiểm tra song song với spring, bạn có thể đọc ở đây


1
Trang được liên kết cho biết "đối với hầu hết các giải pháp lõi kép, chạy với các luồng song song hiện không bao giờ nhanh hơn chạy không theo luồng". Đó vẫn là trường hợp?
Raedwald

2
Tôi nghĩ rằng nếu các bài kiểm tra của bạn thực hiện bất kỳ IO nào thì họ vẫn có lợi. Ví dụ: nếu các bài kiểm tra đơn vị của bạn giống các bài kiểm tra tích hợp và đánh vào cơ sở dữ liệu, thì việc chạy song song sẽ tăng tốc chúng.
Dave

@Raedwald Đừng mong đợi quá nhiều vào các bài kiểm tra đơn vị ngắn hạn không ràng buộc io là những gì tôi đang cố gắng nói. Các phiên bản mới hơn của surefire cũng tốt hơn / hiệu quả hơn 2,5 được mô tả trong bài đăng, vì vậy bạn có thể nhận được kết quả tốt hơn một chút.
krosenvold

3
Bạn nói rằng nó có thể, nhưng bạn có thể bao gồm một liên kết đến giải thích về cách làm không? Liên kết thứ hai của bạn dành cho "with spring", mà tôi không quan tâm đến.
Cory Kendall

Liên kết @krosenvold? Tôi đang đấu tranh để tìm một giải pháp tích hợp sẵn.
Ilan Biala

10

Lấy cảm hứng từ bộ chạy ParallelComputer thử nghiệm của JUnit, tôi đã xây dựng bộ chạy ParallelSuiteParallelParameterized của riêng mình . Sử dụng các thiết bị chạy này, người ta có thể dễ dàng song song hóa các bộ thử nghiệm và các thử nghiệm tham số hóa.

ParallelSuite.java

public class ParallelSuite extends Suite {

    public ParallelSuite(Class<?> klass, RunnerBuilder builder) throws InitializationError {

        super(klass, builder);

        setScheduler(new RunnerScheduler() {

            private final ExecutorService service = Executors.newFixedThreadPool(4);

            public void schedule(Runnable childStatement) {
                service.submit(childStatement);
            }

            public void finished() {
                try {
                    service.shutdown();
                    service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
            }
        });
    }
}

ParallelParameterized.java

public class ParallelParameterized extends Parameterized {

    public ParallelParameterized(Class<?> arg0) throws Throwable {

        super(arg0);

        setScheduler(new RunnerScheduler() {

            private final ExecutorService service = Executors.newFixedThreadPool(8);

            public void schedule(Runnable childStatement) {
                service.submit(childStatement);
            }

            public void finished() {
                try {
                    service.shutdown();
                    service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
            }
        });
    }
}

Cách sử dụng rất đơn giản. Chỉ cần thay đổi giá trị @RunWith annotations thành một trong các lớp Parallel * này .

@RunWith(ParallelSuite.class)
@SuiteClasses({ATest.class, BTest.class, CTest.class})
public class ABCSuite {}

5

tempus-fugit cung cấp một cái gì đó tương tự, hãy kiểm tra tài liệu để biết chi tiết. Nó dựa trên JUnit 4.7 và bạn chỉ cần đánh dấu bài kiểm tra của mình @RunWith(ConcurrentTestRunner).

Chúc mừng


3

Bạn có thể kiểm tra thư viện mã nguồn mở - Test Load Balancer . Nó thực hiện chính xác những gì bạn yêu cầu - chạy song song các lớp thử nghiệm khác nhau. Điều này tích hợp ở cấp ant-junit để bạn không phải thay đổi các bài kiểm tra của mình. Tôi là một trong những tác giả của thư viện.

Ngoài ra, hãy nghĩ đến việc không chạy chúng trong các chuỗi vì bạn có thể cần một hộp cát cấp quy trình. Ví dụ: nếu bạn đang đánh một DB trong các bài kiểm tra tích hợp của mình, bạn không muốn một bài kiểm tra thất bại vì một bài kiểm tra khác đã thêm một số dữ liệu trong một chuỗi khác. Hầu hết các bài kiểm tra không được viết với tâm trí này.

Cuối cùng, làm thế nào để giải quyết vấn đề này cho đến bây giờ?


2

TestNG có thể làm được điều đó (đây là phản xạ đầu tiên của tôi - sau đó tôi thấy bạn đã có rất nhiều testcase).

Đối với JUnit, hãy nhìn vào song song-junit .


3
Thật không may, đây không phải là câu trả lời cho câu hỏi tôi đang hỏi. song song-junit chỉ chạy trong một lớp thử nghiệm duy nhất. TestNG cũng chỉ chạy trong một lớp duy nhất và các bài kiểm tra của tôi không phải là bài kiểm tra TestNG.
krosenvold

@PlatinumAzure: Tôi đã cập nhật liên kết. Tôi không biết dự án này được duy trì như thế nào. Một câu hỏi khác đã được đặt ra gần đây để phân phối việc thực thi junit tests trên một số máy .
thiện

2

Bạn có thể chạy các bài kiểm tra song song bằng cách sử dụng ParallelComputer do chính Junit cung cấp. Đây là một đoạn mã nhỏ để giúp bạn bắt đầu.

Class[] cls = { TestCase1.class, TestCase2.class };
Result result = JUnitCore.runClasses(ParallelComputer.classes(), cls);
List<Failure> failures = result.getFailures();

Điều này sẽ hữu ích khi bạn cần chạy thử nghiệm từ mã vì nó không phụ thuộc vào Maven hoặc bất kỳ công cụ quản lý bản dựng nào khác.

Xin lưu ý rằng, điều này sẽ chạy tất cả các trường hợp thử nghiệm song song, nếu bạn có bất kỳ sự phụ thuộc nào giữa các trường hợp thử nghiệm khác nhau, nó có thể dẫn đến kết quả dương tính giả. Dù sao thì bạn cũng KHÔNG NÊN có các bài kiểm tra phụ thuộc lẫn nhau.


0

Một sự lựa chọn khác: Punner, một plugin junit runner và maven song song mới. Bạn không cần phải thay đổi mã của mình, hãy sao chép mã đó vào pom.xml của bạn:

<!-- Disable default surefire based testing -->
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.20</version>
  <configuration>
    <skip>true</skip>
  </configuration>
</plugin>

<plugin>
  <groupId>com.github.marks-yag</groupId>
  <artifactId>punner-maven-plugin</artifactId>
  <version>${version}</version>
  <configuration>
  </configuration>
  <executions>
    <execution>
      <id>test</id>
      <phase>test</phase>
      <goals>
        <goal>test</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Punner có thể chạy song song các phương pháp thử nghiệm, có thể giữ các đầu ra thử nghiệm riêng biệt và sạch sẽ.

Punner sẽ giảm đầu ra bảng điều khiển mvn của bạn, như sau:

[INFO] --- punner-maven-plugin:0.9.13:test (test) @ ipc ---
[INFO] Punner report directory: /Users/guile/workspace/ipc/target/punner-reports
[INFO]
[INFO] com.github.yag.ipc.IPCTest.testConnectionHandler.............. PASSED
[INFO] com.github.yag.ipc.IPCTest.testSequence....................... PASSED
[INFO] com.github.yag.ipc.IPCTest.testPartialContent................. PASSED
[INFO] com.github.yag.ipc.IPCTest.testResponseContent................ PASSED
[INFO] com.github.yag.ipc.IPCTest.testPingPong....................... PASSED
[INFO] com.github.yag.ipc.IPCTest.testServerClose.................... PASSED
[INFO] com.github.yag.ipc.IPCTest.testServerSideHeartbeatTimeout..... PASSED
[INFO] com.github.yag.ipc.IPCTest.testClientSideHeartbeatTimeout..... PASSED
[INFO] com.github.yag.ipc.IPCTest.testClientSideHeartbeat............ PASSED
[INFO] com.github.yag.ipc.IPCTest.testClientReconnect................ PASSED
[INFO]
[INFO] Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.952 sec, Time saved: 25.919 sec.

Punner tạo ra các đầu ra tương thích chắc chắn, bạn cũng có thể lấy dữ liệu nhật ký thô và báo cáo định dạng đánh dấu từ thư mục báo cáo:

  ipc git:(develop) ll target/punner-reports
total 104
-rw-r--r--   1 guile  staff    11K Oct 15 23:07 TEST-com.github.yag.ipc.IPCTest.xml
-rw-r--r--   1 guile  staff   298B Oct 15 23:07 com.github.yag.ipc.IPCTest.txt
drwxr-xr-x  12 guile  staff   384B Oct  8 00:50 logs
-rw-r--r--   1 guile  staff    33K Oct 15 23:07 report.md

Punner là dự án cá nhân của tôi, tôi viết Punner để tăng tốc giai đoạn kiểm thử đơn vị của một số dự án khác như khuôn khổ IPC, khóa chi tiết, dịch vụ tạp chí, công cụ quy trình công việc phân tán, v.v. Nó tiết kiệm rất nhiều thời gian chờ đợi của tôi.

Punner chưa hỗ trợ một số tính năng nâng cao. Tôi rất vui nếu bạn có thể thử nó và cho tôi một số phản hồi.


-3

Bạn có thể thay đổi thử nghiệm của mình thành thử nghiệm TestNg trong một phút (bạn chỉ cần thay đổi nhập khẩu), TestNG là tốt nhất trong thử nghiệm song song.


-3

Bạn có thể thử Gridgain cho phép bạn chạy phân phối các thử nghiệm của mình trên một lưới điện toán.


1
Tôi đã thử giải pháp GridGain và gặp hai vấn đề lớn. Đầu tiên, bạn phải yêu cầu GridGain loại trừ khỏi classpath của nhiệm vụ lưới của bạn bất kỳ thứ gì mà GridGain cũng sử dụng, ví dụ như Spring và rất nhiều thứ của Apache Commons. Thứ hai, classloading mạng, trong khi một ý tưởng tuyệt vời, không làm việc cho thư viện mà muốn tìm kiếm classpath, ví dụ như mùa xuân
Graham Lea
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.