Bir Maven yapısında paralel olarak junit testleri mi çalıştırıyorsunuz?


110

JUnit 4.4 ve Maven kullanıyorum ve çok sayıda uzun süredir devam eden entegrasyon testim var.

Paralelleştirme test takımlarına gelince, her test yöntemini tek bir test sınıfında paralel olarak çalıştırmama izin veren birkaç çözüm var. Ancak bunların hepsi testleri bir şekilde değiştirmemi gerektiriyor.

X iş parçacığında paralel olarak X farklı test sınıfları çalıştırmanın çok daha temiz bir çözüm olacağını düşünüyorum. Yüzlerce testim var, bu yüzden bireysel test sınıflarını işlemek gerçekten umurumda değil.

Bunu yapmanın bir yolu var mı?

Yanıtlar:


75

Maven eklentisini kullanın:

<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>, Junit 4.7 veya sonraki bir sürümünü kullanıyorsanız surefire tarafından desteklenmektedir. surefire guide
jontejj

42

Junit 4.7'den itibaren TestNG kullanmadan testleri paralel olarak çalıştırmak artık mümkün. Aslında 4.6'dan beri mümkün, ancak 4.7'de bunu uygulanabilir bir seçenek haline getirecek bir dizi düzeltme var. Burada okuyabileceğiniz yay ile paralel testler de yapabilirsiniz.


1
Bağlantılı sayfada "çoğu çift çekirdekli çözüm için, paralel iş parçacıklarıyla çalışmak hiçbir zaman iş parçacıklı olmayan çalıştırmadan daha hızlı değildir" diyor. Hala durum bu mu?
Raedwald

2
Testleriniz herhangi bir IO yaparsa, yine de fayda sağlayacağını düşünüyorum. Örneğin, birim testleriniz daha çok entegrasyon testleri gibiyse ve veritabanına isabet ederse, paralel olarak çalıştırmak onları hızlandırmalıdır.
Dave

@Raedwald Dont , kısa io-bağımlı olmayan birim testleri için çok fazla şey beklemiyor , söylemeye çalıştığım şey. Surefire'ın daha yeni sürümleri de yayında anlatılan 2.5'ten daha iyi / daha verimlidir, bu nedenle biraz daha iyi sonuçlar elde edebilirsiniz.
krosenvold

3
Bunun mümkün olduğunu söylüyorsunuz, ancak nasıl yapılacağına dair bir açıklamaya bir bağlantı ekleyebilir misiniz? İkinci bağlantınız,
Cory Kendall 15

@krosenvold bağlantı? Yerleşik bir çözüm bulmakta zorlanıyorum.
Ilan Biala

10

JUnit'in deneysel ParallelComputer çalıştırıcısından esinlenerek kendi ParallelSuite ve ParallelParameterized koşucularımı oluşturdum. Bu koşucular kullanılarak, test takımları ve parametreli testler kolayca paralel hale getirilebilir.

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);
                }
            }
        });
    }
}

Kullanımı basittir. @RunWith annotations değerini bu Parallel * sınıflarından birine değiştirin .

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

5

tempus-fugit benzer bir şey sunar, ayrıntılar için belgelere bakın. JUnit 4.7'ye dayanır ve siz sadece testinizi işaretleyin @RunWith(ConcurrentTestRunner).

Şerefe


3

Açık kaynak kitaplığı - Test Yük Dengeleyicisini kontrol edebilirsiniz . Tam olarak istediğiniz şeyi yapar - paralel olarak farklı test sınıfları çalıştırın. Bu, ant-junit seviyesinde bütünleşir, böylece testlerinizi herhangi bir şekilde değiştirmeniz gerekmez. Ben kütüphanenin yazarlarından biriyim.

Ayrıca, işlem düzeyinde bir korumalı alana ihtiyacınız olabileceğinden bunları iş parçacıklarında çalıştırmamayı düşünün. Örneğin, entegrasyon testlerinizde bir DB'ye ulaşıyorsanız, başka bir test farklı bir iş parçacığına bazı veriler eklediğinden bir testin başarısız olmasını istemezsiniz. Çoğu zaman testler bu akılda tutularak yazılmaz.

Son olarak, bu sorunu şimdiye kadar nasıl çözdük?


2

TestNG bunu yapabilir (bu benim ilk refleksimdi - sonra zaten birçok test vakası olduğunu gördüm).

JUnit için, parallel-junit'e bakın .


3
Ne yazık ki sorduğum sorunun cevabı bu değil. parallel-junit yalnızca tek bir test sınıfı içinde çalışır. TestNG ayrıca yalnızca tek bir sınıfta çalışır ve benim testlerim TestNG testleri değildir.
krosenvold

@PlatinumAzure: Bağlantıyı güncelledim. Bu projenin nasıl sürdürüldüğünü bilmiyorum. Son zamanlarda birkaç makinede junit testlerinin yürütülmesini dağıtmak için başka bir soru soruldu .
philant

2

Junit tarafından sağlanan ParallelComputer'ı kullanarak testleri paralel olarak çalıştırabilirsiniz. İşte başlamanız için küçük bir pasaj.

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

Bu, Maven veya diğer derleme yönetim araçlarına bağımlılığı olmadığı için koddan testler çalıştırmanız gerektiğinde yardımcı olacaktır.

Lütfen bunun tüm test durumlarını paralel olarak çalıştıracağını unutmayın; farklı test senaryoları arasında herhangi bir bağımlılığınız varsa bu yanlış pozitiflerle sonuçlanabilir. Zaten birbirine bağlı testlere sahip OLMAMALISINIZ.


0

Başka bir seçenek: Punner, yeni bir paralel koşucu ve maven eklentisi. Kodunuzu değiştirmeniz gerekmez, pom.xml dosyanıza kopyalamanız gerekmez:

<!-- 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, test yöntemlerini paralel olarak çalıştırabilir, test çıktılarını ayrı ve temiz tutabilir.

Punner, mvn konsol çıktılarınızı şu şekilde azaltacaktır:

[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, surefire uyumlu çıktılar üretir, ayrıca ham günlük verilerini ve raporlar dizininden bir fiyat indirimi formatı raporu alabilirsiniz:

  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 benim kişisel projem, Punner'ı IPC çerçevesi, ince ayarlı kilitleme, günlük hizmeti, dağıtılmış iş akışı motoru vb. Gibi diğer bazı projelerin birim test aşamasını hızlandırmak için yazdım. Bekleme zamanımdan çok tasarruf sağladı.

Punner henüz bazı gelişmiş özellikleri desteklemiyor. Bunu deneyip bana geri bildirimde bulunursanız çok mutluyum.


-3

Testinizi bir dakika içinde TestNg testi olacak şekilde değiştirebilirsiniz (yalnızca içe aktarmaları değiştirmeniz gerekir), TestNG paralel testte en iyisidir.


-3

Testlerinizi bir hesaplama ızgarasına dağıtmanıza izin veren Gridgain'i deneyebilirsiniz .


1
GridGain çözümünü denedim ve iki büyük sorunla karşılaştım. İlk olarak, GridGain'e grid görevinizin sınıf yolundan GridGain'in de kullandığı her şeyi, örneğin Spring ve birçok Apache Commons malzemesini hariç tutmasını söylemelisiniz. İkincisi, ağ sınıf yükleme harika bir fikir olsa da, sınıf yolunda arama yapmak isteyen kütüphaneler için işe yaramaz, örneğin Bahar
Graham Lea
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.