2016-12-09 14 views
0

Ist dies die richtige Methode zum Initialisieren eines ThreadLocal RemoteWebDriver?Verwenden Sie nicht-statischen WebDriver für die parallele Ausführung - Selenium - TestNG - Java

Ich habe Posts gesehen, in denen Leute sagen, dass Sie keinen statischen WebDriver haben sollten, aber wenn ich den statischen Modifizierer entferne, komme ich mit der Nullzeigerausnahme voran.

Alles läuft gut, aber ich habe ein Problem, bei dem ein Thread gelegentlich Daten in einem anderen Thread eingibt. Ich versuche, das Problem zu beheben, das mich dazu geführt hat.

TestSetup Klasse:

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 Klasse:

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 

Wie würde ich die WebDriver auf die Test-Klasse übergeben, wenn sie nicht statisch in der TestSetup Klasse ist?

UPDATE:

Es scheint, dass meine erste Implementierung verwenden, aber die Knoten Beschränkung auf nur drei Instanzen darüber zulassen, unter Verwendung des maximal 5 Instanzen gegenüber hat mein Problem gelöst (zumindest für den Moment).

Antwort

0

Sie sollten ein ThreadLocal nicht innerhalb einer Methode initialisieren. Ihre Implementierung hängt davon ab, wie die Browser-Variante über die @BeforeClass-Methode übergeben wird, die dann von Ihrer initialValue() - Implementierung konsumiert wird, um das ThreadLocal zu instanziieren und eine WebDriver-Instanz persistent zu machen. Das Problem dabei ist, dass das nächste Mal, wenn einige Threads Ihren Thread lokal über get() abfragen, und wenn es einen Nullwert gibt, der Aufruf an initialValue() weitergeleitet wird, sich aber jetzt nur an den letzten Browserparameter erinnert. Ihre gesamte Implementierung bedeutet also einen Toss.

Ich schrieb einen Blogpost, der dieses Verhalten erklärt. Bitte werfen Sie einen Blick darauf here.

Denken Sie auch daran, dass, wenn sie zur Ausführung an die Gewährleistung der gleichen Thread kommt, TestNG diese Garantie erstreckt sich nur für @BeforeMethod>@Test>@AfterMethod Kombination. Für alles andere gibt es keine solche Garantie.

Sie können auch auf this Blog von mir verweisen, wobei ich über parallele Ausführungen spreche.

Die richtige Art und Weise der Umsetzung dieses wie unten sein sollte:

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

ich Ihre Lösung (aber mit dem RemoteWebDriver) umgesetzt und nach wie vor in die Frage läuft in einen anderen Thread von einem Thread der Eingabe von Daten am daher verursacht Diese Threads schlagen fehl, weil die erwarteten Daten nicht enthalten sind. –

+0

Bei dieser Konfiguration sage ich, dass ich 11 Klassen in meiner Datei test.xml habe und in der XML-Datei thread-count = "2", die ersten 2 Klassen laufen gut, aber der Rest läuft überhaupt nicht es sagt Session-ID ist Null –

+0

@DustinN. Vielleicht möchten Sie einen Blick auf diesen Blogbeitrag von mir werfen https://rationalemotions.wordpress.com/2013/07/31/parallel-webdriver-executions-using-testng/ für eine vollständige Lösung. Ohne zu sehen, was Sie tun, ist es schwer zu sagen, was schief läuft. Aber ich kann Ihnen versichern, dass die Lösung, die ich geteilt habe, nicht dazu führt, dass Webdriver-Instanzen über Threads verbreitet werden. –

Verwandte Themen