需求
最近公司在推广Testng自动化测试,因其中一个spring boot服务测试类众多,并且部分测试类需要依赖执行,还有部分测试类需要提前生成数据。类似classA要执行多次生成数据,classD 依赖classB、classA,classE依赖classC、classA。
graph LR
classB-->classA
classC-->classA
classD-->classB
classD-->classA
classE-->classC
classE-->classA
原方案所有用例顺序执行,耗时30分钟。配置如下:
<?xml version="1.0" encoding="utf-8" ?>
<suite name="testproj" parallel="false">
<listeners>
<listener class-name="CustomListener" />
<listener class-name="NewReport" />
</listeners>
<test name="testPostLoan">
<classes>
<class name="classA"></class>
<class name="classB"></class>
<class name="classA"></class>
<class name="classD"></class>
<class name="classA"></class>
<class name="classC"></class>
<class name="classA"></class>
<class name="classE"></class>
</classes>
</test>
</suite>
执行顺序:classA,classB,classD、classC、classE
存在问题:在一个标签下classA无法重复执行只会执行一次,其他classA换成extends classA 的类
在测试类中测试方法执行顺序控制,本公司使用dependsOnMethods如下:
public class TestConfig extends BaseTest {
private static final Logger LOG = LoggerFactory.getLogger(TestConfig.class);
@BeforeClass
public void setUp() throws ParseException {
LOG.info("=================== Test TestConfig run setUp ===================Thread=" +Thread.currentThread().getId());
}
@Test
public void testTest(){
LOG.info("=================== Test TestConfig testTest run testTest===================Thread=" +Thread.currentThread().getId());
}
@Test(dependsOnMethods = {"testTest"})
public void testEND(){
LOG.info("=================== Test TestConfig testEND run testEND===================Thread=" +Thread.currentThread().getId());
}
}
Methods执行顺序:setUp、testTest、testEND。
方案一 :在一个suite 中并行执行下,依赖执行。
Testng 并行测试配置
<suite name="test" parallel="tests" thread-count="5">
<suite name="test" parallel="classes" thread-count="5">
<suite name="test" parallel="methods" thread-count="5">
testng.xml 中标签属性及含义
name:此套件的名称。这是一个强制性的属性。
parallel:由TestNG 运行不同的线程来运行此套件。
thread-count:使用的线程数,如果启用并行模式(忽略其他方式)
methods:级别的多线程测试,每个方法都将采用独立的线程进行测试
classes:不同标签下的用例可以在不同的线程执行,相同标签下的用例只能在同一个线程中执行
tests:test级别的多线程测试,每个标签下的所有方法将在同一个线程中执行,测试类是无序的,不同的是在不同的线程来运行的,
多线程执行要保证线程安全,慎用全局变量。
修改配置文件如下:
<?xml version="1.0" encoding="utf-8" ?>
<suite name="testproj" parallel="tests" thread-count="10">
<listeners>
<listener class-name="CustomListener"/>
<listener class-name="NewReport"/>
</listeners>
<test name="TEST1">
<groups>
<run>
<include name="GroupA"/>
<include name="GroupB"/>
<include name="GroupD"/>
</run>
<dependencies>
<group name="GroupB" depends-on="GroupA"/>
<group name="GroupD" depends-on="GroupB GroupA"/>
</dependencies>
</groups>
<classes>
<class name="classA"></class>
<class name="classB"></class>
<class name="extendsclassA"></class>
<class name="classD"></class>
</classes>
</test>
<test name="TEST2">
<groups>
<run>
<include name="GroupA"/>
<include name="GroupC"/>
<include name="GroupE"/>
</run>
<dependencies>
<group name="GroupC" depends-on="GroupA"/>
<group name="GroupE" depends-on="GroupA GroupC"/>
</dependencies>
</groups>
<classes>
<class name="classA"></class>
<class name="classB"></class>
<class name="extendsclassA"></class>
<class name="classD"></class>
</classes>
</test>
</suite>
在测试类上添加@Test(groups = “GroupName”,alwaysRun = true)
@Test(groups = "GroupName",alwaysRun = true)
public class TestConfig {
略
}
此方案结果满足公司需求,时间从30分钟减到7分钟左右。
方案二:添加多个suites,classA放在testNGA.xml 中并行执行多次,classB和classD,classC和classE放在testNGB.xml 中并行执行
代码:
TestNG testNG = new TestNG();
List<String> suites = new ArrayList<>();
suites.add("testNGA.xml"); //先添加先执行
suites.add("testNGB.xml");
//设置testNG配置文件xml的路径
testNG.setTestSuites(suites);
//设置测试报告输出目录,默认为test-output
testNG.setOutputDirectory("");
testNG.run();
配置文件suiteA
<?xml version="1.0" encoding="utf-8" ?>
<suite name="suiteA" parallel="tests" thread-count="4">
<test name="test1">
<classes>
<class name="classA"></class>
</classes>
</test>
<test name="test2">
<classes>
<class name="classA"></class>
</classes>
</test>
<test name="test3">
<classes>
<class name="classA"></class>
</classes>
</test>
<test name="test4">
<classes>
<class name="classA"></class>
</classes>
</test>
</suite>
配置文件suiteB
<?xml version="1.0" encoding="utf-8" ?>
<suite name="suiteB" parallel="tests" thread-count="2">
<listeners>
<listener class-name="CustomListener"/>
<listener class-name="NewReport"/>
</listeners>
<test name="TEST1">
<groups>
<run
<include name="GroupB"/>
<include name="GroupD"/>
</run>
<dependencies>
<group name="GroupD" depends-on="GroupB"/>
</dependencies>
</groups>
<classes>
<class name="classB"></class>
<class name="classD"></class>
</classes>
</test>
<test name="TEST2">
<groups>
<run>
<include name="GroupC"/>
<include name="GroupE"/>
</run>
<dependencies>
<group name="GroupE" depends-on="GroupC"/>
</dependencies>
</groups>
<classes>
<class name="classB"></class>
<class name="classD"></class>
</classes>
</test
</suite>