2016-12-09 86 views
0

這是初始化ThreadLocal RemoteWebDriver的正確方法嗎?使用非靜態WebDriver進行並行執行 - Selenium - TestNG - Java

我看過帖子裏有人說你不應該有一個靜態WebDriver,但是,如果我刪除了靜態修飾符,我最終會得到NULL指針異常。

一切都運行良好的大部分,但我遇到了一個問題,其中一個線程偶爾會在不同的線程中輸入數據。我試圖解決導致我這個問題。

TestSetup類:

public class TestSetup { 

    private static ThreadLocal<RemoteWebDriver> threadDriver;// = new ThreadLocal<RemoteWebDriver>(); 

    @Parameters({"browserParam"}) 
    @BeforeClass(alwaysRun = true) 
    public void beforeClass(@Optional("") final String browserParam) throws InterruptedException, MalformedURLException { 

     // Set Driver 
     threadDriver = new ThreadLocal<RemoteWebDriver>() 
     { 

      @Override 
      protected RemoteWebDriver initialValue() 
      { 

       String browser = "Chrome"; 
       DesiredCapabilities dc = new DesiredCapabilities(); 

       if (browser.equals("Chrome")) 
       { 

        String chromeDriver = "C:\\workspace\\drivers\\chromedriver.exe"; 
        System.setProperty("webdriver.chrome.driver", chromeDriver); 

        // Access Grid Hub 
        dc.setBrowserName(DesiredCapabilities.chrome().getBrowserName()); 

       } // end Chrome 

       // Set the driver 
       try { 
        threadDriver.set(new RemoteWebDriver(new URL(hubURL), dc)); 
       } catch (MalformedURLException e) { 
        e.printStackTrace(); 
       } 

       return getDriver(); 

      } // end initialValue 

     } // end threadDriver 

    } // end beforeClass 



    @AfterClass(alwaysRun = true) 
    public void afterClass() { 

     // Quit the Webdriver 
     getDriver().quit(); 

    } // end afterClass 



    public RemoteWebDriver getDriver() { 

     return threadDriver.get(); 

    } // end getDriver 

} // end TestSetup class 

LoginTest類:

private Function perform = new Function(); 

@Test (retryAnalyzer = Retry.class, groups={"baseline", "negative"}) 
public synchronized void loginEmptyUsername() throws InterruptedException { 

ExtentTest test = ExtentTestManager.getTest(); 

// Go to Secure 
getDriver().get(StoredVariables.getsecureSite().get()); 

// Wait for password 
perform.waitForElementToBeClickable(SLogin.password_txtbx(), "id"); 

// Clear email field 
SLogin.email_txtbx(getDriver()).clear(); 

// enter password 
SLogin.password_txtbx(getDriver()).clear(); 
SLogin.password_txtbx(getDriver()).sendKeys(StoredVariables.getpassword().get()); 

// click Sign In 
SLogin.signIn_btn(getDriver()).click(); 

// Wait for error 
perform.waitForElementToBeClickable(SLogin.loginError_txt(), "id"); 

// Verify error text 
Assert.assertTrue(SLogin.loginError_txt(getDriver()).getText().contains("Oops! Your email or password (case sensitive) was incorrect. Please try again.")); 

// Log test 
test.log(LogStatus.INFO, "login", "Tried logging in with an empty email"); 

} // end loginEmptyUsername 

我將如何傳遞的webdriver到測試類,如果它不是在TestSetup類的靜態?

UPDATE:

看來,用我的初步實施,但限制的節點,只允許3個實例,而不是利用5個實例的最大解決了我的(至少暫時)問題。

回答

0

您不應該在方法中初始化ThreadLocal。您的實現取決於通過@BeforeClass方法傳入的瀏覽器風格,該方法將由initialValue()實現消耗,以實例化ThreadLocal並保留WebDriver實例。這個問題是,下一次當某個線程通過get()查詢你的線程本地,並且如果有一個空值,則該呼叫被路由到initialValue(),但現在只記得最後一個瀏覽器參數。所以你的總體實施需要拋棄。

我寫了一篇博客文章解釋這種行爲。請看看它here

還記得,當涉及到保證執行同一個線程,TestNG的只爲@BeforeMethod>@Test>@AfterMethod組合擴展了這種保證。對於其他一切,沒有這樣的保證。

您也可以參考我的this博客,其中我會談論並行執行。

實施這應該是如下正確的方法:

public class TestSetup { 

    private String browserFlavor; 

    private static final ThreadLocal<RemoteWebDriver> driver = new ThreadLocal<RemoteWebDriver>() { 
     @Override 
     protected RemoteWebDriver initialValue() { 
      //By default lets set the browser flavor always as Chrome. 
      return new ChromeDriver(); 
     } 
    }; 

    @Parameters ({"browserParam"}) 
    @BeforeClass (alwaysRun = true) 
    public void beforeClass(@Optional ("") final String browserParam) { 
     this.browserFlavor = browserParam; 
    } 

    @BeforeMethod 
    public void instantiateBrowser() { 
     switch (browserFlavor) { 
      case "firefox": 
       driver.set(new FirefoxDriver()); 
       break; 
      case "ie": 
       driver.set(new InternetExplorerDriver()); 
       break; 
     } 
    } 

    @Test 
    public void testMethod() { 
     driver.get().get("http://www.google.com"); 
    } 

} 
+0

我實現您的解決方案(但與RemoteWebDriver),現在還在運行到一個線程進入數據的問題到另一個線程,因此,引起那些線程失敗,因爲它們都不包含預期的數據。 –

+0

另外,通過這個設置,假​​設我在我的test.xml文件和xml文件中有11個類,我告訴它thread-count =「2」,前兩個類運行正常,但其餘的根本不運行,因爲它表示會話ID爲空 –

+0

@DustinN。您可能需要查看我的https://rationaleemotions.wordpress.com/2013/07/31/parallel-webdriver-executions-using-testng/這篇博客文章,以獲取完整的解決方案。沒有看到你在做什麼很難說出了什麼問題。但我可以向你保證,我共享的解決方案不會導致webdriver實例在線程間泄漏。 –

相關問題