当前位置: 首页 > 知识库问答 >
问题:

防止TestNg在并行测试之间共享数据

漆雕亮
2023-03-14

目标:独立并行地运行两个类,每个测试将方法名存储到一个变量中,该变量可以在测试中稍后访问。

问题:当测试并行运行时,它们开始在它们之间共享数据,从而损坏测试。

如果您看到控制台输出,这是错误的:

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(); 

    }

}

测试B

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
===============================================

共有3个答案

徐嘉谊
2023-03-14

有不同的方法来解决这个问题。我能想到的一个解决方案是Java的ThreadLocal概念。请参见此链接以获取示例-http://rationaleemotions.wordpress.com/2013/07/31/parallel-webdriver-executions-using-testng/(请参阅LocalDriverManager类)。

哈栋
2023-03-14

我的建议是:

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");
    ....
夏侯林
2023-03-14

SeleniumHelperDebug类是静态的,因此不是线程安全的。有什么理由不能在每个测试中都有一个实例吗?

你想用SeleniumHelperDebug类解决什么问题?

也许有一个更好的解决方案是线程安全的,但尚不清楚该类试图实现什么

 类似资料:
  • 我有一个测试类的testng套件,我正在通过一个testng.xml文件运行它。这个很管用。所有测试都是串行运行的,因此没有并行执行障碍。 当然,通过类成员变量在单个类中的测试方法之间共享状态是很容易的,但是我不知道如何在测试类之间共享状态。

  • 我正在编写一个单元测试类(使用testng),它模拟了成员变量(使用Mockito),并并行运行测试。我最初在@BeForeClass方法中设置了预期的mock,在每个测试用例中,我通过为每个异常情况创建mockito.when来破坏一些东西。 我所看到的(不出所料)是这些测试不是独立的;当一个测试用例中的mockito.when会影响其他测试用例。我注意到可以在每次测试之前设置模拟,因此我将@B

  • 我正在重构一大堆selenium测试,并尝试在TestNG中执行它们。问题是,无论结果如何,测试执行都会在每次测试后停止(最终会超时)。当我刷新浏览器时,测试继续进行。我不确定问题出在哪里。 我的测试是这样的

  • 问题内容: 我有一些称为的数据,该数据位于三个孩子的父对象的范围内: 在这三个指令之间共享的最佳方法是什么?选项包括: 使用隔离的范围传递三遍,从而跨四个范围复制它 让子指示继承父范围,并找到,或在 把上并注入到这一点的子指示 还是有另一种更好的方法? 问题答案: 您可以创建一个工厂,该工厂可以传递给每个指令或控制器。这样可以确保在任何给定时间只有一个数组实例。编辑:这里唯一的陷阱是确保您在指令作

  • 我试图用TestNG并行运行一个示例测试项目。但它是在一个线程中顺序执行的。我漏掉什么了吗? 谢了。

  • 问题内容: 我想将一些数据从一个HTML页面发送到另一HTML页面。我通过类似的查询参数发送数据 。这种方法的问题在于数据保留在URL中。是否有其他方法可以使用JavaScript或jquery在HTML页面之间发送数据。 问题答案: 为什么不将值存储在HTML5存储对象(例如或)中,请访问HTML5存储文档以获取更多详细信息。使用此功能,您可以在本地临时/永久存储中间值,然后在以后访问您的值。