3
votes

TestNg n'exécute pas les annotations @test avec 'driver.find' mais fonctionne uniquement avec 'syso-printing

J'ai du mal à démarrer un nouveau paquet avec TestNg. Remarque J'ai simplifié le code pour essayer de comprendre où je me suis trompé. À @Test (priority = 3) , je rencontre le problème. Cela ne me permet pas de cliquer sur un bouton.

J'ai vérifié le compilateur et exécuté la version 1.8, ce qui est très bien.

J'ai vérifié mon projet précédent qui fonctionne très bien mais je n'ai pas vu de différences. J'ai aussi mes dépendances qui sont maven, sélénium, testng qui a l'air bien. J'ai importé la bibliothèque qui est bonne.

Le kicker est que TestNg a très bien fonctionné dans mon dernier projet il y a peut-être un mois sur le même ordinateur et tout.

@Test(priority=2)
 public void OpenBrowserChrome ()
 {
        // Create a new instance of the Chrome driver
    WebDriver driver = new ChromeDriver();
        //WebDriver driver = new InternetExplorerDriver();
    driver.get("https://testng.org/doc/index.html");
        // To maximize the browser
    driver.manage().window().maximize();
        // implicit wait
    driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
        // Print a Log In message to the screen
    System.out.println("Successfully opened the website ");


    driver.get("https://testng.org/doc/index.html");
    driver.findElement(By.xpath("//*[@id='topmenu']/table/tbody/tr[2]/td[1]/a")).click();



}

Voici mon testng.xml:

FAILED: Issue
java.lang.NullPointerException
at com.Prod.dtx_project.DIF1v2.Issue(DIF1v2.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.testng.internal.MethodInvocationHelper.invokeMethod 
(MethodInvocationHelper.java:124)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:580)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:716)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:988)
at org.testng.internal.TestMethodWorker.invokeTestMethods 
(TestMethodWorker.java:125)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
at org.testng.TestRunner.privateRun(TestRunner.java:648)
at org.testng.TestRunner.run(TestRunner.java:505)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
at org.testng.SuiteRunner.run(SuiteRunner.java:364)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
at org.testng.TestNG.runSuites(TestNG.java:1049)
at org.testng.TestNG.run(TestNG.java:1017)
at org.testng.remote.AbstractRemoteTestNG.run     
(AbstractRemoteTestNG.java:114)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
===============================================
Default test
Tests run: 5, Failures: 1, Skips: 0
===============================================

Aussi, voici le message d'erreur que je reçois dans le Console -

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="Suite">

  <test name="Regression Testing">
    <classes>
      <class name="com.Prod.dtx_project.DIF1v2"/>
    </classes>
  </test>   

</suite> 

Je m'attendais à ce qu'il s'ouvre sur l'URL et clique sur le bouton éclipse sur cette page, mais ce n'est pas le cas.

REMARQUE: lorsque je déplace le driver.get et driver.findElement dans le @Test (priority = 2), alors CELA MARCHE. Veuillez voir ci-dessous. CEPENDANT, comment puis-je exécuter mon TestNG avec cette mise en page. Pourquoi cela fonctionne-t-il, mais lorsque vous utilisez plus d'une annotation @Test, cela échoue.

package com.Prod.dtx_project;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;


public class DIF1v2 {

protected WebDriver driver;

@Test(priority=1)
public void initialization()
{
    // To set the path of the Chrome driver.
    System.setProperty("webdriver.chrome.driver", "C:\\Program Files\\Eclipes\\ChromeDriver\\chromedriver.exe");
}

@Test(priority=2)
public void OpenBrowserChrome ()
{
    // Create a new instance of the Chrome driver
    WebDriver driver = new ChromeDriver();
    //WebDriver driver = new InternetExplorerDriver();
    driver.get("https://testng.org/doc/index.html");
        // To maximize the browser
    driver.manage().window().maximize();
        // implicit wait
    driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
        // Print a Log In message to the screen
    System.out.println("Successfully opened the website ");

    driver.findElement(By.xpath("//*[@id='topmenu']/table/tbody/tr[2]/td[1]/a")).click();

}

@Test(priority=3)    //IT FAILED HERE WHEN USING A NEW ANNOTATION// 
public void Issue ()
{
driver.findElement(By.xpath("/html/body/a[13]")).click();

}

@Test(priority=4)
public void LandingPage ()
{
    System.out.println("LandingPage-4");

}

@Test(priority=5)
private void publ() 
{
    System.out.println("publ-5");
}



}


6 commentaires

Ouvre-t-il la page? Si vous mettez un point d'arrêt à l'appel de driver.findElement , ce xpath se résout-il réellement en lien?


Y a-t-il une erreur associée à "... ne me permettant pas de cliquer ..." ou à toute autre information pertinente? Veuillez lire l ' exemple minimal reproductible .


Aussi, merci, j'ai ajouté le message d'erreur ci-dessus.


Il a échoué à @Test (priorité = 3)


Oui, la page s'ouvre mais elle doit s'ouvrir et cliquer sur le bouton. Quand je prends le driver.findElement dans le xPath, il passe. Mais l'inclure échouera.


