I am new to selenium and I am trying setup a Automation framework, I have two classes one for Webdriver (Base class) initialization and second is to run testScripts I have Marked the Webdriver initialization with @BeforeSuite Tag
public class Base {
Logger logs = StartLogging("Base");
public static String browser;
public static WebDriver driver;
//Browser installization
@BeforeSuite
public void browserSetup() throws IOException{
browser = readConfigData("browser");
if (browser.equalsIgnoreCase("Chrome")) {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
} else if (browser.equalsIgnoreCase("Firefox")) {
WebDriverManager.firefoxdriver().setup();
driver = new FirefoxDriver();
} else if (browser.equalsIgnoreCase("edge")) {
WebDriverManager.edgedriver().setup();
driver = new EdgeDriver();
}
driver.get(readConfigData("TestURL"));
driver.manage().window().maximize();
driver.manage().deleteAllCookies();
logs.fatal(driver);
}
}
Secondly I have a Page object model class where I initialize the web elements
public class loginPage extends Base {
Logger logs = StartLogging("loginPage");
@FindBy(xpath = "//input[@id='user-name']")
WebElement Username;
@FindBy(xpath = "//input[@id='password']")
WebElement PassTab;
@FindBy(xpath = "//input[@id='login-button']")
WebElement Loginbtn;
@FindBy(xpath = "//img[@class='bot_column']")
WebElement Logo;
public loginPage() {
logs.fatal(driver);
PageFactory.initElements(driver, this);
}
//--------------rest of the methods below -------------------------
}
I have a third Test class from which the test are executed
public class LoginTest extends Base {
loginPage lp = new loginPage();
Logger logs = StartLogging("LoginTest");
@Test(priority = 1)
public void VerifyPageTitle() throws IOException, InterruptedException {
String actualTitle = driver.getTitle();
String ExpectedTitle = readConfigData("ExpectedTitle");
assertEquals(actualTitle, ExpectedTitle);
}
@Test(priority = 2)
public void VerifyPageLogo() {
logs.info(lp.IslogoDisplayed());
assertEquals(lp.IslogoDisplayed(), true);
}
@Test(priority = 3)
public void VerifyPageURL() throws IOException {
String ActualURL = driver.getCurrentUrl();
String ExpectedURL = readConfigData("ExpectedURL");
assertEquals(ActualURL, ExpectedURL);
}
//--------------rest of the methods below -------------------------
}
So when Even I try to run the Test from Test Suite the test class runs first before the @BeforeSuite Class which causes Nullreferenceexception on searchContext (when initializing page objects web elements)
TestNG trace looks like this
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.SearchContext.findElement(org.openqa.selenium.By)" because "this.searchContext" is null
at org.openqa.selenium.support.pagefactory.DefaultElementLocator.findElement(DefaultElementLocator.java:68)
at org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler.invoke(LocatingElementHandler.java:38)
at jdk.proxy2/jdk.proxy2.$Proxy46.isDisplayed(Unknown Source)
at com.saucelab.pages.loginPage.IslogoDisplayed(loginPage.java:31)
at com.saucelab.Testcases.LoginTest.VerifyPageLogo(LoginTest.java:28)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.testng.internal.invokers.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:139)
at org.testng.internal.invokers.TestInvoker.invokeMethod(TestInvoker.java:664)
at org.testng.internal.invokers.TestInvoker.invokeTestMethod(TestInvoker.java:227)
at org.testng.internal.invokers.MethodRunner.runInSequence(MethodRunner.java:50)
at org.testng.internal.invokers.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:957)
at org.testng.internal.invokers.TestInvoker.invokeTestMethods(TestInvoker.java:200)
at org.testng.internal.invokers.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:148)
at org.testng.internal.invokers.TestMethodWorker.run(TestMethodWorker.java:128)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.testng.TestRunner.privateRun(TestRunner.java:848)
at org.testng.TestRunner.run(TestRunner.java:621)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:443)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:437)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:397)
at org.testng.SuiteRunner.run(SuiteRunner.java:336)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:95)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1280)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1200)
at org.testng.TestNG.runSuites(TestNG.java:1114)
at org.testng.TestNG.run(TestNG.java:1082)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
I suspect that the TestClass is being called before the Web driver class which causes this error
Upon Debugging the following console output is displayed
19:41:31:241 [main] FATAL loginPage - null
19:41:33:101 [main] FATAL Base - ChromeDriver: chrome on windows (34e5b87c9e9c80670ebcc46b04a7f9e6)
19:41:33:136 [main] INFO ProductPage - Product page loaded
19:41:33:167 [main] INFO YourInformationPage - Entering infomations
As you can notice from the output Loginpage(Test case) log Prints first and Base(Webdriver class) prints second
Note: This issue occurs only for the first POM and rest of the pages get initialized correctly and Test are successful
The Base class (Web driver) should run first but the Login class(Test class) Gets Executed