我正在尝试在正在编写的新线程安全测试框架中实现并行性。我有一个DataProviderManager.java类,其中包含我的静态DataProvider
@DataProvider(parallel = true, name = Config.StaticProps.DEFAULT_WEB_DATA_PROVIDER)
public static Object[][] defaultWebDataProvider() {
return new Object[][] {
new Object[]{"chrome", "69", "MAC 10.12"},
new Object[]{"safari", "11.0", "Mac 10.13"},
new Object[]{"safari", "11.0", "Mac 10.13"}
new Object[]{"chrome", "70", "Mac 10.13"}
new Object[]{"firefox", "63", "MAC 10.12"},
new Object[]{"firefox", "62", "MAC 10.12"}
};
}
我有一个测试类,该类将3个参数从我的DataProvider传递到ThreadLocal getter和setter,以为每个线程设置Selenium Capabilities来实例化具有这些功能的驱动程序实例。测试本身只是基于一些运行时参数打开一个特定的URL。
@Factory(dataProvider = StaticProps.DEFAULT_WEB_DATA_PROVIDER, dataProviderClass = DataProviderManager.class)
//@Factory(dataProvider = StaticProps.DEFAULT_WEB_DATA_PROVIDER)
public WebExampleTest(String browser, String browserVersion, String platform) {
super.setRunParams(browser, browserVersion, platform);
}
@BeforeMethod(alwaysRun = true)
public void setupTest() {
home = new Home();
}
@TestCaseId("")
@Features({GroupProps.WEB})
@Test(groups = {GroupProps.DEBUG}, dataProvider = StaticProps.DEFAULT_WEB_DATA_PROVIDER, dataProviderClass = DataProviderManager.class)
@Parameters({ ParamProps.WEB, ParamProps.MOBILE_WEB })
public void openSiteTest(String browser, String browserVersion, String platform) {
Logger.logMessage("Current Thread ID: " + Thread.currentThread().getId());
new WebInteract(null, null).pause(1000).openUrl(URLBuilder.buildUrl());
}
这是我的testing.xml文件
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Test Engineering Core Suite"
parallel="true"
data-provider-thread-count="6"
thread-count="6"
verbose="2">
<!-- LISTENERS -->
<listeners>
<listener class-name="com.msg.test.core.listeners.TestListeners" />
<listener class-name="com.msg.test.core.listeners.SuiteListeners" />
<listener class-name="com.msg.test.core.listeners.TestAnnotationTransformer" />
</listeners>
<!-- TEST EXECUTION QUEUE -->
<test verbose="1" name="All Tests" annotations="JDK">
<!-- TEST GROUPS
"Full" - all tests in the test suite.
"Broken" - those tests that are broken and safe to ignore until they can be resolved.
-->
<!--<groups>-->
<!--<run>-->
<!--<include name="Debug" />-->
<!--<exclude name="Broken" />-->
<!--</run>-->
<!--</groups>-->
</test>
</suite>
以下是输出的一部分,以向您显示当前发生的情况
2018-11-18 12:49:37.633 ========NEW TEST SESSION========
2018-11-18 12:49:37.633 Desktop OS: Mac 10.13
2018-11-18 12:49:37.633 Browser: chrome
2018-11-18 12:49:37.633 Browser Version: 70
2018-11-18 12:49:37.634 Current Thread ID: 66
2018-11-18 12:49:37.635 Pause for '1000' milliseconds.
Nov 18, 2018 12:49:37 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
2018-11-18 12:49:37.846 Session ID: 622fda273344469ab98aef0d06f90315
2018-11-18 12:49:37.847 ========NEW TEST SESSION========
2018-11-18 12:49:37.847 Desktop OS: Mac 10.13
2018-11-18 12:49:37.847 Browser: chrome
2018-11-18 12:49:37.848 Browser Version: 70
2018-11-18 12:49:37.849 Current Thread ID: 68
2018-11-18 12:49:37.849 Pause for '1000' milliseconds.
2018-11-18 12:49:37.950 Open url 'https://www.example.com'.
2018-11-18 12:49:38.571 Open url 'https://www.example.com'.
2018-11-18 12:49:38.571 Open url 'https://www.example.com'.
2018-11-18 12:49:38.576 ======SUCCESS======
2018-11-18 12:49:38.577 Desktop OS: Mac 10.13
2018-11-18 12:49:38.577 Browser: chrome
2018-11-18 12:49:38.577 Browser Version: 70
2018-11-18 12:49:38.640 Open url 'https://www.example.com'.
2018-11-18 12:49:38.854 Open url 'https://www.example.com'.
2018-11-18 12:49:39.059 ======SUCCESS======
2018-11-18 12:49:39.060 Desktop OS: Mac 10.13
2018-11-18 12:49:39.060 Browser: chrome
2018-11-18 12:49:39.060 Browser Version: 70
2018-11-18 12:49:39.083 ======SUCCESS======
2018-11-18 12:49:39.084 Desktop OS: Mac 10.13
2018-11-18 12:49:39.084 Browser: chrome
2018-11-18 12:49:39.084 Browser Version: 70
2018-11-18 12:49:39.126 ======SUCCESS======
2018-11-18 12:49:39.126 Browser: chrome
2018-11-18 12:49:39.126 Browser Version: 70
2018-11-18 12:49:39.393 ======SUCCESS======
您可以看到,我能够在不同的线程上并行运行相同的测试,但是每个线程都在DataProvider的相同浏览器,版本和平台上运行。
我的问题是,而不是运行多个线程,每个线程都同时从DataProvider执行同一数据(浏览器,版本平台-chrome,70,Mac 10.13),如何运行每个线程(浏览器,版本,平台)< / p>
new Object[]{"chrome", "69", "MAC 10.12"}, **This should be thread 1**
new Object[]{"safari", "11.0", "Mac 10.13"}, **This should be thread 2**
new Object[]{"safari", "11.0", "Mac 10.13"} **This should be thread 3**
new Object[]{"chrome", "70", "Mac 10.13"} **This should be thread 4**
new Object[]{"firefox", "63", "MAC 10.12"}, **This should be thread 5**
new Object[]{"firefox", "62", "MAC 10.12"} **This should be thread 6**
同时从不同线程上的DataProvider吗?
答案 0 :(得分:0)
TestNG的工作原理
常规@Test
方法和数据提供者
当正常的@Test
带注释的测试方法需要运行多次但使用不同的数据集时,可以将其与数据提供程序结合使用。要并行运行它,您基本上在@DataProvider
批注上启用了parallel属性,并在parallel=methods
标签级别指定了<suite>
属性。
下面是显示所有这些操作的示例。它利用了org.testng.IHookable
接口,因此人们基本上可以提取出通过数据提供者发送给@Test
方法的参数,并使用它们来进行每次迭代所需的任何设置。
您也可以使用@BeforeMethod
批注,但是它不可能从{{1}内提取出数据提供者发送给@Test
方法的参数。 }。
@BeforeMethod
运行此测试时相应的输出如下
import org.testng.IHookCallBack;
import org.testng.IHookable;
import org.testng.ITestResult;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class TestClassWithDataDrivenTest implements IHookable {
@Override
public void run(IHookCallBack callBack, ITestResult result) {
beforeMethod(callBack.getParameters());
callBack.runTestMethod(result);
}
public void beforeMethod(Object[] parameters) {
String browser = parameters[0].toString();
String browserVersion = parameters[1].toString();
String platform = parameters[2].toString();
String msg =
String.format(
"[beforeMethod()-Thread Id : %d] [%s] flavor version [%s] on platform [%s]",
Thread.currentThread().getId(), browser, browserVersion, platform);
System.err.println(msg);
}
@Test(dataProvider = "dp")
public void testMethod(String browser, String browserVersion, String platform) {
String msg =
String.format(
"[testMethod()-Thread Id : %d] [%s] flavor version [%s] on platform [%s]",
Thread.currentThread().getId(), browser, browserVersion, platform);
System.err.println(msg);
}
@DataProvider(parallel = true, name = "dp")
public static Object[][] defaultWebDataProvider() {
return new Object[][] {
new Object[] {"chrome", "69", "MAC 10.12"},
new Object[] {"safari", "11.0", "Mac 10.13"},
new Object[] {"safari", "11.0", "Mac 10.13"},
new Object[] {"chrome", "70", "Mac 10.13"},
new Object[] {"firefox", "63", "MAC 10.12"},
new Object[] {"firefox", "62", "MAC 10.12"}
};
}
}
[beforeMethod()-Thread Id : 11] [chrome] flavor version [69] on platform [MAC 10.12]
[beforeMethod()-Thread Id : 12] [safari] flavor version [11.0] on platform [Mac 10.13]
[beforeMethod()-Thread Id : 14] [chrome] flavor version [70] on platform [Mac 10.13]
[beforeMethod()-Thread Id : 13] [safari] flavor version [11.0] on platform [Mac 10.13]
[beforeMethod()-Thread Id : 15] [firefox] flavor version [63] on platform [MAC 10.12]
[testMethod()-Thread Id : 12] [safari] flavor version [11.0] on platform [Mac 10.13]
[beforeMethod()-Thread Id : 16] [firefox] flavor version [62] on platform [MAC 10.12]
[testMethod()-Thread Id : 13] [safari] flavor version [11.0] on platform [Mac 10.13]
[testMethod()-Thread Id : 14] [chrome] flavor version [70] on platform [Mac 10.13]
[testMethod()-Thread Id : 11] [chrome] flavor version [69] on platform [MAC 10.12]
[testMethod()-Thread Id : 16] [firefox] flavor version [62] on platform [MAC 10.12]
[testMethod()-Thread Id : 15] [firefox] flavor version [63] on platform [MAC 10.12]
===============================================
Default Suite
Total tests run: 6, Passes: 6, Failures: 0, Skips: 0
===============================================
和数据提供商一起
当要生成测试类实例时,可以使用@Factory
方法(可以在构造函数的顶部或返回@Factory
的静态方法上添加此注释)。
测试类实例被定义为其中包含一个或多个Object[]
方法的常规类。与数据提供者结合使用时,工厂使用数据提供者提供的数据来实例化每个测试类。
如果想让TestNG一口气在所有实例中并行运行@Test
方法(TestNG仍会按顺序运行每个测试类中的所有@Test
方法),则可以通过@Test
标签上的属性parallel=instances
进行指定。
请注意,不能在每个测试类实例中并行运行所有<suite>
方法。 TestNG AFAIK无法在该级别启用并行性。
下面是显示此操作的示例
@Test
testng套件xml文件如下
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class TestClassWithFactory {
private String browser, browserVersion, platform;
@Factory(dataProvider = "dp")
public TestClassWithFactory(String browser, String browserVersion, String platform) {
this.browser = browser;
this.browserVersion = browserVersion;
this.platform = platform;
}
@BeforeMethod
public void beforeMethod() {
String msg =
String.format(
"[Instance id %d][beforeMethod()-Thread Id : %d] [%s] flavor version [%s] on platform [%s]",
this.hashCode(), Thread.currentThread().getId(), browser, browserVersion, platform);
System.err.println(msg);
}
@Test
public void testMethod() {
String msg =
String.format(
"[Instance id %d][testMethod()-Thread Id : %d] [%s] flavor version [%s] on platform [%s]",
this.hashCode(), Thread.currentThread().getId(), browser, browserVersion, platform);
System.err.println(msg);
}
@DataProvider(parallel = true, name = "dp")
public static Object[][] defaultWebDataProvider() {
return new Object[][] {
new Object[] {"chrome", "69", "MAC 10.12"},
new Object[] {"safari", "11.0", "Mac 10.13"},
new Object[] {"safari", "11.0", "Mac 10.13"},
new Object[] {"chrome", "70", "Mac 10.13"},
new Object[] {"firefox", "63", "MAC 10.12"},
new Object[] {"firefox", "62", "MAC 10.12"}
};
}
}
执行输出如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="53345934_suite" parallel="instances" verbose="2">
<test name="53345934_test">
<classes>
<class name="com.rationaleemotions.stackoverflow.qn53345934.TestClassWithFactory"/>
</classes>
</test>
</suite>