Ont répondu à la question, faites-moi savoir si cela aide.


3 Réponses :


0
votes

Il donne nullpointer à l'instruction driver.get car vous n'avez pas initialisé le driver dans le test priority = 3.
La portée de chaque test est différente, vous devez donc l'initialiser dans chaque test que vous souhaitez utiliser.

En priorité = 2, vous l'avez initialisé en utilisant driver = new ChromeDriver (); , donc de la même manière vous devez l'initialiser dans le test priority = 3, puis vous devez exécuter driver.get (url) et cela fonctionnerait.

Votre test 2 et votre test 3 devraient être comme:

@Test(priority=2)
public void OpenBrowserChrome()
{
    WebDriver driver = new ChromeDriver();
    driver.get("https://testng.org/doc/index.html");
    driver.manage().window().maximize();
    driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
    System.out.println("Successfully opened the website ");
    driver.findElement(By.xpath("//[@id='topmenu']/table/tbody/tr[2]/td[1]/a")).click();
    driver.quit();

}

@Test(priority=3)
public void Issue() throws InterruptedException
{
    WebDriver driver = new ChromeDriver();
    driver.get("https://testng.org/doc/index.html");
    driver.findElement(By.xpath("//[@id='topmenu']/table/tbody/tr[2]/td[1]/a")).click();
    Thread.sleep(5000);
    driver.findElement(By.xpath("/html/body/a[13]")).click();
    driver.quit();

}

Si vous voulez pour cliquer sur deux éléments en continu comme dans le test3, vous devez créer une instance distincte du pilote autre que celle de test2, puis appuyez à nouveau sur l'url, puis vous devez cliquer sur les éléments. Dans le scénario ci-dessus, vous pouvez supprimer le test2 car il ne résout actuellement aucun objectif pour vous et vous pouvez effectuer les deux opérations dans le test3.


19 commentaires

Bonjour Sameer, j'ai défini ce qui suit ci-dessous et cela échoue toujours à @Test (priory = 3)


@Test (priority = 2) public void OpenBrowserChrome () {pilote WebDriver = nouveau ChromeDriver (); driver.get (" testng.org/doc/index.html" ); pilote. findElement (By.xpath ("// * [@ id = 'topmenu'] / table / tbod‌ y / tr [2] / td [1] / a")). c‌ lick ();} @Test ( priority = 3) public void Issue () {driver.findElement (By.xpath ("/ html / body / a [13]")). click ();}


Dans le @Test (priority = 3), veuillez ajouter une ligne de code WebDriver driver = new ChromeDriver (); avant driver.findElement (By.xpath ("/ html / body / a [13] ")). Cliquez sur (); et cela fonctionnerait.


Iv a remarqué que si toutes les étapes étaient inférieures à 1 @ Test, cela fonctionne. Mais continuer à dire @ Test p3, et le faire démarrer à partir d'un navigateur ouvert déjà pour trouver un élément ne fonctionnera pas.


J'ai mis à jour ma réponse, veuillez vérifier cela. Et vos test2 et 3 sont différents, leur portée est différente, vous devez donc à nouveau initialiser le pilote, puis à nouveau appuyer sur l'url, puis opérer sur l'élément. J'ai également ajouté driver.quit (); à la fin des tests afin que le navigateur précédent se ferme après son exécution. Veuillez vérifier la réponse mise à jour et essayez cela.


J'ai modifié ma réponse, veuillez vérifier maintenant. Si vous voulez que peu de choses se poursuivent, vous devez faire ces choses sous un seul test, car chaque test nécessite son pilote séparément.


Bonjour Sameer, Oui, votre code fonctionne. Merci beaucoup. Mais j'ai pensé en utilisant TestNG que je pourrais l'utiliser pour les tests basés sur les données pour rappeler une méthode en utilisant une méthode @ Test par exemple. un mot de passe de connexion. La méthode ci-dessus montre le long de la ligne pour avoir de nombreux scripts et étapes de test dans chaque annotation @ Test.


Mon objectif était de faire ce qui suit dans 1 fichier de classe: @ Test p1 // lancer le pilote @ Test p2 // entrer les valeurs du formulaire @ Test p3 // login @ Test p4 // remplir le formulaire sous un profil différent


J'ai compris votre point, mais dans la classe de test, un test décrit un flux et les choses que vous faites relèvent d'un flux, vous devez donc faire tout cela en un seul test. Si vous avez un autre flux, vous devriez faire un autre test. Et veuillez voter pour et accepter la réponse si cela vous aide :)


Et une autre suggestion, vous pouvez utiliser @BeforeTest et en ce sens que vous pouvez initialiser le pilote Web et ouvrir l'URL. Beforetest s'exécute avant chaque test, vous n'avez donc pas besoin de faire l'initialisation du pilote à chaque fois sous votre test.


J'ai d'abord utilisé @Before Suite pour System.setProperty et @ BeforeTest pour lancer le navigateur. Puis utilisé @ Test pour les étapes de test et toujours lors de l'utilisation du deuxième @ Test, il a échoué. J'ai donc fini par supprimer lentement chaque étape une par une pour diagnostiquer le problème. J'ai fini avec le script d'organisation ci-dessus et je n'ai pas pu le comprendre.


