J'ai un fichier de suite de tests avec une classe ayant 3 méthodes. Au niveau de la suite, j'ai donné parallel = "methods" thread-count = "3" afin que 3 threads s'ouvrent en parallèle pour chaque méthode de la classe.
Lors de l'exécution de la suite, 3 threads (navigateur) sont ouverts en lançant l'URL mais seul le 3ème thread / navigateur est exécuté selon les étapes de la méthode. Pour les 2 premiers fils / navigateur, aucune action n'a été effectuée.
J'ai beaucoup essayé de trouver des réponses à ce problème, mais je n'ai pas trouvé de solution. Voici le code que j'utilise et veuillez me corriger si je manque quelque chose.
BaseClass:
=============================================== Suite Total tests run: 3, Failures: 2, Skips: 0 ===============================================
Classe avec TestMethods
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Suite" parallel="methods"> <test thread-count="5" name="Test"> <classes> <class name="website.NewTest"/> </classes> </test> <!-- Test --> </suite> <!-- Suite -->
Suite File
public class NewTest extends BaseClass{ @Test() public void method1() { driver.findElement(By.name("q")).sendKeys("parallel"); driver.findElement(By.name("q")).sendKeys(Keys.ENTER); } @Test() public void method2() { driver.findElement(By.name("q")).sendKeys("methods"); driver.findElement(By.name("q")).sendKeys(Keys.ENTER); } @Test() public void method3() { driver.findElement(By.name("q")).sendKeys("testng"); driver.findElement(By.name("q")).sendKeys(Keys.ENTER); } }
Résultat attendu: 3 navigateurs à ouvrir en parallèle. Le premier navigateur doit rechercher «parallèle». Le 2ème navigateur doit rechercher des "méthodes". Le troisième navigateur doit rechercher «automation».
Résultat réel: 3 navigateurs s'ouvrent en parallèle mais 2 navigateurs qui sont ouverts en premier effectuent des actions selon la méthode et le dernier navigateur ouvert recherche le mot "parallelmethodtestng" et se ferme. Les 2 premiers navigateurs ouverts ne se ferment ni ne maximisent selon le code.
public class BaseClass { public WebDriver driver; public WebDriverWait wait; @BeforeMethod() public void configure() { System.setProperty("webdriver.chrome.driver","C:\\SeleniumDrivers\\chromedriver.exe"); driver=new ChromeDriver(); driver.get("https://www.google.com"); driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @AfterMethod() public void tearDown() { driver.quit(); } }
J'espère que cela vous aidera.
4 Réponses :
WebDriver n'est pas thread-safe. Je peux citer la FAQ sur Selenium
Q: WebDriver est-il thread-safe?
R: WebDriver n'est pas thread-safe. Cela dit, si vous pouvez sérialiser l'accès à l'instance de pilote sous-jacente, vous pouvez partager une référence dans plusieurs threads. Ce n'est pas conseillé. Vous / pouvez / d'autre part instancier une instance WebDriver pour chaque thread.
Ce n'est pas pertinent si votre solution est utilisée dans de grands ou petits projets. Si vous souhaitez mettre à l'échelle votre solution, vous pouvez toujours utiliser une grille Selenium pour une exécution parallèle. Les objets WebDriver locaux ne seront pas votre problème. Votre problème sera de perdre de la mémoire en mangeant des instances Chrome.
Merci pour les informations utiles Jens Dibbern :)
Je suggère d'utiliser l'extension qaf TestNG , qui prend en charge la gestion des pilotes, la gestion des ressources et bien d'autres pour l'automatisation des tests fonctionnels des services Web, mobiles et Web. Avec qaf , votre classe de test peut ressembler à ceci:
public class NewTest extends WebDriverTestCase{ @Test() public void method1() { getDriver().get("https://www.google.com"); getDriver().findElement(By.name("q")).sendKeys("parallel"); getDriver().findElement(By.name("q")).sendKeys(Keys.ENTER); } @Test() public void method2() { getDriver().get("https://www.google.com"); //another improved way WebElement ele = getDriver().findElement(By.name("q")); ele.sendKeys("methods"); ele.sendKeys.submit(); } @Test() public void method3() { getDriver().get("https://www.google.com"); //another way with qaf WebElement ele = $("name=q"); ele.sendKeys("testng"); ele.sendKeys.submit(); } }
Si vous souhaitez utiliser uniquement TestNG sans aucune extension, vous devez gérer le pilote Web via ThreadLocal
public synchronized WebDriver createDriver() { return new ChromeDriver(options.getOptions()); } @BeforeMethod(alwaysRun = true) public void setupDriver(String browser) { driver.set(CcreateDriver()); } public synchronized WebDriver getDriver() { return driver.get(); }
Les pilotes doivent être créés via des méthodes synchronisées.
private final ThreadLocal<WebDriver> driver = new ThreadLocal<>();
Cela peut se produire car thread-count
n'est pas au bon endroit. Selon la documentation de TestNG, thread-count
doit être dans la balise suite . Veuillez l'utiliser comme indiqué ci-dessous.
<suite name="My suite" parallel="methods" thread-count="5">
Consultez la documentation de test ici:
http://testng.org/doc/documentation-main.html#parallel-running
Vos 3 méthodes de test utilisent des variables partagées
driver
etwait
. Pour être en mesure d'exécuter correctement et en toute sécurité des méthodes en parallèle, je pense que vous devez rendre ces variables locales à chaque méthode de test.Oui, la variable locale peut fonctionner, mais mon intention est d'atteindre le résultat escompté dans d'énormes projets. Dans de tels cas, la création de variables locales pour chaque méthode ne fonctionnera pas. Je veux que mon script s'exécute comme prévu, quel que soit le type de méthode parallèle. L'exécution parallèle des tests et des classes fonctionne comme prévu, mais pas la méthode. S'il vous plait, j'ai besoin de votre aide avec ceci.
Vous comprenez que dans l'exécution parallèle des méthodes de test, il est possible que pendant qu'un thread exécute
@BeforeMethod
un autre thread exécuteAfterMethod
arrêtantWebDriver
qui est sur le point d'être utilisé dans un autre fil, n'est-ce pas? Si vous avez beaucoup de méthodes / classes de test, essayez d'exécuter chaque classe de test dans un thread séparé.Oui, je comprends cela, je m'excuse pour la confusion ici. S'il vous plaît, aidez-moi à obtenir le résultat attendu sans créer de variable locale (le cas échéant).