Як переконатися, що TestNG послідовно запускає методи на тестових класах замість чергування?

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

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

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

Деякі речі, які я спробував, і деякі деталі

Найпростішим рішенням було б змусити бігуна TestNG запускати класи послідовно (тобто. Дочекатися, поки всі методи тестування тестового класу закінчаться перед запуском методів тестування іншого класу). Чи можна це зробити?

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

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

Одним з варіантів було б використовувати іншу базу даних для кожного тестового класу, але я не бачу простий спосіб зробити це (використовуючи JPA і Guice).

Зараз я не використовую DBUnit, Unitils і т.д .; Я не знаю цих інструментів дуже добре, але у мене склалося враження, що вони не вирішують мої проблеми.

Я використовую JPA, щоб ініціалізувати базу даних у кожному тестовому класі (тобто створювати об'єкти об'єктів і керувати ними).

11
Я думаю, що принаймні частина проблеми полягає в тому, що кілька класів мають методи, які називаються testPrepareDb та іншими методами, позначеними @Test (dependOnMethods = "testPrepareDb") . Коли декілька таких класів виконуються як частина одного тесту, здається, що всі залежні методи виконуються лише після запуску всіх testPrepareDb методів, що в моєму випадку є неправильним. В основному, я б просто хотів, щоб мої тестові класи автоматично переводилися на окремі тести TestNG без необхідності явно вказувати їх як у комплекті xml.
додано Автор mazi, джерело

7 Відповіді

Even in sequential mode TestNG could interleave test methods from the same suite. It does guarantee the sequence @BeforeClass -> @Test -> @AfterClass but it can do something like:

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-файл з усіма класами в тому ж самому пакеті. Сподіваюся, що ідея буде йти за ним і виправити це теж. Переміщені тести є стриппером при роботі з спільними ресурсами, такими як бази даних.

5
додано
Не потрібна спеціальна конфігурація. Я не використовую XML-файли або що-небудь подібне. Я просто вказую шаблони файлів у надійній конфігурації. ОНОВЛЕННЯ: Я також виправлений testng для виконання класів послідовно і виправити все це в корені, але він ще не готовий до тягнути запит.
додано Автор Bogdan Calmac, джерело
Це також не працює для мене, і я використовую надійний 2.17. Я думаю, що це питання може бути, як описано в його коментарі під його оригінальним запитанням - якщо у вас є кілька методів з однаковою назвою, навіть на різних класах, і ви залежите від одного з них, TestNG розглядає це як залежність від усіх їх. Це припущення, хоча, як я вже munged всі мої взаємозалежні методи разом, щоб обійти це і не вистачає часу, щоб досліджувати далі.
додано Автор Dan King, джерело
Дякуємо за пораду про нову функцію в 2.16! Я не можу здатися, щоб змусити його працювати, хоча; потрібна якась спеціальна конфігурація? Параметри паралельних і т.д. не здається доречним (і, здається, для JUnit так чи інакше).
додано Автор mazi, джерело

TestNG пропонує кілька паралельних стратегій. Схоже, що методи занадто агресивні для ваших потреб, але ви дивилися на класи або, можливо, екземпляри ?

1
додано
Налаштування багатопоточності не допоможе, оскільки потрібна стратегія - це "запускати методи паралельно, якщо вони належать до одного класу". Він недоступний.
додано Автор patrungel, джерело
Раніше я спробував false ; тепер я спробував методи , класи і тести ( екземпляри , здається, не є дійсним). Ніхто не допомагає. Як я вже писав, проблема полягає не в паралелізації, а в упорядкуванні.
додано Автор mazi, джерело

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

0
додано

Я написав статтю, що обговорює деякі способи послідовних тестів у TestNG:

http://ancient-marinator.blogspot.com /2013/05/on-testing-scheduling-your-tests.html

Naturally, the best source for information is at home: http://testng.org/doc/index.html

0
додано
Єдине замовлення, яке потрібно застосувати в TestNG - це поставити @Test (groups = "test1") на початку першого класу, @Test (groups = "test2", dependOnGroups = "test1") і т.д. для кожного класу послідовно. Це дозволить серіалізувати запуск на основі класу.
додано Автор Bob Dalgleish, джерело
@BobDalgleish - але це означає, що ви повинні поставити всі ваші тести на групи. Що ще більш важливо, це також означає, що ви не можете запустити один клас на своєму власному рівні, без виконання іншого класу.
додано Автор Dan King, джерело
Спасибі, це хороший блог. Це дуже загальне, хоча і не стосується моєї конкретної проблеми.
додано Автор mazi, джерело

We were running into this same issue, most people say it's caused by using dependsOn, but our solution was just setting priorities at a test level for some of our tests. I set up a Test Listener to re-prioritize our tests so that they run in the correct order. This is based on saberduck's solution in 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 priorityMap = new HashMap(); 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's 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





0
додано

Використовуйте перехоплювачі методів (= запишіть та ввімкніть користувацький), щоб керувати впорядкованістю.

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

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

0
додано

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

0
додано