Oui, car lorsque vous utilisez beforesuite ou beforetest, vous initialisez le pilote là-bas et après cela, vous devez passer ce pilote à la classe de test, sinon il échouerait également comme s'il échouait maintenant. Ma suggestion serait que vous devriez commencer par les bases et faire un flux dans un test, puis vous devriez commencer à utiliser beforesuite ou beforetest par la suite lorsque vos bases sont claires.


Et veuillez voter pour et accepter la réponse si cela vous aide :)


Bonjour Sameer, donc, juste pour clarifier, lors de l'exécution d'un fichier de classe, l'annotation acceptable serait de n'utiliser qu'une seule fois @Test + tout avant / après ect. exécuter un cas de test? et l'utiliser plus d'une fois gâchera TestNG. Merci pour la clarification.


De plus, j'ai fait le vote positif et j'ai reçu le message suivant. :) "Merci pour les commentaires! Les votes exprimés par ceux qui ont moins de 15 points de réputation sont enregistrés, mais ne modifient pas le score affiché publiquement.


Il peut y avoir n nombre de tests, vous devez écrire test pour chaque flux que vous voulez tester mais il ne peut y avoir qu'un seul avant-suite, un avant-test, un avant-méthode et même pour après-test et après-méthode.


Et si vous utilisez beforetest ou suite, vous devez passer le pilote au test du beforetest pour l'utiliser. Et si vous n'utilisez que des tests, vous devez initialiser le pilote à chaque fois et vous devez faire un test pour un flux et vous pouvez effectuer n'importe quel nombre de tests dans votre classe.


Vous devriez vous référer à ce lien, c'est très utile !! guru99.com/all-about-testng-and-selenium.html < / a>


Et vous pouvez marquer la réponse comme acceptée en cliquant sur la coche, veuillez faire si cela vous a aidé :)



0
votes

l'ajout d'un @BeforeClass pour systems.setProperty a fini par fonctionner.


0 commentaires

0
votes

Dans @Test (priority = 2), supprimez "WebDriver" alors tout fonctionnera correctement. J'ai testé.

Sous "classe publique DIF1v2", vous aviez "pilote WebDriver protégé". Cela signifie que "pilote" est une variable d'instance (variable définie dans une classe) - variable déclarée sous la classe, en dehors de toutes les méthodes. Dans ce cas, "driver" a la valeur par défaut de null.

Mais dans @Test (priority = 2), il y a "WebDriver driver = new ChromeDriver ();". Vous déclarez "pilote" comme "WebDriver". Ceci est un autre "pilote". Ce "pilote" est une variable locale. Ce "pilote" appartient uniquement à @Test (priorité = 2). Sa valeur n'affecte que dans @Test (priority = 2).

L'erreur "java.lang.NullPointerException" dans @Test (priority = 3) est causée par driver = null. Vous appelez la méthode findElement de null.

Pour que la valeur reste de méthode en méthode, une variable doit être une variable d'instance. Voyons un test. J'ai ajouté une variable de chaîne "test".

123
LandingPage-4
publ-5
PASSED: initialization
PASSED: OpenBrowserChrome
PASSED: Issue
PASSED: LandingPage
PASSED: publ

SORTIE:

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;


public class DIF1v2 {

protected WebDriver driver;
protected String test = "123"; //// THIS INSTANCE VARIABLE IS FOR TESTING.
@Test(priority=1)
public void initialization()
{
    // To set the path of the Chrome driver.
    System.setProperty("webdriver.chrome.driver", "C:\\Program Files\\Eclipes\\ChromeDriver\\chromedriver.exe");
}

@Test(priority=2)
public void OpenBrowserChrome ()
{
    String test = "456";       //// THIS IS ANOTHER "test". JUST THE SAME NAME.
    // Create a new instance of the Chrome driver
    driver = new ChromeDriver();
    //WebDriver driver = new InternetExplorerDriver();
    driver.get("https://testng.org/doc/index.html");
        // To maximize the browser
    driver.manage().window().maximize();
        // implicit wait
    driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
        // Print a Log In message to the screen
    System.out.println("Successfully opened the website ");

    driver.findElement(By.xpath("//*[@id='topmenu']/table/tbody/tr[2]/td[1]/a")).click();

}

@Test(priority=3)    //IT FAILED HERE WHEN USING A NEW ANNOTATION// 
public void Issue ()
{
    System.out.println(test);  //// THIS WILL PRINT "123"
    driver.findElement(By.xpath("/html/body/a[13]")).click();

}

@Test(priority=4)
public void LandingPage ()
{
    System.out.println("LandingPage-4");

}

@Test(priority=5)
private void publ() 
{
    System.out.println("publ-5");
}



}

J'ai initialisé la variable d'instance:

protected String test = "123";

Dans @Test (priority = 2), j'ai initialisé une autre variable avec le même nom:

String test = "456";

Ensuite, dans @Test (priority = 3), j'ai:

System.out.println (test);

Le résultat imprimé est:

123


0 commentaires