目标:并行地独立运行2个类,其中每个测试将Method名称存储到一个可以在测试中稍后访问的变量中。
问题:当测试并行运行时,他们会开始在他们之间共享数据,从而破坏测试。
如果您看到控制台输出错误:
INFO: Name of Test from Before Method: classB_Method1
INFO: Name of Test from Before Method: classB_Method1
由于这些是两个独立的类,因此正在运行方法。和 我在这里设置了正确的名称:
!! Setting Method name to: classA_Method1
!! Setting Method name to: classB_Method1
输出应如下所示:
INFO: Name of Test from Before Method: classA_Method1
INFO: Name of Test from Before Method: classB_Method1
种皮
import java.lang.reflect.Method;
import org.testng.annotations.*;
import com.xxxx.util.*;
public class TestA {
@Test(/*dataProvider = "DP_MVPLoan_Login",*/ groups = {"parallel_test" }, invocationCount = 1, priority = 2, enabled = true)
public void classA_Method1(/*String... excelData*/) throws Exception {
}
/////////////////////////////////////////////////////////////////////////////
// ****SetUp and Tear Down
@BeforeTest(alwaysRun=true)
public void setupClass() throws Exception {
}
@BeforeMethod(alwaysRun=true)
public void setupMethod(Method method) throws Exception {
SeleniumHelperDebug.setCurrentMethodName(method.getName());
SeleniumHelperDebug.defaultBeforeMethod();
}
}
TestB
import java.lang.reflect.Method;
import org.testng.annotations.*;
import com.xxxx.util.*;
public class TestB {
@Test(/*dataProvider = "DP_MVPLoan_Login",*/ groups = { "parallel_test" }, invocationCount = 1, priority = 2, enabled = true)
public void classB_Method1(/*String... excelData*/) throws Exception {
}
/////////////////////////////////////////////////////////////////////////////
// ****SetUp and Tear Down
@BeforeTest(alwaysRun=true)
public void setupClass() throws Exception {
}
@BeforeMethod(alwaysRun=true)
public void setupMethod(Method method) throws Exception {
SeleniumHelperDebug.setCurrentMethodName(method.getName());
SeleniumHelperDebug.defaultBeforeMethod();
}
}
帮助方法
public class SeleniumHelperDebug {
//Name of the method/Test being run
private static String currentMethodName;
public static String getCurrentMethodName() {
return currentMethodName;
}
public static void setCurrentMethodName(String currentMethodName) {
System.out.println("!! Setting Method name to: "+ currentMethodName);
SeleniumHelperDebug.currentMethodName = currentMethodName;
}
//Setup Method. BeforeTest
public static void defaultBeforeMethod() throws Exception {
Thread.sleep(500);
/*setCurrentMethodName(method.getName());*/
System.out.println("INFO: Name of Test from Before Method: " +getCurrentMethodName() );
System.out.println("REMINDER: Keep Browser Window in Foreground to Help prevent F@ilures");
}
}
的testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="classes" verbose="2" thread-count="2">
<!--
<listeners>
<listener class-name="com.progressfin.util.WebDriverListener"></listener>
</listeners -->>
<tests>
<test name="Test" preserve-order="true">
<!-- <parameter name="browserName" value="firefox"></parameter> -->
<groups>
<run>
<include name="parallel_test"/>
</run>
</groups>
<classes>
<class name="com.xxxx.test.TestA" />
<class name="com.xxxx.test.TestB"/>
</classes>
</test> <!-- Test -->
</tests>
</suite> <!-- Suite -->
控制台输出
...
... TestNG 6.8.6 by Cédric Beust (cedric@beust.com)
...
[TestNG] Running:
C:\Users\samuel.safyan\workspace\JavaSelenium2\testNgParallelism2.xml
[TestRunner] Starting executor for test Test with time out:2147483647 milliseconds.
!! Setting Method name to: classA_Method1
!! Setting Method name to: classB_Method1
INFO: Name of Test from Before Method: classB_Method1
REMINDER: Keep Browser Window in Foreground to Help prevent F@ilures
INFO: Name of Test from Before Method: classB_Method1
REMINDER: Keep Browser Window in Foreground to Help prevent F@ilures
PASSED: classB_Method1
PASSED: classA_Method1
===============================================
Test
Tests run: 2, Failures: 0, Skips: 0
===============================================
答案 0 :(得分:2)
您的SeleniumHelperDebug类是静态的,因此不是线程安全的。你有没有理由不能每次测试一个实例?
您尝试使用SeleniumHelperDebug类解决了什么问题?
可能有更好的解决方案是线程安全的,但目前尚不清楚该类正在尝试实现什么
答案 1 :(得分:2)
我的建议:
1. Dont use static webdriver instances.
2. Dont use ThreadLocal
那么答案是什么?
Well, you don't need to handle the threads if your using a testrunner that can
fork threads for you. I use TestNG, and in that case I just pass DriverHelper
objects as arguments into my test methods from my Factory or my DataProvider
method. The DataProvider creates multiple helper instances and then once the
DriverHelper is inside my @Test annotated method, I instantiate the WebDriver
browser and proceed with test. If my DataProvider returns 10 items, then
TestNG iterates it 10 times, each on a different thread. Of course, this is
overly simplified, because you need to pay attention to the test lifecycle, and
take care to not open the browser until after you are in the Test method, but
it should get you started.
帮助您入门。这是一个非工作的例子,作为提示:
@DataProvider(name = "testdata")
public static Object[][] getTestData( ITestContext context )
{
List<XmlTest> tests = context.getSuite().getXmlSuite().getTests();
Map<String, String> suiteParams = context.getSuite().getXmlSuite().getAllParameters();
Object[][] testData = new Object[tests.size()][2];
int i = 0;
for ( XmlTest thisTest : tests ) {
testData[i][0] = new FirefoxDriver();
testData[i][1] = thisTest.getName();
i++;
Reporter.log( i + ": Added test: " + thisTest.getName(), true );
}
return testData;
}
....
@Test(dataProvider = "testdata", dataProviderClass = TestData.class)
public void test2( FirefoxDriver se, String testName ) {
Reporter.log("Thread-" + Thread.currentThread().getId() );
se.navigateTo("http://google.com");
....
答案 2 :(得分:1)
有不同的方法可以解决这个问题。我能想到的一个解决方案是Java的ThreadLocal概念。请参阅此链接以获取示例 - http://rationaleemotions.wordpress.com/2013/07/31/parallel-webdriver-executions-using-testng/ (请参阅LocalDriverManager类)。