Tüm testler GÜNCEL olduğunda Gradle testi nasıl çalıştırılır?


131

Not senaryomu oluşturdum. Gradle yapısını çalıştırdığımda, her şey çalışıyor ve jUnit testlerini çalıştırıyor.

Bundan sonra Gradle testini çalıştırdığımda aşağıdakileri alıyorum:

C:\Users\..\..\Project>gradle test
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE

Gerçekleştirdiğimde gradle clean, o zaman Gradle derleme çalışıyor, tabii ki ... Tüm projeyi inşa etmek değil, sadece testleri sıfırlayabilmek istiyorum: Bunu nasıl yapmalıyım?


3
Verilen bilgilere göre bu gereksiz görünüyor. Ne uygulama kodu ne de test kodu değişmediyse, testleri neden yeniden çalıştırmanız gerekiyor?
Jolta

10
@Jolta Kodumdaki bazı testler 3 partili girişlerle ilgili, testlerimi sadece kodun içine herhangi bir hata koymadığımdan emin olmak için değil, ayrıca 3 partili girişlerde bir değişiklik olup olmadığını kontrol etmek için çalıştırıyorum alıyorum
USer22999299

4
Nitelikli seçici olduğum için üzgünüm, ama bunun hakkında düşünmenin doğru yolu olduğunu gerçekten düşünmüyorum: eğer değişken 3 taraflı girdileriniz varsa, bu girdilerle bir şekilde dalga geçmek için bununla başa çıkmanın doğru yolu değil mi? Test, aslında yazdığınız kodu test etmekle ilgili olmalıdır. Kabul edilemez olması için 3 taraflı girdilere güveniyorsanız, yanlış pozitifler alma konusunda oldukça açık bir tehlikede değil misiniz? Strateji, uygulama kodunuzun bir parçası olarak sorunlu girişi karşılamak olmamalı mı?
mike rodent

9
@mikerodent, kodunuzu üçüncü taraf bir çevrimiçi hizmete karşı test etmeyi düşünün. En kısa sürede dağıtılan düzeltmelerle yanıt verebilmek için hizmet API'sindeki olası değişiklikleri izlemek isteyebilirsiniz. CI testleri bunu yapmanın iyi bir yolu değil mi? Bir taklit kullanmak size yalnızca kendi kodunuzun gerilemeye sahip olmadığını söyleyecektir, ancak bağımlılıklarda yine de değişiklikler olabilir. gerçek hizmetin kullanılması, ürününüzün mevcut ortamda beklenen işlemleri gerçekten gerçekleştirebileceğini gösterir.
Elist

5
Bu aynı zamanda, testin amacının kodunuzun diğer kod bitleri ile entegrasyonunu doğrulamak olduğu ve bağımlılıklarda alay etmenin uygun olmadığı bir entegrasyon testi bakış açısından da geçerlidir
1800 BİLGİ

Yanıtlar:


172

Bir seçenek --rerun-tasks, komut satırındaki bayrağı kullanmak olabilir . Bu, tüm test görevini ve bağlı olduğu tüm görevleri yeniden çalıştırır.

Yalnızca testleri yeniden yürütmekle ilgileniyorsanız, başka bir seçenek de testleri yürütmeden önce test sonuçlarını kademeli olarak temizlemektir. Bu, cleanTestgörev kullanılarak yapılabilir .

Bazı arka plan - Java eklentisi, diğer görevlerin her biri için temiz görevler tanımlar. Belgelere göre :

cleanTaskName - Belirtilen görev tarafından oluşturulan dosyaları siler. cleanJar, jar görevi tarafından oluşturulan JAR dosyasını siler ve cleanTest, test görevi tarafından oluşturulan test sonuçlarını siler.

Bu nedenle, testlerinizi yeniden çalıştırmak için ihtiyacınız olan tek şey cleanTestgörevi de çalıştırmaktır , yani:
gradle cleanTest test


3
gradle cleanTest testtestleri yeniden çalıştırmaz, çıktılarını temizler, ancak testgörev yine de test sonuçlarını önbellekten alır - bkz. github.com/gradle/gradle/issues/9153
dan.m,

3
Yukarıdaki yorum doğrudur. Ancak kullanırsanız --no-build-cache, beklendiği gibi çalışacaktır, örneğin gradle cleanTest test --no-build-cache.
vRallev

51

Diğer seçenek, build.gradle dosyanıza aşağıdakileri eklemektir:

test.outputs.upToDateWhen {false}

1
Bu tekniği funcTestfonksiyonel testleri çalıştırmak için oluşturduğum bir görev için kullandım .
pharsicle

