[英]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.