0
votes

I'm using @dataprovider for the Selenium on Java and TestNg project, specifically on the TestBase class that implements saucelabs desired capabilities. My concern is that this code returns "NullPointerException" error because data provider values is never been taken. Could someone point what is wrong with my code (using the same code as from the example: https://github.com/saucelabs-sample-test-frameworks/Java-TestNG-Selenium/blob/master/src/test/java/com/yourcompany/Tests/TestBase.java)

public class TestBase {

protected WebDriver driver;
protected static String baseUrl;
protected Application app;
protected ConfigFileReader configRead;
protected PropertyLoader propertyRead;
public Logger Log = Logger.getLogger(BasicTest_Local.class.getName());

public static final String SAUCE_ACCESS_KEY = System.getenv("SAUCE_ACCESS_KEY");
public static final String SAUCE_USERNAME = System.getenv("SAUCE_USERNAME");

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



    @DataProvider(name = "hardCodedBrowsers", parallel = true)
     public static Object[][] sauceBrowserDataProvider(Method testMethod) {
            return new Object[][]{              
            new Object[]{"firefox", "55.0", "Windows 10"},                
            new Object[]{"chrome", "65.0", "Windows 10"},                
    };}


    public void createDriver(String browser, String version, String os, String methodName)
        throws Exception, MalformedURLException, UnexpectedException {
        Class<? extends TestBase> SLclass = this.getClass();

        DesiredCapabilities capabilities = new DesiredCapabilities();

        // set desired capabilities to launch appropriate browser on Sauce
        capabilities.setCapability(CapabilityType.BROWSER_NAME, browser);
        capabilities.setCapability(CapabilityType.VERSION, version);
        capabilities.setCapability(CapabilityType.PLATFORM_NAME, os);
        System.out.println(CapabilityType.PLATFORM_NAME + CapabilityType.VERSION + CapabilityType.PLATFORM_NAME);

        capabilities.setCapability("seleniumVersion", "3.8.1");
        capabilities.setCapability("name", SLclass.getSimpleName());
        capabilities.setCapability("screenResolution", "1920x1080");

    this.webDriver.set(new RemoteWebDriver(new URL("http://" + SAUCE_USERNAME + ":" + SAUCE_ACCESS_KEY + "@ondemand.saucelabs.com:80/wd/hub"), capabilities));

    configRead = new ConfigFileReader();

    propertyRead = new PropertyLoader();

    baseUrl = propertyRead.getProperty("site.url");

    app = new Application(driver);
    getURL();

    }





private void getURL () {

    driver.get(baseUrl);
    driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
    Log.info("Open a site URL");

}



@AfterMethod(description = "Throw the test execution results into saucelabs")
public void afterMethod(ITestResult result) throws Exception {

    ((JavascriptExecutor) driver).executeScript("sauce:job-result=" + (result.isSuccess() ? "passed" : "failed"));
    driver.quit();
}

}

FYI: I have tried to add @Test annotation with the dataprovider name before "createDriver" method:

@Test(dataprovider="name") public void createDriver(String browser, String version, String os, String methodName)

but this approach is only opens the browsers and a site url(baseURL) but never go to the test class ("Login") that extends the TestBase class:

  public class Login_and_CreateOrder extends TestBase {

  @Test (groups = {"HappyPath"})
  public void Login() {

    app.homePage().homePageDisplayed();
    Log.info("Validate Home Page");

    app.loginPage().Login_as( 
    configRead.getUserName2(),configRead.getPassword());
    Log.info("Login as user");

    assertTrue(app.loginPage().welcomeMessage.getText().contains("Hello"), 
    "Validate user's login.Display Welcome message");

    }
}

Additional .xml file

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

<suite name="Tests Suite" verbose="2" parallel="methods" thread-count="2">

<test name="SmokeRunTests" parallel="methods" thread-count="2">
    <classes>
           <class name="com.****.tests.Login"/>
       </classes>
   </test>

Error:

[ERROR] Tests run: 2, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 4.448 
s <<< FAILURE! - in TestSuite
[ERROR] Login(com.****.tests.Login)  Time elapsed: 0.365 s  <<< FAILURE!
java.lang.NullPointerException
at com.****.tests.Login.Login(Login.java:13)

[ERROR] afterMethod(com.****.tests.Login)  Time elapsed: 0.455 s  <<< 
FAILURE!
java.lang.NullPointerException

[INFO] 
[INFO] Results:
[INFO] 
[ERROR] Failures: 
[ERROR]   Login.Login:13 NullPointer
[ERROR]   Login.TestBase.afterMethod:95 ยป NullPointer
[INFO] 
[ERROR] Tests run: 2, Failures: 2, Errors: 0, Skipped: 0
[INFO] 
[INFO] ---------------------------------------------------------------------- 
--
[INFO] BUILD FAILURE
[INFO] -------------------------------------
2

2 Answers

0
votes

Your DataProvider has an extra comma,

@DataProvider(name = "hardCodedBrowsers", parallel = true)
 public static Object[][] sauceBrowserDataProvider(Method testMethod) {
        return new Object[][]{              
        new Object[]{"firefox", "55.0", "Windows 10"},                
        new Object[]{"chrome", "65.0", "Windows 10"}, //no need of comma for the last value           
};}

Try this, I have removed that comma and it's working

 @DataProvider(name = "hardCodedBrowsers", parallel = true)
 public static Object[][] sauceBrowserDataProvider(Method testMethod) {
        return new Object[][]{              
        {"firefox", "55.0", "Windows 10"},                
        {"chrome", "65.0", "Windows 10"}                
};}
0
votes

Just edit value for @Test annotation:

@Test (groups = {"HappyPath"}, dataProvider = "hardCodedBrowsers")//you should add data provider
public void Login(String browser, String version, String os, Method method) {
//and add initialization for some browser
    this.createDriver(browser, version, os, method.getName());// you missed this init
    app.homePage().homePageDisplayed();
    Log.info("Validate Home Page");

    app.loginPage().Login_as( 
    configRead.getUserName2(),configRead.getPassword());
    Log.info("Login as user");

    assertTrue(app.loginPage().welcomeMessage.getText().contains("Hello"), 
    "Validate user's login.Display Welcome message");

    }