QA Interview Hub · База знань · Тести

Java: основи

Тестовий проєкт

Maven: pom.xml, scope, Surefire і Failsafe, запуск тестів

Maven збирає проєкт за описом у pom.xml: координати (groupId, artifactId, version), залежності, плагіни, властивості. Стандартна структура: src/main/java, src/test/java, src/test/resources. Для проєкту лише з тестами код лежить у src/test.

  • Залежність зі <scope>test</scope> доступна лише при компіляції й запуску тестів і не потрапляє в артефакт. Тестові бібліотеки (JUnit, AssertJ, REST Assured) мають такий scope.
  • Версії виносять у <properties> або BOM (dependencyManagement), щоб не розходились. mvn dependency:tree показує, звідки прийшла конфліктна версія.
  • Життєвий цикл: validate → compile → test → package → verify; команда виконує всі фази до вказаної. Тому mvn verify запускає й тести Failsafe.

Surefire запускає unit-тести у фазі test (за замовчуванням класи *Test, Test*, *Tests, *TestCase). Failsafe призначений для інтеграційних тестів (*IT, IT*, *ITCase); його цілі integration-test і verify. Збій не зупиняє збірку одразу, тож фаза post-integration-test (зупинка тестового середовища) таки виконається, а результат перевіряє verify. Запускайте mvn verify, а не mvn integration-test. У проєктах автоматизації UI/API часто використовують лише Surefire, а Failsafe — коли тести йдуть після підняття сервісів.

Корисні запуски:

mvn test -Dtest=LoginTest                 # один клас
mvn test -Dtest=LoginTest#validLogin      # один метод
mvn test -Dgroups=smoke                   # теги JUnit 5/6 / групи TestNG
mvn test -DexcludedGroups=slow
mvn verify -Pstaging -Dbrowser=firefox    # профіль і системна властивість
mvn -DskipTests package                   # компілює тести, але не запускає
mvn -Dmaven.test.skip=true package        # навіть не компілює тести

Профіль (<profile>) змінює залежності, властивості чи конфігурацію плагіна для оточення. Користувацькі властивості з -D Surefire передає у процес тестів, тож у коді вони доступні через System.getProperty("browser", "chrome").

Gradle коротко, конфігурація через property та env, логування SLF4J

Gradle — альтернатива Maven зі скриптом build.gradle (Groovy) чи build.gradle.kts (Kotlin). Те саме: залежності, плагіни, завдання. Відмінності для автоматизатора:

  • скрипт — код, тому гнучкіший, але важче читається; є інкрементальна збірка й кеш;
  • JUnit 5 вмикається явно: tasks.test { useJUnitPlatform() }; теги — useJUnitPlatform { includeTags("smoke") };
  • запуск: ./gradlew test --tests "*LoginTest"; gradlew (wrapper) фіксує версію інструмента, як і mvnw у Maven. Користуйтеся wrapper, а не встановленим глобально Gradle/Maven.

Конфігурація тестів. Не зашивайте URL, браузер і облікові дані в код. Зазвичай шари такі: значення за замовчуванням у файлі .properties → перевизначення системними властивостями (-Dbase.url=...) → змінні оточення для секретів (System.getenv("API_TOKEN")). Системну властивість Maven Surefire передає в тести, а Gradle її треба явно прокинути у завданні test. Секрети в CI беруться зі сховища секретів, а не з репозиторію, й не друкуються в лог.

Логування через SLF4J. SLF4J — фасад: код пише в org.slf4j.Logger, а реальну роботу виконує реалізація (Logback, Log4j 2) на classpath. Має бути одна реалізація, інакше попередження про кілька binding.

private static final Logger log = LoggerFactory.getLogger(CheckoutTest.class);

log.info("Order {} created for user {}", orderId, userId);   // а не "..." + orderId
log.error("Checkout failed for order {}", orderId, exception); // виняток останнім аргументом
  • Плейсхолдери {} форматують повідомлення лише тоді, коли рівень увімкнений, на відміну від конкатенації, що збирає рядок завжди.
  • Не використовуйте System.out.println: немає рівнів, часу й файлового виводу.
  • Не логуйте паролі й токени. Рівнем (INFO у CI, DEBUG локально) керують у logback-test.xml.
  • З Lombok достатньо @Slf4j.