Из одного списка ввода я делаю уникальные наборы входов. Все наборы должны работать параллельно, но сам каждый набор должен запускать тест последовательно, с перестановками набора в качестве входных данных для теста.
Как это настроено:
DataProvider принимает список устройств (количество устройств варьируется). Это делает наборы устройств n-размера, скажем, 3 устройства на набор. Каждый набор устройств вводится для одного и того же заводского метода для одного и того же контрольного примера. (Эта часть должна быть параллельной). Затем метод Factory делает перестановки этого набора и выполняет тестовый пример для каждой перестановки. (Эта часть должна быть последовательной)
Например:
Список устройств в качестве входных данных для DP: {A, B, C, D, E, F}
DP создает наборы из 3 устройства: {A, B, C} и {D, E, F}
{A, B, C} вводятся для фабрики. Фабрика производит: {A, B, C}, {B, C, A} и {C, A, B}.
Тестовый набор должен сначала выполняться для: A, B, C
Затем тестовый пример должен выполняться снова для B, C, A
и запускаться в последний раз для C, A, B
Параллельно
{D, E, F} вводится для той же Фабрики, что и выше. Фабрика делает: {D, E, F}, {E, F, D} и {F, D, E}
Как и выше, тестовый случай последовательно перебирает перестановки.
Что я ожидается, что каждая фабрика работает в потоке, и что каждая фабрика делает перестановки и запускает перестановки последовательно. Заводы должны работать параллельно.
Первый вопрос: Возможно ли это? Я все еще довольно новичок в TestNG, так что, возможно, это не так.
Второй вопрос: (зависит от OnQuestion = "Первый вопрос") - Как? Я мог бы не структурировать это наилучшим образом, как есть. Использование потоков возможно, но похоже, что TestNG уже должен это обрабатывать.
В XML я пытался изменить то, что выполняется параллельно. Для сюиты все это 1 поток (не удивительно). Для теста это только 1 отдельный поток. Для классов это создает отдельные потоки для каждого метода @ Test-annotated, но последний поток запускает все остальные методы. Methods запускает каждый метод в одном из 3 потоков, выделенных в XML, но каждая фабрика все еще находится в одном «основном» потоке. Конечно, если я просто удаляю параллельный параметр, все работает в одном потоке. Группировка по экземплярам должна быть истинной, поэтому каждый шаг T C выполняется до запуска следующего экземпляра T C. Я также играю со структурой - если я найду решение, я выложу обновление.
//with parallel "tests"
DP thread: main
Creating a permutation from: A, B, C
Factory thread: main
Set: A, B, C
Set: B, C, A
Set: C, A, B
Creating a permutation from: D, E, F
Factory thread: main
Set: D, E, F
Set: E, F, D
Set: F, D, E
TestNG-tests-1: step 1
TestNG-tests-1: step 2
TestNG-tests-1: step 3
TestNG-tests-1: step 4
TestNG-tests-1: step 1
TestNG-tests-1: step 2
TestNG-tests-1: step 3
TestNG-tests-1: step 4
(repeats 4x)
//with parallel "classes"
DP thread: main
Creating a permutation from: A, B, C
Factory thread: main
Set: A, B, C
Set: B, C, A
Set: C, A, B
Creating a permutation from: D, E, F
Factory thread: main
Set: D, E, F
Set: E, F, D
Set: F, D, E
TestNG-test=Dev test-1: step 1
TestNG-test=Dev test-2: step 2
TestNG-test=Dev test-3: step 3
TestNG-test=Dev test-3: step 4
TestNG-test=Dev test-3: step 1
TestNG-test=Dev test-3: step 2
TestNG-test=Dev test-3: step 3
TestNG-test=Dev test-3: step 4
(repeats 4x with thread 3 running remaining iterations)
Ожидаемый / желаемый вывод:
DP thread: main
Creating a permutation from: A, B, C
Factory thread: 1
Set: A, B, C
Set: B, C, A
Set: C, A, B
Creating a permutation from: D, E, F
Factory thread: 2
Set: D, E, F
Set: E, F, D
Set: F, D, E
TestNG-test=Dev test-1: step 1
TestNG-test=Dev test-1: step 2
TestNG-test=Dev test-1: step 3
TestNG-test=Dev test-1: step 4 //completed TC for A, B, C
TestNG-test=Dev test-1: step 1
TestNG-test=Dev test-1: step 2
TestNG-test=Dev test-1: step 3
TestNG-test=Dev test-1: step 4 //completed TC for B, C, A
TestNG-test=Dev test-1: step 1
TestNG-test=Dev test-1: step 2
TestNG-test=Dev test-1: step 3
TestNG-test=Dev test-1: step 4 //completed TC for C, A, B
TestNG-test=Dev test-2: step 1
TestNG-test=Dev test-2: step 2
TestNG-test=Dev test-2: step 3
TestNG-test=Dev test-2: step 4 //completed TC for D, E, F
TestNG-test=Dev test-2: step 1
TestNG-test=Dev test-2: step 2
TestNG-test=Dev test-2: step 3
TestNG-test=Dev test-2: step 4 //completed TC for E, F, D
TestNG-test=Dev test-2: step 1
TestNG-test=Dev test-2: step 2
TestNG-test=Dev test-2: step 3
TestNG-test=Dev test-2: step 4 //completed TC for F, D, E
(parallel output, so not necessary in order as above)
XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<suite name="Suite" parallel="suites" thread-count="3" data-provider-thread-count="3" verbose="1">
<test name="Dev test" group-by-instances="true">
<classes>
<class name="package.TestCase1Factory" />
<!-- <class name="package.TestCase2Factory" /> -->
<!-- <class name="package.TestCase3Factory" /> -->
<!-- will eventually have other test cases in this suite -->
</classes>
</test>
</suite>
DP:
public class DP_forFactory {
@DataProvider (name = "setsAndNum", parallel = true)
public static Object[][] testInput3() throws IOException {
System.out.println("DP thread: " + Thread.currentThread().getName());
//just some sample data. Each row could also just be {A, B, C}, etc
Object[][] output = new Object[][] {
{new String[] {"A", "B", "C"}, "Parallel set 1"},
{new String[] {"D", "E", "F"}, "Parallel set 2"},
};
return output;
}
}
Завод:
public class TestCase1Factory {
private static final int DEVICES_PER_TEST = 3;
@Factory (dataProviderClass = DP_forFactory.class, dataProvider = "setsAndNum")
public Object[] createTCInstances(String[] deviceSet, String setNum) {
System.out.println("Creating a permutation from: " + deviceSet[0] + ", " + deviceSet[1] + ", " + deviceSet[2]);
System.out.println("Factory thread: " + Thread.currentThread().getName());
Object[] sequentialSet = new Object[deviceSet.length];
//create permutations
for (int i = 0; i < DEVICES_PER_TEST; i++) {
sequentialSet[i] = new TestCase1(deviceSet[i], deviceSet[(i+1) % DEVICES_PER_TEST], deviceSet[(i+2) % DEVICES_PER_TEST]);
}
return sequentialSet;
}
}
Контрольный пример (класс):
//this is the part that receives the @Factory input
public class TestCase1 {
//these are specific to the TC, so don't need to have a flexible setup
private String role1;
private String role2;
private String role3;
public TestCase1(String dev1, String dev2, String dev3) {
this.role1= dev1;
this.role2= dev2;
this.role3= dev3;
System.out.println("Set: " + role1 + ", " + role2 + ", " + role3);
}
@Test
public void step1() {
System.out.println(Thread.currentThread().getName() + ": step 1");
}
@Test (dependsOnMethods = "step1")
public void step2() {
System.out.println(Thread.currentThread().getName() + ": step 2");
}
@Test (dependsOnMethods = "step2")
public void step3() {
System.out.println(Thread.currentThread().getName() + ": step 3");
}
@Test (dependsOnMethods = "step3")
public void step4() {
System.out.println(Thread.currentThread().getName() + ": step 4");
}
}