【问题标题】:Selenium Webdriver TestNG tests are "overwriting" each otherSelenium Webdriver TestNG 测试相互“覆盖”
【发布时间】:2017-03-09 19:38:02
【问题描述】:

我正在尝试使用 TestNG 在单台机器上并行运行 Selenium Webdriver 测试。我有 3 个 @Test 方法,其中 3 个不同的用户登录到同一个应用程序并到达主页。我需要 @Test 方法并行运行,并写入 ExtentReports 报告。

我的问题是,尽管在不同的类中有 3 种完全不同的方法,但其中一个用户将登录到 3 个浏览器中的 2 个,而将一个用户排除在外。

登录方法位于PageFactory页面对象类中。

这是我的 3 种测试方法:

@Test(enabled = true, priority = 0) 
public void JohnLogin() throws Exception {
    ExtentTest t = ClientReportFactory.getTest();
    try {       
        Login objLogin = new Login(getDriver());
        String username = "John";
        String password = "Password";
        objLogin.SignIn(username, password);
        HomePage objHomePage = new HomePage(getDriver());   
        assertTrue(objHomePage.clientName.getText().c‌​ontains("John"));
    } catch (Exception e) {
    }
}

@Test(enabled = true, priority = 1) 
public void BobLogin() throws Exception {
    ExtentTest t = ClientReportFactory.getTest();
    try {       
        Login objLogin = new Login(getDriver());
        String username = "Bob";
        String password = "Password";
        objLogin.SignIn(username, password);
        HomePage objHomePage = new HomePage(getDriver());       
        assertTrue(objHomePage.clientName.getText().c‌​ontains("Bob"));
    } catch (Exception e) {
    }
}

@Test(enabled = true, priority = 2) 
public void SamLogin() throws Exception {
    ExtentTest t = ClientReportFactory.getTest();
    try {       
        Login objLogin = new Login(getDriver());
        String username = "Sam";
        String password = "Password";
        objLogin.SignIn(username, password);
        HomePage objHomePage = new HomePage(getDriver());       
        assertTrue(objHomePage.clientName.getText().c‌​ontains("Sam"));
    } catch (Exception e) {
    }
}

所以,如果我暂停主页上的测试。我将打开 2 个浏览器窗口为“John”,一个“Bob”,没有“Sam”...导致失败。

这是 PageFactory 对象的登录方法。

 public void SignIn(String strUsername, String strPassword) throws InterruptedException {
    WebDriverWait wait = new WebDriverWait(driver, 15); 
    username.clear();
    username.sendKeys(strUsername);
    password.clear();
    password.sendKeys(strPassword);
    submit.click();
    wait.until(ExpectedConditions.visibilityOf(homePagePanel));
}

起初我确定问题出在@BeforeMethod 线程中(例如,测试位于与@Before 和@After 不同的线程中)。但我不明白怎么会是这样。 Base Test 方法成功打开和关闭 3 个浏览器。似乎@Test 方法使用了彼此的数据!但以防万一,这是我的@Before 和@After,以及我的线程代码。

public class BaseTest {
    public String browser;
    private ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();

@BeforeMethod(alwaysRun = true)
@Parameters({ "browser"})
public void setup(String browser)throws MalformedURLException,
InterruptedException {

        WebDriver driver = null;
        if (browser.equalsIgnoreCase("Internet Explorer")) {
            System.setProperty("webdriver.ie.driver", "C:\\Selenium\\IEDriverServer.exe");
            driver = new InternetExplorerDriver();
        } else if (browser.equalsIgnoreCase("Firefox")) {
            System.setProperty("webdriver.gecko.driver", "C:\\Selenium\\geckodriver.exe");
            driver = new FirefoxDriver();
        } else if (browser.equalsIgnoreCase("chrome")) {
            System.setProperty("webdriver.chrome.driver", "C:\\Selenium\\chromedriver.exe");
            driver = new ChromeDriver();
        } else if (browser.equalsIgnoreCase("MicrosoftEdge")) {
            System.setProperty("webdriver.edge.driver", "C:\\Selenium\\MicrosoftWebDriver.exe");
            driver = new EdgeDriver();
        }
        setWebDriver(driver);
        this.browser = browser;
        ClientReportFactory.getTest(ExtentTestName, ExtentTestDescription);

baseURL = "testApp.com";
driver.get(baseURL);
        driver.manage().window().maximize();
        }

public WebDriver getDriver(){
    return threadedDriver.get();
}
public void setWebDriver(WebDriver driver) {
    threadedDriver.set(driver);
}

@AfterMethod 
public void afterMethod() {
    ClientReportFactory.closeTest(ExtentTestName, ExtentTestDescription);
    getDriver().quit();
    threadedDriver.set(null);
}

@AfterSuite
public void afterSuite() {
    ClientReportFactory.closeReport();
    if (getDriver() != null) {
        getDriver().quit();
    } else {
        System.out.println("Drivers already closed");
    }
}

【问题讨论】:

    标签: java multithreading selenium testng pageobjects


    【解决方案1】:

    假设您所有的 @Test 方法都在不同的类中,我猜问题可能是由于您的 ThreadLocal 变量是 NOT STATIC 而是一个实例变量.这导致行为是每个实例的每个线程,而不是所需的行为,即所有实例的每个线程。您可以参考this StackOverFlow 线程以获得更好的解释。

    您将求助于使用ThreadLocal 的实例变体当且仅当您的所有@Test 方法都属于同一个测试类(因​​为现在您只是试图确保该类级别数据成员WebDriver 在属于同一测试类的所有测试方法之间以线程安全的方式共享)

    因此,如果您的每个 @Test 方法都位于其自己的 Test 类中,那么请尝试更改:

    private ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();
    

    private static ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();
    

    【讨论】:

    • Krishnan,我下面的回答有什么问题?我想学习。
    • @Dineshmohan - 我已经修复了否决票部分。在旁注中,我认为您的解决方案可能会受到 Java 在尝试使用 ThreadLocals 时表现出的奇怪行为的困扰,其中 initialValue() 是在方法范围内定义的,并且该值取决于封闭范围。您可以在我的博文rationaleemotions.wordpress.com/2016/05/16/… 中阅读更多相关信息(我不确定您的代码是否也会出现同样的问题,但它确实有可能导致问题的相同类型的代码)
    【解决方案2】:

    你可以试试这个。

    public class DriverFactory(){
    
    private static ThreadLocal<WebDriver> driverThread;
    public WebDriver driver;
    
    @Parameters("browser")
    public WebDriver instantiateDriverObject(String browser) {
    DriverFactory factory = new DriverFactory();
    driver = factory.createInstance(browser); //Driver instantiation goes here
    driverThread = new ThreadLocal<WebDriver>() {
        @Override
        protected WebDriver initialValue() {
        webDriverPool.add(driver);
        return driver;
        }
    };
    return driver;
    }
    
    public WebDriver getDriver() {
    return driverThread.get();
    }
    

    }

    【讨论】:

    • 我错误地点击了那个。我很抱歉。从昨天开始,我一直在尝试修复它,但运气不佳。我现在已经修好了。很抱歉造成混乱。
    猜你喜欢
    • 1970-01-01
    • 2016-04-17
    • 2016-04-25
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多