2009-07-19 18 views
3

J'utilise Selenium avec TestNG pour tester un site Web. J'ai créé des tests en utilisant l'IDE Selenium et les ai exportés vers TestNG, chaque test étant une méthode dans une classe. Par exemple,Comment obtenir Selenium et TestNG pour ouvrir un navigateur pour exécuter des tests dans plusieurs classes

Pour les tests de connexion il y a une classe de connexion qui a des méthodes TESTLOGIN(), testlogin2() etc Pour les tests d'inscription il y a une classe Signup a des méthodes testSignup(), testSignup2(), etc

I J'utilise Ant pour lancer les tests qui fonctionnent bien sauf que chaque classe ouvrira un navigateur et exécutera ses méthodes, par exemple, si j'ai cinq classes, alors cinq navigateurs s'ouvriront simultanément et ensuite lanceront les tests. Ce que je veux, c'est que Ant/Selenium/TestNG ouvre simplement un navigateur et exécute tous les tests (dans le même navigateur) dans toutes les classes que j'ai spécifiées dans testng.xml. En utilisant l'exemple ci-dessus, je veux ouvrir un navigateur puis exécuter testLogin(), testLogin2(), testSignup(), testSignup2(). Si cela ne peut pas être réalisé, alors je veux ouvrir un navigateur, exécuter tous les tests dans une classe, puis fermer le navigateur, puis ouvrir un autre navigateur puis exécuter l'ensemble des méthodes de test dans la classe suivante.

Toute aide appréciée. Merci d'avance.

Répondre

2

Aujourd'hui, j'ai trouvé la réponse qui fonctionne pour moi. Donnez-moi quelques minutes pour rassembler tous les échantillons de code :)

Init.java

//base class that will be called before all tests 
@Test(groups = "init") 
public class Init{ 

    DefaultSelenium browser; 

    public void start(ITestContext itc){ 
     browser = (DefaultSelenium) itc.getAttribute("browser"); 
     browser.open("url"); 
     browser.click("xpath"); 
    } 

} 

TemplateForClasses.java

/* - all public methods will be tests 
* - all tests will be called after group init 
* - just before suite will start we will start 1 browser instance 
*/ 
@Test(dependsOnGroup="init") 
public class TemplateForClasses{ 

    DefaultSelenium browser; 

    @BeforeSuite 
    public void startBrowser(ITestContext itc){ 
     browser = new DefaultSelenium(host,port,browser_type,url); 
     itc.setAttribute("browser",browser); 
     browser.start(); 
    } 

    @AfterSuite 
    public void stopBrowser(ITestContext itc){ 
     browser = (DefaultSelenium) itc.getAttribute("browser"); 
     browser.stop(); 
    } 

    //any other: @Before, @After methods 

} 

FirstGroupOfTests.java

//all tests classes will inherit preferences set in TemplateForClasses 
public class FirstGroupOfTests extends TemplateForClasses{ 

    public void FirstTest(ITestContext itc){ 
     browser = (DefaultSelenium) itc.getAttribute("browser"); 
     //browser.click("start"); 
    } 

} 

idée:

  • navigateur de démarrage ont une fois les tests
  • qui courent avant tous les autres tests (isBrowserRunning)
  • se réfèrent au navigateur de test unique

Ce code a été testé, mais actuellement je l'ai pris du haut de mon tête si possible je vais l'éditer demain pour le rendre plus exact.

Mise à jour: Ce résultat est basé sur la documentation testng.org + quelques questions posées par moi sur stackoverflow + quelques réponses trouvées sur plusieurs forums/groupes

Je dois ajouter que je suis en testng programatically et je suis générer du XML à la volée (comme cela est fait sur documentation.org). J'utilise tout dans un paquet, j'ai ajouté le paquet au xml, inclus seulement les classes Init + celles qui héritent de TemplateForClasses. Si vous avez besoin de ce XML, faites le moi savoir.

0

J'ai aussi été coincé dans le même problème pendant un certain temps. Je vais l'expliquer dans les termes les plus simples possibles. Prenons l'exemple suivant:

Class A (contains the code selenium.start();) 
| 
|(inherited classes) 
|--------class B } 
|--------class C } Have some @Test methods 
|--------class D } 

Maintenant, chaque fois que nous courons ces méthodes d'essai, il exécutera le code dans le constructeur de la classe mère selenium.start(); C'est quand les multiples navigateurs s'ouvriront tous sur votre écran.

Maintenant, un par un, les méthodes de test seront exécutées - supposons que les tests dans la classe B sont exécutés, ils se passeront dans une fenêtre, pour la classe C une autre et ainsi de suite.

Donc, en gros, tout ce que vous avez à faire est de supprimer le code start() du constructeur parent et le mettre quelque part dans les classes B, C et D.

Tant que vous continuez à travailler avec un objet sélénium tout se passera dans une fenêtre de navigateur. Quand vous mettez start(); ce navigateur s'ouvrira (s'il n'était pas ouvert) et une nouvelle session sera créée. Arrêtez(); et la session est terminée.

Le flux de contrôle va comme ceci =>

Class A, Class B 
Class A, Class C 
Class A, Class D 

Donc, si vous pouvez trouver un moyen de continuer à utiliser le même objet de sélénium avec seulement 1 départ() et 1 arrêt() pour toute l'exécution séquence illustrée ci-dessus, l'exécution de votre test se fera dans une seule fenêtre du navigateur. Si vous mettez le code start() dans la classe A et le code d'arrêt dans chacun des points B, C et D, vous aurez 3 fenêtres ouvertes et une à la fois elles se fermeront au fur et à mesure de l'exécution.

Si vous mettez les codes start() et stop() individuellement dans B, C et D alors vous verrez un navigateur s'ouvrir, exécuter des cas de test, fermer. Un autre s'ouvrira alors, exécutera des cas de test pour C, fermera etc.

Espérons que cela aide. :-)

+0

Pourriez-vous s'il vous plaît partager le code réel? – paul

0

Je l'ai fait avec l'injection de dépendance de Spring. Et le code init est dans une usine. J'avais besoin d'un moyen d'avoir une instance de Selenium partagée non seulement entre les tests mais entre les classes auxiliaires. Selenium.someMethod() est rarement appelé directement dans les tests. Il ressemble plus à helper.goToSomePage() ou à preferencesPage.changePassword (....).

Il peut être considéré comme une mauvaise idée de partager une instance de Selenium entre les tests, mais les quelques bogues qu'elle contient n'ont pas été si difficiles à trouver. Les tests sont exécutés séquentiellement et l'objet Selenium n'a pas besoin d'être thread-safe. L'état de l'objet doit cependant rester cohérent. Pour info, Spring est un framework Java et l'injection de dépendances n'en est qu'une partie. D'autres frameworks DI comme Guice peuvent bien sûr être utilisés à la place.