Як запустити тест Gradle, коли всі тести ДОСЛІДЖЕНІ?


130

У мене налаштований сценарій оцінки. Коли я виконую збірку Gradle, все працює і він виконує тести jUnit.

Після цього, коли я запускаю тест Gradle, я отримую наступне:

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

Коли я виконую gradle clean, то Gradle будує роботи, звичайно ... Я хочу мати змогу скинути лише тести, а не будувати весь проект: як мені це зробити?


3
Це видається непотрібним, виходячи з наведеної інформації. Якщо ні код програми, ні тестовий код не змінилися, чому потрібно повторно запускати тести?
Jolta

10
@Jolta Деякі тести в моєму коді пов'язані на сторонніх введеннях, я запускаю свої тести не лише для того, щоб переконатися, що я не вставив помилку в код, а також, щоб перевірити, чи щось змінилося на сторонніх входах що я отримую
USer22999299

4
Вибачте, що вибагливі, але я не думаю, що це правильний спосіб думати з цього приводу: якщо у вас є змінні тристоронні введення, чи не правильний спосіб впоратися з цим, щоб якось знущатися над цими входами? Тестування насправді має стосуватися тестування коду, який ви пишете. Хіба ви не є досить очевидною загрозою отримання помилкових позитивних результатів, якщо ви покладаєтесь на те, що сторонній вхід буде неприйнятним? Чи не повинна стратегія забезпечувати введення проблем як частини коду вашої програми?
мійський гризун

9
@mikerodent розглянемо можливість перевірити свій код на сторонній онлайн-службі. Ви хочете відслідковувати можливі зміни в сервісному інтерфейсі API, щоб мати можливість реагувати на розгорнуті виправлення ASAP. Чи не тести на ІП є гарним способом зробити це? Використання макету лише скаже вам, що ваш власний код не має регресій, але залежності все-таки можуть змінитися. використання реальної послуги означатиме, що ваш продукт може реально виконувати очікувані операції в поточному середовищі.
Еліст

5
Це також справедливо з точки зору інтеграційного тестування, де суть тесту полягає у валідації інтеграції вашого коду з іншими бітами коду, де не було б доречно знущатися в залежності
1800 ІНФОРМАЦІЯ

Відповіді:


171

Одним із варіантів було б використання --rerun-tasksпрапора в командному рядку . Це повторило б усе тестове завдання і всі завдання, від яких залежить.

Якщо ви зацікавлені лише у повторному проведенні тестів, ще одним варіантом було б зробити градле очищення результатів тестів перед його виконанням. Це можна зробити за допомогою cleanTestзавдання.

Деяке тло - плагін Java визначає чисті завдання для кожного з інших завдань. Відповідно до документації :

cleanTaskName - Видаляє файли, створені за вказаною задачею. cleanJar видалить файл JAR, створений завданням jar, а cleanTest видалить результати тесту, створені тестовим завданням.

Тому все, що вам потрібно для повторного запуску тестів, це також виконати cleanTestзавдання, тобто:
gradle cleanTest test


3
gradle cleanTest testне повторює тести, він очищає їх вихід, але testзавдання все одно отримає результати тестування з кешу - див. github.com/gradle/gradle/isissue/9153
dan.m був користувач2321368

3
Коментар вище правильний. Але якщо ви користуєтесь --no-build-cache, то це буде працювати, як очікувалося, наприклад gradle cleanTest test --no-build-cache.
vRallev

51

Іншим варіантом буде додати наступне у своєму build.gradle:

test.outputs.upToDateWhen {false}

1
Я використав цю техніку для funcTestзавдання, яке створив для запуску функціональних тестів.
pharsicle

4
Це набагато кращий підхід, ніж прийнята відповідь, оскільки він буде застосований лише до потрібного завдання. upToDateWhenМоже бути використаний в будь-який «коду керованої» , як наприклад, системні властивості, змінні оточення, властивості проекту і т.д.
mkobit

1
Як згадується відповідь stackoverflow.com/a/52484259/340175 , є корисна публікація в блозі blog.gradle.org/stop-rerunning-tests, яка пояснює, чому такий підхід не рекомендується як загальний підхід. Однак я погоджуюся, що це може бути корисним і не дозволяє досягти того, що задається питанням.
JulianHarty

Так, це датований відповідь, коли я писав, що цей Gradle був у версії 2.11 і тільки почав бути корисним, але все ще мав багато шорстких країв, які відшліфовані сьогодні.
Франтишек Хартман

1
Чудова відповідь !!! Здав його з допомогою параметра: gradle test -Prerun-tests. Код у build.gradle:if(project.hasProperty("rerun-tests")) { test.outputs.upToDateWhen {false} }
AlikElzin-kilaka


17

Про це нещодавно було темою у публікації до блогу Gradle. Зупиніть повторювати свої тести . В автор показаний приклад використанняoutputs.upToDateWhen { false } і пояснює , чому це не так:

Це фактично не примушує повторень

Те, що, напевно, хотів сказати автор цього фрагмента, - це "Завжди повторювати мої тести". Це не те, що робить цей фрагмент. Це лише позначить завдання застарілим, змусивши Gradle відтворити результат. Але ось справа, якщо кеш збірки увімкнено, Gradle не потрібно виконувати завдання для відтворення виводу. Він знайде запис у кеші та розпакує результат у вихідний каталог тесту.

Те саме стосується цього фрагмента:

test.dependsOn cleanTest

Gradle розпакує результати тесту з кешу збірки після того, як вихід очищений, тому нічого не буде повторено. Коротше кажучи, ці фрагменти створюють дуже дорогий не-оп.