4
Bu, yalnızca istenen göreve uygulanacağı için kabul edilen yanıttan çok daha iyi bir yaklaşımdır. upToDateWhenBöyle sistem özelliklerine, ortam değişkenleri, proje özelliklerine vb gibi herhangi bir "kod güdümlü" bir şekilde kullanılabilir
mkobit

1
Yanıt stackoverflow.com/a/52484259/340175'te belirtildiği gibi , bu yaklaşımın genel bir yaklaşım olarak neden önerilmediğini açıklayan yararlı bir blog yazısı blog.gradle.org/stop-rerunning-tests var. Bununla birlikte, yararlı olabileceğine ve sorunun sorduğu şeyi başaracağına katılıyorum.
JulianHarty

Evet, bu cevap tarihli, bu Gradle'ı 2.11 sürümündeydi ve kullanılabilir olmaya başladığında, ancak bugün cilalanan pek çok pürüzlü kenarları vardı.
František Hartman

1
Mükemmel cevap!!! Bir parametre kullanarak Geçti: gradle test -Prerun-tests. Build.gradle içindeki kod:if(project.hasProperty("rerun-tests")) { test.outputs.upToDateWhen {false} }
AlikElzin-kilaka


17

Bu, yakın zamanda Gradle'ın blog gönderisindeki konuydu Testlerinizi yeniden çalıştırmayı durdurun . Yazar kullanarak bir örnek gösterir outputs.upToDateWhen { false }ve neden yanlış olduğunu açıklıyor:

Bu aslında yeniden gösterimleri zorlamaz

Bu pasajın yazarının muhtemelen söylemek istediği şey "Testlerimi her zaman yeniden çalıştır" dır. Bu pasajın yaptığı şey bu değil. Yalnızca görevi güncelliğini yitirmiş olarak işaretler ve Gradle'ı çıktıyı yeniden oluşturmaya zorlar . Ancak önemli olan şu ki, yapı önbelleği etkinse, Gradle'ın çıktıyı yeniden oluşturmak için görevi çalıştırması gerekmez. Önbellekte bir giriş bulacak ve sonucu testin çıktı dizinine açacaktır.

Aynısı bu pasaj için de geçerlidir:

test.dependsOn cleanTest

Gradle, çıktı temizlendikten sonra test sonuçlarını derleme önbelleğinden çıkarır, böylece hiçbir şey yeniden çalıştırılmaz. Kısacası, bu parçacıklar çok pahalı bir işlemsizlik yaratıyor.

Şimdi “Tamam, önbelleği de devre dışı bırakacağım” diye düşünüyorsanız, neden yapmamanız gerektiğini söyleyeyim.

Ardından yazar, bazı testleri tekrar yapmanın neden zaman kaybı olduğunu açıklamaya devam ediyor:

Testlerinizin büyük çoğunluğu deterministik olmalıdır, yani aynı girdiler verildiğinde, aynı sonucu vermeleri gerekir.

Kodun değişmediği testleri yeniden çalıştırmak istediğiniz birkaç durumda, bunları bir girdi olarak modellemelisiniz. Aşağıda, görevin güncel kontrolleri sırasında kullanması için girdi eklemeyi gösteren blog gönderisinden iki örnek verilmiştir.

task randomizedTest(type: Test) {
  systemProperty "random.testing.seed", new Random().nextInt()
}

task systemIntegrationTest(type: Test) {
  inputs.property "integration.date", LocalDate.now()
}

Blog gönderisinin tamamını okumanızı tavsiye ederim.


8
Bu, bahsettiğiniz belirli kullanım durumu için harika görünüyor, ancak canlı bir harici web hizmetine karşı dağıtım sonrası testler yazıyorum ve bunu başarmak için sadece junit ve gradle'ı kullanıyorum. Test altındaki kod repo canlı değil ve aslında orada olduğunu aslında kod kendisi yerine bir canlı üretim sistemini test ediyorum çünkü hiçbir 'uygulaması kodu'. Cevabınız için teşekkürler, bu çok faydalı! Kod gradle'ın bilmediği kodların hiçbiri değişmese bile, testleri her seferinde yeniden çalıştırmayı gerektiren ek kullanım durumları olduğunu belirtmek istedim
Brandon

11

Komut satırınızı değiştirmek istememeniz durumunda, "build.gradle" dosyasını kullanan bir çözüm aşağıda verilmiştir:

test {
    dependsOn 'cleanTest'
    //Your previous task details (if any)
}

