Creating a webdriver instance across classes | selenium Java - java

Just pitching into Java! Trying to implement BDD style framework...
I'm running into this issue
My Driver.java looks like this:
public class Driver {
public static WebDriver Instance;
#Before
public void InitializeTest() {
System.setProperty("webdriver.chrome.driver", "C://chromedriver.exe");
Instance = new ChromeDriver();
}
#After
public void TearDownTest(Scenario scenario) {
//close the browser
if (scenario.isFailed()) { //take Screenshot
System.out.println(scenario.getName());
}
Instance.close();
}
}
And my Step-definition file:
public class MyStepdefs {
public static String Url = "https://ebay.com/staging/";
LoginPage loginPage = new LoginPage();
#Given("^I login to Ebay as \"([^\"]*)\"$")
public void iLoginToEbayAs(String username) throws Throwable {
Driver.Instance.navigate().to(Url);
loginPage.setUserName().sendKeys(username);
loginPage.setPassword().sendKeys("seeeev");
}
Receiving this error:
java.lang.NullPointerException
at Steps.MyStepdefs.iLoginToEbayAs(MyStepdefs.java:4)
MyStepdefs.java:4 == Driver.Instance.navigate().to(Url);
Help me pass through this!

Your Driver class never gets initialized, I'm betting Instance is null. I think you have at least 2 options, possibly more ways but this is what i'm thinking.
Instead of using #Before, which never gets executed because you don't have any test methods in that class, just make that a static "Init" method that you call in order to initialize your Instance variable
Make your Driver class an abstract class that your MyStepDefs class extends from. When you run your method iLoginToEbayAs() it will by default call the #Before method in the parent class and initialize your Instance variable as you expected.
Currently if you set a breakpoint in your #Before method I'm betting it's never getting executed hence NPE.

You are missing the argument in the step definition. it should be given below.
#Given("^I login to Ebay as \"([^\"]*)\"$")
public void iLoginToEbayAs(String role) throws Throwable {
Driver.Instance.navigate().to(Url);
}
have you imported the driver class?

Related

How to run tests without closing webdriver using PO?

Please help me with my Selenium project.
Link for GIT repository: https://kodov#bitbucket.org/kodov/addressbook5.git
I have an application Addressbook ( https://sourceforge.net/projects/php-addressbook/ ) which I want to test.
I made several tests for Login page and page for creating a new contact.
The case is to make:
Negative test for login
Positive test for login
Then I don't need to close the browser but to run tests for creating a contact.
The problem is that I made POM and my tests and pages are in different classes, so I don't know how to quit the
Webdriver just after all tests, but not after the first one.
Maybe I need to change annotations.
You can create a Base Test class and make the other tests class extend that class.
For example:
public class BaseTest {
public static WebDriver driver;
private static boolean isTestsStarted;
public static WebDriverWait wait;
#BeforeClass
public static void setup() {
// To run setup method before all tests that extends this base class
if(!isTestsStarted) {
System.setProperty("webdriver.chrome.driver", ConfProperties.getProperty("chromedriver_path"));
driver = new ChromeDriver();
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
driver.get(ConfProperties.getProperty("base_url"));
isTestsStarted = true;
}
}
// To quit driver after all tests run
// This will run only once, after all tests ran
// Another advantage of this is, it will quit driver even though you stop the program manually
static {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
driver.quit();
}));
}
}
Then extend this base class in your test classes
for your loginTest class
public class LoginTest extends BaseTest {
public static LoginPage loginPage;
public static MainPage mainPage;
#BeforeClass
public static void setup() {
// You can call driver object since you initialized it in your parent class
loginPage = new LoginPage(driver);
mainPage = new MainPage(driver);
driver.get(ConfProperties.getProperty("base_url"));
}
#Test
public void testUserCanNotLoginWithInvalidCredentials() {
loginPage.clearUsernameField().clearPasswordField()
.enterUsername(ConfProperties.getProperty("invalid_username"))
.enterPassword(ConfProperties.getProperty("invalid_password"))
.clickLoginButton();
assertThat(loginPage.getLoginButton().isDisplayed()).isTrue();
}
#Test
public void testUserCanLoginWithValidCredentials() {
loginPage.clearUsernameField().clearPasswordField()
.enterUsername(ConfProperties.getProperty("valid_username"))
.enterPassword(ConfProperties.getProperty("valid_password"))
.clickLoginButton();
assertThat(mainPage.getUserName())
.isEqualTo(ConfProperties.getProperty("valid_username"));
}
}
With the same way, you can use your driver object in other classes if you make those classes extend BaseTest class
You need to login no matter what, so you have to include the login part in both of your tests.
You can also try #Test(dependsOnMethods = { "testName" }) but I am not sure not if this works when your test is in another file.

Unable to call method which performing mouse actions to TestNG test case using selenium Java

Main Block:
public class test3 extends utility {
public WebDriver driver;
#BeforeTest
public void invokeBrowser() throws IOException {
driver = base();
driver.get(resource.getProperty("url"));
}
#Test
public class thirdPage {
public void main() {
actionTest test3 = new actionTest();
test3.executeTest();
}
}
}
Code performing mouse Actions:
public class actionTest {
public void executeTest() {
Actions execute = new Actions();
execute.moveToElement(driver.findElement(By.id("header-search-input"))).click().keyDown(Keys.SHIFT).sendKeys("Cricket").build().perform();
driver.findElement(By.id("header-desktop-search-button")).click();
}
}
Above code results in "NullPointerException" stating driver = null while executing block test3.executeTest();
Restructuring your codebase might help you to fix this issue. Create a base test class. Add the code related to web driver initialization and other main things there. Then create another class for your tests. Inherit it from the base test class. Then you can use the initialized driver in your all test classes.

