从一个输入列表中,我进行了唯一的一组输入。所有集合都应并行运行,但是每个集合本身都需要按顺序运行测试,并且需要将集合的排列作为测试的输入。
设置方式:
DataProvider接收设备列表(设备数量各不相同)。它制作了n个大小的设备集,例如每组3个设备。
对于相同的测试用例,每组设备均以相同的Factory方法输入。 (这部分应该是平行的)
然后,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还是很陌生,所以也许不是。
第二个问题 :( dependsOnQuestion =“第一个问题”)-怎么样?我可能没有以最佳方式按原样构建此结构。使用线程是可能的,似乎TestNG应该已经在处理这种事情。
在XML中,我尝试更改并行运行的内容。对于套件,它全是1个线程(在此并不奇怪)。对于Test,它仅创建1个单独的线程。对于类,它似乎为每个@Test批注的方法创建了单独的线程,但是最终线程运行所有剩余的方法。方法在XML中分配的3个线程之一中运行每个方法,但是每个Factory仍在单个“主”线程中。当然,如果我只是删除并行参数,则所有内容都在单个线程中运行。 按实例分组必须为真,以便每个TC的步骤在TC的下一个实例运行之前执行。 我也在研究结构-如果找到解决方案,我将发布更新。
//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");
}
}