Ve işte çıktı. Önceki çıktınıza göre 2 değişikliğe dikkat edin:

1) Çıktıda yeni bir 'cleanTest' görevi görünür.

2) 'test' her zaman temizlenir (yani asla 'GÜNCEL'), bu nedenle her seferinde yürütülür:

$ gradle build
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:jar
:bootRepackage
:assemble
:cleanTest
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test
:check
:build

1
daha cleanTestönce testçalıştırmak testleri yeniden çalıştırmaz, çıktılarını temizler, ancak test görevi test sonuçlarını önbellekten almaya devam eder - bkz. github.com/gradle/gradle/issues/9153
dan.m was user2321368

8

--rerun-tasks çalışır, ancak tüm görevleri yeniden çalıştırdığı için verimsizdir.

cleanTest önbellek oluşturması nedeniyle tek başına yeterli olmayabilir.

bu nedenle, bunu başarmanın en iyi yolu:

./gradlew --no-build-cache cleanTest test

0

Ayrıca eklemek zorunda --rerun-taskskalmak gerçekten gereksizdir. Asla olmaz. Bir oluştur --no-rerun-tasksve --rerun-tasksvarsayılan yapcleanTask



-4

Bence bu, Gradle'da bu komutu çalıştırmanın mümkün olduğu göz önüne alındığında geçerli bir soru testve ne olursa olsun hiçbir şey olmuyor!

Ancak Jolta'nın yorumunda söylediği gibi, bunu yapma ihtiyacını sorgulayacağım: eğer hiçbir kod değişmediyse neden yeniden test etmeniz gerekiyor? Üçüncü taraf girdileri hakkında şüpheleriniz varsa, bunu uygulama kodunuzda karşılamanız gerektiğini söyleyebilirim. Kodunuzun "kesintili" olabileceğinden endişeleriniz varsa, yani tüm testleri ilk kez geçebilir ancak bir saniyede (veya 100. kez) geçemezseniz, neden bu şüpheleriniz olduğunu düşünmeniz ve bunları ele almanız gerekmez mi?

Şahsen ben bunun Gradle'da (çok küçük) bir tasarım hatası olduğunu düşünüyorum: eğer her şey tamamen güncelse, "BAŞARILI OLUŞTURUN" yerine "SON BAŞARILI YAPIDAN BERİ DEĞİŞİKLİK YOK: HİÇBİR ŞEY YAPILMADI" demeli.


3
"Neden bu şüphelere sahip olduğunuzu düşünmeniz ve bunları ele almanız gerekmiyor mu?": Evet, ancak verileri düşünmek için testleri birkaç kez çalıştırıp ne olacağını görmek istiyorum. Bu çok mu çılgın?
mhsmith

1
@mikerodent Söylediğinize kısmen katılıyorum. Hiçbir kod değişikliğinin gerçekten yeniden test edilecek hiçbir şey olmadığı tipik olarak basit beyaz kutu birim testleri gibi "kolay" durumlar vardır. Yine de bağımlılıkları olan testleri düşünün. "Ah evet, liman çalışmıyor vb." Bağımlılıkları kuranın (bunlar "sağlanır") yapı değil altyapının (ve geliştirmede) olduğu testler vardır. Bu durumlarda her zaman yeniden koşabilmeyi isterim.
dbalakirev

@dbalakirev Evet, bu benim başıma geldi ... ama Docker gibi bu bağımlılıkların rolüyle dalga geçmeniz gerekmez mi? Eğer Yani eğer değildir yapıyor gelecekte oluşabilecek sorunları kadar depolama değil,? % 100 emin olduğumu söylemiyorum ama sanırım söylediğim şey, bizimkinden şüphesiz daha ideal bir dünyada testlerinizin tüm temelleri kapsaması gerektiğidir.
mike rodent

Evet ile alay edebilirsiniz, bununla bir bağımlılığınız (docker) vardır, eğer size karşı başarısız olursa, kod değişmemiş olsa bile yeniden çalıştırmak istediğiniz anlamına gelir. Bu düşüncenin, 1. bağımlılıklardan kaçınmaya çalıştığınız birim testleri veya testler için olmadığını vurgulamak isterim. 2. veya en azından test çerçevesini kullanarak onlarla dalga geçtiğinizde, ama eğer isterseniz bunlar gerçekten "sağlandığında".
dbalakirev

2
__ hiçbir kod değişmediyse neden yeniden test etmeniz gerekiyor? __ Entegrasyon testleri hakkında bir şeyler duydunuz mu?
Bogdan Mart
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.