2017-03-09 1 views
0

J'essaie d'exécuter des tests Selenium Webdriver en parallèle sur une seule machine, en utilisant TestNG. J'ai 3 méthodes @Test, où 3 utilisateurs différents se connectent à la même application et atteignent la page d'accueil. J'ai besoin que les méthodes @Test s'exécutent en parallèle et écrivent dans un rapport ExtentReports.Selenium Webdriver Les tests TestNG "écrasent" les uns les autres

Mon problème est, en dépit de 3 méthodes complètement différentes dans différentes classes, un des utilisateurs sera connecté dans 2 des 3 navigateurs, laissant un utilisateur dehors.

La méthode de connexion est située dans une classe d'objets de page PageFactory.

Voici mes 3 méthodes d'essai:

@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) { 
    } 
} 

Donc, si je fais une pause les tests sur la page d'accueil. Je vais avoir 2 fenêtres de navigateur ouvertes comme "John", un "Bob" et pas de "Sam" ... Causer des échecs.

Voici la méthode de connexion de l'objet PageFactory. Au début, je vous le problème

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)); 
} 

était dans le filetage de @BeforeMethod (Comme dans, les tests ont été dans un thread différent de celui @Before et @After). Mais je ne vois pas comment cela pourrait être le cas. La méthode de test de base ouvre et ferme avec succès 3 navigateurs. Il semble que les méthodes @Test utilisent les données de l'autre! Mais juste au cas où, voici mon @Before et @After, avec mon code Threading.

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"); 
    } 
} 

Répondre

2

En supposant que toutes vos méthodes @Test sont dans les différentes classes, je devine que le problème est peut-être dû au fait que votre ThreadLocal variable est pas STATIC mais est une variable d'instance . Cela provoque le comportement à par thread par instance plutôt que le comportement souhaité à savoir, par thread dans toutes les instances. Vous pouvez vous référer au fil this StackOverFlow pour une meilleure explication à ce sujet.

Vous recourrait à l'aide d'une variante d'instance de ThreadLocalsi et seulement si toutes vos @Test méthodes appartiennent à la même classe de test (parce que maintenant vous essayez seulement de faire en sorte que le membre de données de niveau de classe WebDriver est partagée dans un fil de manière sûre à travers toutes les méthodes d'essai qui appartiennent à la même classe de test)

donc, si chacun de vos méthodes @Test résident dans sa propre classe de test, s'il vous plaît essayez de changer:

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

à

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

Krishnan, qu'est-ce qui ne va pas dans ma réponse ci-dessous? Je voudrais apprendre. – Dineshmohan

+0

@Dineshmohan - J'ai corrigé la partie du vote vers le bas.D'un autre côté, je pense que votre solution peut être affectée par un comportement bizarre que Java affiche lorsque vous essayez de travailler avec ThreadLocals dans lequel la valeur initialValue() est définie dans une portée de méthode et lorsque cette valeur dépend d'une portée englobante. Vous pouvez en lire plus à ce sujet dans mon blog https://rationaleemotions.wordpress.com/2016/05/16/a-date-with-threadlocal/ (Je ne sais pas si votre code affichera le même problème, mais il a le même type de code qui pourrait causer des problèmes) –

0

Vous pourriez essayer.

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(); 
} 

}

+0

J'ai par erreur fini par cliquer dessus. Mes excuses. Depuis hier j'ai essayé de le réparer mais avec peu de chance. Je l'ai maintenant réparé. Désolé pour la confusion. –