Якщо ви зараз думаєте "Гаразд, я також відключу кеш", дозвольте сказати, чому ви не повинні.

Потім автор продовжує пояснювати, чому повторення деяких тестів є марною витратою часу:

Переважна більшість ваших тестів повинна бути детермінованою, тобто з однаковими вхідними даними вони повинні давати однаковий результат.

У кількох випадках, коли потрібно повторити тести, коли код не змінився, слід моделювати їх як вхідні дані. Ось обидва приклади з публікації в блозі, де показано додавання даних, тому завдання буде використовувати його під час його актуальної перевірки.

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

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

Рекомендую прочитати всю публікацію в блозі.


8
Це чудово звучить для конкретного випадку використання, про який ви говорите, але я пишу тести після розгортання проти живого зовнішнього веб-сервісу і просто трапляюсь використовувати джуніт та градель для цього. Код випробуваний не живе в репо, а насправді там немає ніякого «коду програми» , тому що я на самом деле тестування живої системи виробництва , а не сам код. Дякую за відповідь, це дуже корисно! Просто хотів би зазначити, що є додаткові випадки використання, які вимагають повторного тестування кожен раз, навіть якщо жоден із кодів gradle не знає про те, що змінюється
Брендон

11

Ось рішення, використовуючи файл "build.gradle", якщо ви не хочете змінювати свій командний рядок:

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

І ось вихід. Помітьте 2 зміни від попереднього результату:

1) У висновку з’являється нове завдання «cleanTest».

2) "Тест" завжди очищається (тобто ніколи не "ДО ДАВАННЯ"), тому він виконується щоразу:

$ 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
працює , cleanTestперш ніж testне буде повторно випробування, вона очищає свою продукцію, але тестове завдання буде ще отримати результати тестування з кешу - см github.com/gradle/gradle/issues/9153
даН.м був user2321368

8

--rerun-tasks працює, але є неефективним, оскільки повторює всі завдання.

cleanTest сама по собі може бути недостатньою через кеш нарощування.

Отже, найкращий спосіб досягти цього:

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

0

Крім того, додавання --rerun-tasksдійсно є зайвим. Ніколи не буває. Створіть --no-rerun-tasksі зробіть --rerun-tasksза замовчуванням колиcleanTask


-1

TL; DR

test.dependsOn cleanTest

2
За даними stackoverflow.com/a/52484259/466862 , це не працюватиме.
Марк Ротвевель

Що ж, документи gradle трохи заплутані .... Тут кажуть, що CleanTest можна використовувати для цієї мети. docs.gradle.org/current/userguide/… . А також, це працює на моїй машині (і gradle версія 4.10.3);)
Topera

-4

Я думаю, що це правильне запитання, враховуючи, що в Gradle можна запустити цю команду test, і що трапиться, це нічого не відбувається!

Але я б поставив під сумнів необхідність коли-небудь робити це, як сказала Джолта у своєму коментарі: якщо жоден код не змінився, чому вам потрібно повторно перевірити? Якщо у вас є сумніви щодо сторонніх даних, я б сказав, що вам потрібно погодитись у цьому коді додатка. Якщо у вас є стурбованість, що ваш код може бути "нечітким", тобто в змозі здати всі тести вперше, але не вдруге (або в 100-й раз), вам не потрібно думати, чому у вас виникають ці сумніви, і вирішити їх?

Особисто я вважаю, що це (дуже незначна) помилка дизайну в Gradle: якщо все повністю оновлено, а не збирається "БУДІВЛІ БЕЗПЕЧНО", це повинно сказати "НЕ ЗМІНА ВІД МІННОГО УСПІШНОГО БУДУВАННЯ: НІЧОГО СКЛАДАНО".


3
"чи не потрібно замислюватися над тим, чому у вас виникають ці сумніви, і вирішувати їх?": Так, але для того, щоб змусити дані подумати, я хотів би кілька разів провести тести і подивитися, що відбувається. Це так божевільно?
мссміт

1
@mikerodent Я частково згоден з вашою точкою. Існують "легкі" випадки, як правило, прості тести для одиниць білого ящика, де зміна коду не означає нічого реальної перевірки. Однак подумайте про тести із залежностями. "О так, докер не працював і т.д." Існують тести, де саме інфраструктура (і в розробленому вигляді) встановлює залежності (вони "надаються"), а не збірка. У цих випадках я завжди хочу мати можливість повторного запуску.
dbalakirev

@dbalakirev Так, це мені прийшло в голову ... але чи не варто вам вміти знущатися над роллю цих залежностей, таких як Докер ...? Я маю на увазі, якщо ти цього не робиш, чи не зберігаєш майбутніх проблем? Я не кажу, що я на 100% впевнений, але те, що, на мою думку, я кажу, що ваші тести повинні, в сумніві, ідеальніші, ніж у нас, покривати всі основи.
мійський гризун

Ви можете знущатися з так, з чим у вас є залежність (докер), що якщо не вдасться до вас, це означає, що ви хочете повторно запуститись, навіть якщо код не змінився. Я хотів би підкреслити, що ця думка не стосується тестів чи тестів, де 1. ви намагаєтесь уникнути залежностей 2. або принаймні знущатися над ними за допомогою тестових рамок, але коли вони дійсно "надаються", якщо ви хочете.
dbalakirev

2
__ якщо код не змінився, чому вам потрібно повторно перевірити? __ Ви чули про тести інтеграції?
Богдан Март
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.