有关多线程数据提供者传递功能的问题

时间:2018-11-16 21:53:33

标签: multithreading testng testng-dataprovider

我正在尝试在正在编写的新线程安全测试框架中实现并行性。我有一个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吗?

1 个答案:

答案 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>