Как убедиться, что TestNG последовательно запускает методы на тестовых классах вместо чередования?

Ситуация и проблема

У меня есть несколько тестовых классов, каждый из которых имеет несколько методов тестирования. Все тесты используют одну и ту же тестовую базу данных в фоновом режиме. Каждый тестовый класс инициализирует содержимое базы данных, а затем проверяет содержимое в нескольких методах тестирования.

Когда я запускаю каждый тест по отдельности, все они проходят. Но когда я запускаю несколько тестов одновременно (используя maven или мою IDE, IntelliJ), методы разных классов тестов выполняются чередующимися, например. инициализация базы данных второго класса запускается после запуска первого класса, но до того, как все тестовые методы первого класса были запущены, поэтому эти методы потерпят неудачу (поскольку база данных уже содержит данные второго класса).

Некоторые вещи, которые я пробовал, и еще несколько деталей

Простейшим решением было бы заставить бегун TestNG последовательно запускать классы (т.е. дождаться завершения всех тестовых методов тестового класса до запуска методов тестирования другого класса). Это можно сделать?

Возможно, я могу сделать это, указав каждый класс в качестве отдельного теста в моем пакете, но я не хочу этого делать, поскольку это означает, что я должен добавить что-то в пакет, когда добавляю тестовый класс, который неуклюжий и подверженный ошибкам.

Просто попросить TestNG не распараллеливать что-либо (например, установить количество потоков в 1 или отключить параллельный запуск) здесь не помогает, поскольку методы все равно запускаются в неправильном порядке (хотя и не одновременно).

Один из вариантов - использовать другую базу данных для каждого тестового класса, но я не вижу простого способа сделать это (используя JPA и Guice).

В настоящее время я не использую DBUnit, Unitils и т.д.; Я не очень хорошо знаю эти инструменты, но у меня создалось впечатление, что я не решаю свои проблемы.

Я использую JPA для инициализации базы данных в каждом тестовом классе (т.е. создавать объекты сущности и создавать их).

Ответ 1

Даже в последовательном режиме TestNG может чередовать методы тестирования из одного и того же пакета. Он гарантирует последовательность @BeforeClass → @Test → @AfterClass, но он может сделать что-то вроде:

before class1
    test class1.method1
before class2
    test class2.method1
    test class1.method2
after class1
    test class2.method2
after class2

Решение состоит в том, чтобы заставить каждый класс использовать другой набор (который выполняется по-настоящему последовательно). Начиная с версии 2.16, плагин maven surefire помещает каждый класс в отдельный набор, чтобы проблема была исправлена.

С другой стороны, IDEA (даже последние 13 EAP) генерирует xml файл со всеми классами в одном и том же пакете. Надеюсь, ИДЕА последует этому примеру и исправит это. Промежуточные тесты - это showstopper при работе с общими ресурсами, такими как базы данных.

Ответ 2

TestNG предлагает несколько параллельных стратегий. Похоже, что methods слишком агрессивен для ваших нужд, но вы посмотрели на classes или, может быть, instances?

Ответ 3

пришел с аналогичной проблемой. Я думаю, что group-by-instance = "true" может быть решением.

Ответ 5

Используйте метод перехватчиков (= запись и включение пользовательского) для управления порядком.

Кроме того, каждый класс может использовать свою собственную изолированную программную среду базы данных: возможно, может помочь упаковка каждого тестового класса в транзакцию.

Имея индивидуальный суффикс для таблиц /db, настроенных для каждого класса, пусть даже ваши тестовые методы будут работать параллельно (я думаю, что первые два варианта не будут).

Ответ 6

Я бы не использовал dependOnGroups на уровне класса, потому что, если какой-либо метод тестирования в любом из классов, в котором вы зависете, не работает, он не будет запускать ваш класс вообще... Это реальный недостаток использования 'dependOn '(или методы). Сначала я попытался бы просто установить @Test (group = thisClassName) на уровне класса, а затем идентифицировать класс с тестовым тегом в файле testng.xml. Затем контролируйте порядок выполнения ваших классов в xml как список этих тестов. Я считаю, что вам может потребоваться также установить PreserveOrder = "True" на следующем теге более высокого уровня в xml. Я бы избегал использования dependOn, за исключением случаев, когда он действительно нужен для зависимостей, но не для контроля порядка. Надеюсь это поможет. -JR

Ответ 7

Мы столкнулись с этой проблемой, большинство людей говорят, что это вызвано использованием dependOn, но наше решение просто устанавливало приоритеты на тестовом уровне для некоторых наших тестов. Я настроил Test Listener, чтобы переориентировать наши тесты, чтобы они работали в правильном порядке. Это основано на решении сабердука в https://github.com/cbeust/testng/issues/106

Это решение сохранит приоритет теста, объединив его с приоритетом класса.

package testng_Listeners;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import org.testng.IAnnotationTransformer;
import org.testng.Reporter;
import org.testng.annotations.ITestAnnotation;

//Listener to fix TestNG Interleaving issue. I had to re-write this as the original example I had did not allow for priority to be manually set on a test level.
public class RePrioritizingListener implements IAnnotationTransformer {

HashMap<Object, Integer> priorityMap = new HashMap<Object, Integer>();
Integer class_priorityCounter = 10000;
// The length of the final priority assigned to each method.
Integer max_testpriorityLength = 4;

@Override
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {


// class of the test method.
Class<?> declaringClass = testMethod.getDeclaringClass();
// Current priority of the test assigned at the test method.
Integer test_priority = annotation.getPriority();
// Current class priority.
Integer current_ClassPriority = priorityMap.get(declaringClass);

if (current_ClassPriority == null) {
    current_ClassPriority = class_priorityCounter++;
    priorityMap.put(declaringClass, current_ClassPriority);
}

String concatenatedPriority = test_priority.toString();

// Adds 0 to start of this number.
while (concatenatedPriority.length() < max_testpriorityLength) {
    concatenatedPriority = "0" + concatenatedPriority;
}

// Concatenates our class counter to the test level priority (example
// for test with a priority of 1: 1000100001; same test class with a
// priority of 2: 1000100002; next class with a priority of 1. 1000200001)
concatenatedPriority = current_ClassPriority.toString() + concatenatedPriority;

//Sets the new priority to the test method.
annotation.setPriority(Integer.parseInt(concatenatedPriority));

String printText = testMethod.getName() + " Priority = " + concatenatedPriority;
Reporter.log(printText);
System.out.println(printText);

}
}

Также вам нужно добавить слушателя к вашему testng.xml

<suite name="Suite" configfailurepolicy="continue" >
<listeners>
<listener class-name="testng_Listeners.RePrioritizingListener"></listener>
</listeners>