In your code, I think you have mixed two approaches together.
- Using Base Class
- Without Using Base Class
In Approach 1:
You don't have to assign a driver to a local variable if you are using a base class
Avoid:
public class LoginTest extends BaseTest{
public WebDriver driver;
public LoginTest(){
this.driver = BaseTest.driver
}
instead use
public class LoginTest extends BaseTest{
public LoginTest(){
driver.get(url);
}
you can use the driver variable directly as it is inherited, don't assign it to a local variable. Else page object won't work properly.
The second Approach
Here avoid base class and pass driver instance to each page object class.
public class LoginTest{
private WebDriver driver;
public LoginTest(WebDriver driver){
this.driver = driver
}
And in Test
new LoginTest(driver)
Important:
Note that in Java everything is passed as a value but as a variable that points to a class object, will have the reference to the memory location of that object as its value, so objects will behave as they are passed as reference:
So in,
public class LoginTest{
private WebDriver driver;
public LoginTest(WebDriver driver){
this.driver = driver
}
Whatever changes you make to this.driver or the actual driver in you test suite, will affect vice versa.
So using Base class will make it cleaner and makes novice users know that we are using the same driver instance and doesn't cause errors by mistakenly thinking changing something in the driver in the page object class doesn't affect anything else.
Consider below setup:
public class LoginTest extends BaseTest{
public WebDriver driver;
public LoginTest(){
this.driver = BaseTest.driver
BaseTest.driver.get("https://www.google.com");
System.out.println( BaseTest.driver.getTitle());
System.out.println( this.driver.getTitle());
}
Now if you call LoginTest() you can see the code works fine and prints google as the title as the object is passed as a reference.
Now coming to your questions
Why the driver instance is static?
The driver instance need not be static unless you are accessing it as a class variable from a non-subclass
eg: TestBaseClass.driver
If you declare driver as static then you can access it from any class as a class variable of TestBaseClass.
But if you are extending all classes using TestBaseClass then driver variable will be available by default to child classes so you don't need it to be static but public.
You cannot use it as "Protected" or "Default" as it won't be available from a different package.
Also, if I use the "BaseTest" driver instance in all PageObject
Classes, then does it mean, that the same Chromedriver session is
active throughout the test?
Yes, you are using the same chrome driver instance throughout unless you create a new instance
eg: if you declare a driver variable in test base class as public, and inherited the base class and then initialize it from sub class as
driver = new ChromeDriver();
Then the driver variable will have the same chrome driver instance session where ever you access it from.
If you initialize and quit driver in @AfterTest and @BeforeTest then each test will have the same reference variable driver but different chrome driver instance.
Why do Test classes need to use one global driver instance everywhere.
Does this initializes webdriver session or properties etc. I am
confused.
We use this mainly for reporting, for instance in TestNG listeners if a test fails then in the test failure listener we can take the screenshot using the global driver variable that has the current webdriver state.
Else we have to explicitly pass the driver instance or call it statically as TestBase.driver.
What issues this could cause?
This works perfectly when you run the script in a single thread, but in parallel execution, this could cause issues so you have to make driver variable thread-safe.