[英]How to run tests in parallel by methods with TestNG and Selenium
问题如下。 我正在使用 TestNG v.7.6.0 和 Selenium v.4.2.2。 我尝试与 invocationCount 和 threadPoolSize 并行运行相同的测试方法。 这是我的测试类的一个例子(AUT 是“https://www.saucedemo.com/”):
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.time.Duration;
public class LoginTest {
ThreadLocal<WebDriver> driver;
@BeforeMethod()
public void setup() {
WebDriverManager.chromedriver().setup();
WebDriver webDriver = new ChromeDriver();
webDriver.manage().window().maximize();
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
webDriver.get("https://www.saucedemo.com/");
this.driver = new ThreadLocal<WebDriver>();
this.driver.set(webDriver);
}
@Test(invocationCount = 2, threadPoolSize = 2)
public void test() {
this.driver.get().findElement(By.id("user-name")).sendKeys("standard_user");
this.driver.get().findElement(By.id("password")).sendKeys("secret_sauce");
this.driver.get().findElement(By.id("login-button"));
}
}
第一次测试运行正常,但第二次测试失败并出现错误
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.WebDriver.findElement(org.openqa.selenium.By)" because the return value of "java.lang.ThreadLocal.get()" is null
at LoginTest.test(LoginTest.java:36)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:577)
at org.testng.internal.invokers.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:139)
at org.testng.internal.invokers.TestInvoker.invokeMethod(TestInvoker.java:677)
at org.testng.internal.invokers.TestInvoker.invokeTestMethod(TestInvoker.java:221)
at org.testng.internal.invokers.MethodRunner.runInSequence(MethodRunner.java:50)
at org.testng.internal.invokers.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:962)
at org.testng.internal.invokers.TestInvoker.invokeTestMethods(TestInvoker.java:194)
at org.testng.internal.invokers.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:148)
at org.testng.internal.invokers.TestMethodWorker.run(TestMethodWorker.java:128)
at org.testng.internal.thread.ThreadUtil.lambda$execute$0(ThreadUtil.java:58)
at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
因此,驱动程序在第二次测试中没有正确设置。 为什么? 我该如何解决?
如果我不使用 ThreadLocal,我的测试会相互混合。 例如,第二次测试运行的密码设置在第一个浏览器的密码字段中。 通过方法案例与驱动程序并行工作的正确方法是什么? 先感谢您
当您在setup
中使用此行时this.driver = new ThreadLocal<WebDriver>();
当第二个线程启动时,第二个测试用新值覆盖threadlocal
。
因此,当第一个线程试图获取它之前保存到threadlocal
的值时,它无法找到,因为此时this.driver
字段引用了第二个线程创建的对象。
要解决此问题,您需要在字段声明中初始化threadlocal
,因此您的代码如下所示:
PS - 将该字段设为静态也是值得的,这样您还可以处理为每个测试创建新的LoginTest
实例的情况(但是我不确定 TestNg 是否会出现这种情况)。
public class LoginTest {
static ThreadLocal<WebDriver> driver = new ThreadLocal<WebDriver>();
@BeforeMethod()
public void setup() {
WebDriverManager.chromedriver().setup();
WebDriver webDriver = new ChromeDriver();
webDriver.manage().window().maximize();
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
webDriver.get("https://www.saucedemo.com/");
driver.set(webDriver);
}
@Test(invocationCount = 2, threadPoolSize = 2)
public void test() {
driver.get().findElement(By.id("user-name")).sendKeys("standard_user");
driver.get().findElement(By.id("password")).sendKeys("secret_sauce");
driver.get().findElement(By.id("login-button"));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.