Home > Software engineering >  TestNG's @Test annotation not executed properly with the mvn command
TestNG's @Test annotation not executed properly with the mvn command

Time:02-09

Everything with the @Test annotation throws null pointer exception, regardless of the method called. I tried calling driver.findElement() and executing js script with JavascriptExecutor. Both methods ended up with a null pointer. If I run through the IDE everything works like a charm. Otherwise, only the Before and After annotations are executed adequately Here's my pom.xml:

   <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">

<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.9</version>
            <configuration>
                <parallel>methods</parallel>
                <threadCount>1</threadCount>
            </configuration>
        </plugin>
    </plugins>
</build>

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.1.1</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.testng/testng -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.5</version>
        <scope>test</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.10</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.apache-extras.beanshell</groupId>
        <artifactId>bsh</artifactId>
        <version>2.0b6</version>
    </dependency>
</dependencies>

<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>

 </project>

and testng.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Practice Suite">
<test name="Test Basics 1">

    <method-selectors>
        <method-selector>
            <script language="beanshell">
                <![CDATA[
                String testGroup = System.getProperty("env");
                groups.containsKey(testGroup);
            ]]>
            </script>
        </method-selector>
    </method-selectors>
    
    <classes>
        <class name="tests.SignUpTest"/>
    </classes>
</test>

 </suite>

and finally the two manners I am using to run the test:

mvn -Dwebdriver=chrome -Denv=qa install

mvn -Dwebdriver=chrome -Denv=qa test

EDIT:

BeforeTest and Test:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.safari.SafariDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;

public class BaseTest {


protected  WebDriver driver;

private WebDriver selectDriver(String driver)

    switch (driverString) {
        case "chrome":
            return new ChromeDriver();
        case "firefox":
            return new FirefoxDriver();
        case "edge":
            return new EdgeDriver();
        case "safari":
            return new SafariDriver();
        default:
            return new ChromeDriver();
    }
    
}

     @BeforeTest(alwaysRun = true)
    public void testInit() {

        driver = selectDriver(System.getProperty("webdriver"));

    }

}

import additions.BaseTest;
import org.testng.Assert;
import org.testng.annotations.Test;
import pages.DashBoardPage;
import pages.LoginPage;


public class LoginTest extends BaseTest {

@Test
public void successfulLogin(){
    LoginPage loginPage = new LoginPage(driver);

    loginPage
            .populateUserName("somename")
            .populatePassword("somepassowrd")
            .clickLoginButton();

}

}

CodePudding user response:

Since still there is some uncertainty in the question, I'll try to share my thoughts around this.

If I run through the IDE everything works like a charm.

There are several ways how to run this in IDE:

  1. Run the test class.

    In this case IDE generates own testng.xml which not match the example (from the question), so it will not contain any method-selector items.

  2. Run the testng.xml

    In testng.xml there is method-selector which expects System.getProperty("env") provided. If you run testng.xml from IDE, you have to provide somehow
    System.getProperty("env") via IDE settings, otherwise you'll see org.testng.TestNGException: javax.script.ScriptException error.


If I look at testng.xml, I see method-selector, which filter tests by System.getProperty("env").

And If I look at the test:

@Test
public void successfulLogin(){
    LoginPage loginPage = new LoginPage(driver);

I see no any group defined for it. So this test cannot be executed with maven command. And it's unclear how it might throw any exception.


If I look at maven command

mvn -Dwebdriver=chrome -Denv=qa test

I cannot see the arg defining which testng xml suite to execute.

I expect the command like:

mvn test -Dwebdriver=chrome -Denv=qa -Dsurefire.suiteXmlFiles="src/test/resources/tests.xml"

Expected behavior

When we execute the maven command:

mvn test -Dwebdriver=chrome -Denv=qa -Dsurefire.suiteXmlFiles="src/test/resources/tests.xml"

method-selector in testng.xml looks for methods matching the qa group.

and there are no any methods, matched this group.

But there are some configuration methods with alwaysRun = true, and they will be executed anyway.

So

 @BeforeTest(alwaysRun = true)
    public void testInit() {

is invoked without any tests,

and the output will be:

[INFO] Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.345 s - in TestSuite
[INFO] 
[INFO] Results:
[INFO]
[INFO] Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11.867 s

And the test will be executed if we'll add the group:

@Test(groups= {"qa"})
public void successfulLogin(){

CodePudding user response:

I've solved it. It turns out that initialising the driver with the @BeforeTest annotation is not a good idea, especially if your teardown method is marked with @AfterTest. The driver is initialised and used correctly in the first @Test method, but on the second one, the teardown method is already called and the driver becomes null. So I used @BeforeClass and @AfterClass (I might reconsider and use @Before/AfterSuite). Then I added the following configuration to the pom.xml

    <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.2</version>
            <configuration>
             
                <suiteXmlFiles>
                    <suiteXmlFile>testng.xml</suiteXmlFile>
                </suiteXmlFiles>
            </configuration>
        </plugin>
    </plugins>
</build>

Then I added the package with the tests I wanted to execute, in the testng.xml file, like this:

        <packages>
        <package name="path.to.tests.*"></package>
    </packages>

Finally I called the mvn command using the following syntax:

mvn test -Dsurefire.suiteXmlFiles=testng.xml  -Dwebdriver="chrome" -Denv="qa"

This way you don't have to call the path to the testng.xml file, but rather call it out of the pom.xml. As a side note to the last sentence, my testng.xml file is located in the project directory, along with the src folder. If you put it in another folder, I guess it will be good to set the path to this folder in the pom.xml

I hope this is understandable and it will be helpful for anyone who gets stuck with such issue.

Thank again to the others for the clues.

  •  Tags:  
  • Related