TestWatcher with Selenium

I have implemented TestWatcher to do certain things based on test output, however the function that i need to call which is createScreenShot in testFailed needs a driver as incoming property, sadly driver is protected and not static since all my tests running at the same time.
Trying to achieve: to have a screenshot of each failed test.
What have i tried: I tried adding an additional instance property to the class and pass it to the constructor but i get a failure with the following exception
TestResultLoggerExtension.<init>()
java.lang.NoSuchMethodException: com.opngo.nowos.utils.TestResultLoggerExtension.<init>()
WebSettings
#ExtendWith(TestResultLoggerExtension.class)
public class WebDriverSettings {
protected WebDriver driver;
protected String TARGET_URL;
#BeforeEach
public void setUp() {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver(new ChromeOptions()
.addArguments("--headless")
.addArguments("window-size=1920x1480"));
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
loginToEnvironment();
}
public class TestResultLoggerExtension implements TestWatcher, AfterAllCallback {
#Override
public void testFailed(ExtensionContext context, Throwable cause) {
ScreenShotCreator.takeScreenShot(); <- driver needs to get here somehow since on any failed test i need to snap a screenshot
}
You can use ExtensionContext and Reflection to retrieve the WebDriver instance in your TestWatcher:
Object test = extensionContext.getRequiredTestInstance();
Field field = test.getClass().getDeclaredField("driver");
field.setAccessible(true);
WebDriver driver = (WebDriver) field.get(test);
If the WebDriver is not declared in the test class but inherited, use e.g. test.getClass().getSuperclass() or loop through all superclasses.
The methods in TestWatcher get invoked after the methods with #AfterAll/Each annotations. If you quit your WebDriver there, move it to your TestWatcher.

TestNG Parallel execution always fails when i run more than one testcase, Among all only one testscript was passing

I am using Testng for parallel execution of my web testcase. Totally i am having 5 classes.
BaseClass - for initializing and closing of my browser
Core class - Mediator for all drivers initialized
Reusable methods - Click, settext, gettext... [extends Step #2 Core class, so driver comes from there only]
Page Object Class - To store all locators like name,ID,xpath.Uses all those reusable methods like click, gettext,settext.
Main Test Class.
Base Class
public class TestNGBase {
ThreadLocal<WebDriver> localdriver = new ThreadLocal<>();
#BeforeMethod
public void initialize(){
System.setProperty("webdriver.chrome.driver","C:\\SeleniumTest\\chromedriver.exe");
localdriver.set(new ChromeDriver());
}
public WebDriver driver(){
Core.setDriver(localdriver.get());
return localdriver.get();
}
#AfterMethod
public void teardown(){
localdriver.get().close();
localdriver.remove();
}
}
Core Class:
public class Core {
protected static WebDriver driver;
public static void setDriver(WebDriver driverr) {
driver = driverr;
}
}
Reusable Class:
public class WebMethods extends Core {
public WebMethods() {
}
public static void Click(By by) {
driver.findElement(by).click();
}
PageObject Class
public class pagemethods(){
By login = By.name("login");
public void login(){
WebMethods.click(login);}
}
MainTestclass1 : Will use above Pageobject
MainTestclass2 : Will use above Pageobject
MainTestclass3 : Will use above Pageobject
So in above 3 testcase when i trigger all those using testng.xml file. 3 new browser gets initialized and it successfully opens the url. But when i start using the all those reusable methods such as click(). Out of 3 Testcase, any of the two testcase is always getting failed.
I think problem starts Core class as it receives all drivers at the same time. It's collapsing something.
Can some one help me to solve this parallel execution failure problem.
Thanks
Try to not make the main class static. Create a class that makes an instance of the class and then executes. When you make a static class, the method is hanging off of that class, not an instance.
E.g.
public WebDriver
{
WebDriver myWebDriver = new WebDriver();
myWebDriver.whateverMethod();
}
When using threads avoid static. Try that first.

How to call Selenium to another class : NullPointerException

How can we cal an object selenium to the other file which has half code of selenium.
In PHP i can by following code.
login($this); ----> login($sel){ ..... }
Can i do the same in Java as my selenium setup is in one file and the function which uses it is in another file can we pass the selenium to other as I am getting the NullPointerException.
Let me know if you want more details related to this.
Update
Library.java
public class Library extends SeleneseTestCase {
public int Login() throws Exception {
if (selenium.isElementPresent("companyID")) {
selenium.type("companyID", "COMP");
selenium.click("submit_logon");
selenium.waitForPageToLoad("80000");
}
}
}
Login.java
public class Login extends Library {
#Before
public void setUp() throws Exception {
selenium = new DefaultSelenium("localhost", 4444, "*chrome", "https://businessbanking.com/");
selenium.start();
}
public void testAllTests() throws Exception {
Library obj1 = new Library();
obj1.Login();
}
}
As per my observation selenium instance started on login file is not addressed to Library. I tried to pass "selenium" as parameter but failed, in Library i tried "super.setUp()" it also failed.
Thanks.
Replace:
public void testAllTests() throws Exception {
Library obj1 = new Library();
obj1.Login();
}
With:
public void testAllTests() throws Exception {
super.Login();
}
Since your Login class already extends Library it already has the Login() method present in it. What you are currently doing is creating a new Library object which does not run the #Before and hence the Selenium field is not initialised (in the new object).
When a subclass extends a base class it will inherit its methods. This is a fundamental Java and OOP concept.

Categories