Inheritence and #BeforeSuite in TestNG - java

I have been working on TestNG and there was a problem associated with some of my code. Here's the code:
public class Main {
public String baseurl ;
public WebDriver webdriver ;
protected Main(){
//baseurl = "http://goodreads.com";
//webdriver = new FirefoxDriver();
}
#BeforeSuite
public void setup(){
baseurl = "http://goodreads.com";
webdriver = new FirefoxDriver();
}
Above code is of the base class
#Test
public void do_login(){
super.webdriver.get(super.baseurl);
This is of inherited class
Now as far as I know the BeforeSuite should executed first and the values of baseurl and webdriver should get initialized to the specified values. But I'm getting a NullPointerException in the above code. The problem is resolved when I assign the variables as static or if I initialize the variables in the constructor. But why are they not being initialized when I put them in the method(which is supposed to execute before the #Test executes anyway)? Is there some concept about java that I'm missing? Please explain

You don't need to include both classes to the suite. Only #Test containing class should be included. I think that's the problem. I also believe that #BeforeSuite annotated method will be executed not depending on the way you run your tests (as TestNG method or TestNG suite), since default suite will be created in order to run tests anyway.

Related

How does dependency injection work in Cucumber?

I have been trying to inject webdriver into the steps. I have used this instructions and it works well.
The idea is to inject WebDriver into steps classes as a service. At the initial step, you need to add the following dependency.
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-spring</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
There are three main classes which are involved in the dependency injection. Here we introduce them one by one.
BaseUtil
BaseUtil is the class which has an attribute for WebDriverof Selenium. The class is quite simple:
public class BaseUtil {
private WebDriver driver;
public WebDriver getDriver() {return driver;}
public void setDriver(WebDriver driver) { this.driver = driver;}
}
Hook
The Hook class contains #Before, #After. The method testInitialier() is responsible to load the the webDriver file and create an instance, while the method testTearDown() is responsible for closing the browser.
public class Hook extends BaseUtil{
BaseUtil base;
#Before
public void testInitializer(){
File file = new
File(IgniteTaskApplication.class.getClassLoader().getResource("driver/chromedriver.exe").getFile());
String driverPath=file.getAbsolutePath();
System.out.println("Webdriver is in path: "+driverPath);
System.setProperty("webdriver.chrome.driver",driverPath);
base.setDriver(new ChromeDriver());
}
public Hook(BaseUtil base) {
this.base = base;
}
#After
public void tearDownTest(){
base.getDriver().close();
}
}
Steps
And the steps class contains the steps which came from compiled features file. To compile the feature file in Eclipse you need to have Eclipse-Cucumber plugin installed in your Eclipse.
public class ClickButton_Steps extends BaseUtil{
BaseUtil base;
public ClickButton_Steps(BaseUtil base){
super();
this.base=base;
}
#When("^I clcik on the button$")
public void i_clcik_on_the_button() throws Throwable {
cb=new ClickButtonPage(base.getDriver());
cb.navigator();
}
// The other steps ...
}
How do i run it?
Open the feature file -> Run as -> Run with Junit
Question
I am wondering what is the order of running methods in a way which it leads to dependency injection?
I guess the order is as following:
Junit calls #Before method which is testInitializer()
The testInitializer()is in Hook class so it needs to make an instance of Hook class.
It leads to call the constuctor of the Hook class.
But, i cannot understand the rest of the steps. Maybe even it does not true at all. I mean, I have a functional code but i cannot explain how it works?
As I understand you correctly you use JUnit as a test framework with cucumber-spring. JUnit provides the following lifecycle.
When you annotate the method with annotation #Before that it will call this method before each test that you have.
As for #After could be used for cleaning resources and call after each test.
Your test flow when you run the test:
testInitializer
i_clcik_on_the_button
tearDownTest
In addition, you could use logging (slf4j) instead of System.out.println and it will be easier to track test flow.

Running a java script with a java program

I have a selenium script written in java with the following structure
Script.java
#before
-----Some methods------
#Test
-----Some methods------
#after
-----Some methods------
and i have a main java program with structure
Main.java
public static void main(String args[]) throws IOException {
//Here i have to write the logic to run the above script
}
in which i have a main method i have to run the above mentioned script from this java program, how it can be done. as i am a newbie for java so any suggestions are welcome.
If you are using unit test framework like JUnit or TestNg Then the methods mentioned under annotations like #Test ,#Before and so on are independent itself. Their execution order is as per preferance in that framework itself. Main method not required here.
So in your case if you have done code using these methods using any TestNG or JUnit then have to use like following -
class Myclass
{
#Before
public void methodA()
{
// Your code
}
#Test
public void methodB()
{
// your code
}
#After
public void methodC
{
// your code
}
}
And Run your class like Run As > TestNG Test if you are using TestNG framework
Annotations in java needs a package like junit ,testNg or cucumber - jvm where
#Test ,#Before ,#After
could find a way to be run.So you cannot find an answer in java to run them as these annotations are not part of Java.
I think only way to run testNG based script is to create a suite of testNG.xml file and do the execution of suite in main class.Try this code
List<String> suitesList = new ArrayList<String>();
TestListener listener = new TestListener();
TestNG testng = new TestNG();
testng.setOutputDirectory("outputfoldername");
suitesList.add("testng.xml");
testng.setTestSuites(suitesList);
testng.addListener(listener);
testng.run();

Configuration file to run JUnit Suite on different browsers in BrowserStack

Could you please look at my problem and give any advice to its solving.
I use JUnit4 and selenium 2 WebDriver.
So, I have class to run JUnit suite:
#RunWith(Suite.class)
#Suite.SuiteClasses({className1.class, clasName2.class})
public class TestSuite
{
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new JUnit4TestAdapter(className1.class));
suite.addTest(new JUnit4TestAdapter(className2.class));
return suite;
}
}
each class contains #Test method and extends BaseClass that sets in #BeforeClass parameters (through DesiredCapabilities) to run suite on BrowserStack machines:
public class MyTestBase{
static protected WebDriver driver;
private boolean acceptNextAlert = true;
protected static StringBuffer verificationErrors = new StringBuffer();
#BeforeClass
public static void setUp() throws Exception {
DesiredCapabilities capability = DesiredCapabilities.firefox();
capability.setPlatform(Platform.WINDOWS);
capability.setCapability("build", "JUnit - Sample");
capability.setCapability("acceptSslCerts", "true");
capability.setCapability("browserstack.debug", "true");
driver = new RemoteWebDriver(
new URL("http://username:accesskey#hub.browserstack.com/wd/hub"),
capability);
driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
}
/* other code */
}
So, could you please help me with the next:
1) I need to create configuration file and use its parameters to run my TestSuite on different browsers in BrowserStack. Any examples of .xml file to do it will be appreciated.
2) And also how do I need to modify my TestSuite.class to use .xml file parameters.
3) My TestSuite.class consists of many .class with #Test method in each. Each class extends MyTestBase.class where annotations #BeforeClass and #AfterClass are located, but when I run TestSuite new browser has been launched for each class in TestSuite and it's a very big problem for me. What can I do for running browser once for all #Test methods across all classes in TestSuite. I know that #BeforeClass works for all #Test methods inside one class, but what should be done if there are may classes? In TestNG there is #BeforeSuite solves this problem.
Sorry, for so many questions, but I've tried a lot and didn't succeed in this :(
Thanks a lot!
You asked a lot of questions concerning different topics. I will try to sort things out.
Reusing a browser and not opening a new one for every test class
This can only be achieved if you instantiate your WebDriver once and use that object in all your tests. So don't instantiate your browser in the #BeforeClass method of your tests.
How do you initialise your WebDriver?
In the very first test class of your test suite. That might be a dedicated test just for opening the browser. Or you could include this functionality in all of your test and have to check, if the browser had already been initialised or not.
How to reuse a WebDriver object and share it between test classes?
I'd propose to create a Singleton that stores a WebDriver object. This way all tests can access it. However, it takes some more effort to make this thread-safe - in case your run your tests in parallel.
Running your tests with different browsers
You should make your tests #Parameterized and expect a set of WebDriver objects as parameters to execute.
Combining both: Different browsers and reusing browsers between tests
This will likely lead to a point where you would like to define parameters for your test suite. However, in standard JUnit 4 you can't do this.
I recommend to use the ParameterizedSuite runner from this library.

Best Way to Reset Browser State in TestNG with Selenium and Java

Can someone recommend the best way to 'tearDown' in the #AfterClass with testng? I occasionally get a hung window or popup and can't get back to the homepage to logout gracefully for the next class to start and avoid modal dialog errors.
I've tried getting a window handle on the homepage, then one on the popup, then putting a switchTo in my #AfterClass but it doesn't work. I've also tried driver.close(). But then my next class will be skipped with an unreachable browser error.
I really need a good tearDown #AfterClass method that can get out of whatever errors and popups are on page, and just leave a clean browser window at login page for the next test class to run.
Edit: Adding Code:
package TestPackage;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.*;
import org.testng.annotations.Test;
//#Test (priority = 1)
public class test1 {
public static WebDriver driver = new FirefoxDriver();
Environment environment = Environment.QA03();
User testUser = User.ns_system();
AxUtilities axUtilities;
#BeforeClass
#Parameters("environment")
#Test
public void login(String environment1){
// environment = new Environment(environment1);
axUtilities = new DAxUtilities(environment1, driver);
// DAxUtilities dAxUtilities = new DAxUtilities(environment);
Login login = new Login();
login.getLogin(testUser, axUtilities, driver);
axUtilities.sleep(5000);
}
#Test
public void testNothing(){
String s = "public void testNothing() reached...";
System.out.println(s);
}
#AfterClass
public void verifyOKAndLogout() {
driver.quit();
// DAxUtilities dAxUtilities;
}
}
test class 1 and 2 are the same except for the class name...
And the tests are run from xml file. And I've tried many variants of the xml file, even putting each test in its own xml file:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="TestSuite1" verbose="1">
<parameter name="environment" value="QA03"/>
<test name="Test1">
<classes>
<class name="TestPackage.test1"/>
<!--<class name="TestPackage.test2"/>-->
</classes>
</test>
<test name="Test2">
<classes>
<class name="TestPackage.test2"/>
</classes>
</test>
</suite>
But always two web drivers get created, one right after the other, at the very beginning of the test run, before any other code is executed. And breakpoints show the code is definitely skipping from the beginning of class 1, to the beginning of class 2, before running class 1 tests...
From what you wrote it seems that you are creating browser (instantiating WebDriver) before entire test suite and then execute all the tests using the same browser instance. Although it results with faster execution time it also introduces problems like the one you are having right now.
I would suggest creating a new instance of the browser before executing each test class (or even test method). In such case you can safely use driver.quit() in your #AfterClass method. Restarting browser every test will make your tests much more stable.
EDIT comments on your newly added code
the way you are instantiating WebDriver is not correct. If you have
several test classes you will end up with multiple browser windows
opened before any test is executed
you annotated one method with both #Test and #BeforeClass - this will cause the method to be executed twice in a row
The way it should (more or less) looks like is
public class MyTest {
protected WebDriver driver;
#BeforeClass //I would even suggest to use #BeforeMethod but that's up to you
public void setUp() {
driver = new FirefoxDriver();
//other instantiations and assignments if necessary
}
#Test
public void login() {
driver.get("http://watever.com");
//do whatever
}
#Test
public void someOtherTest() {
//do something else
}
#AfterClass //or #AfterMethod
public void tearDown() {
driver.quit();
}
}
I believe that calling driver.close() or driver.quit() and then creating a new WebDriver and assigning it to your driver should do the trick. You'd probably want to call the same function to create the driver at both the beginning and end of your class.
Use
#tearDown{
driver.quit();
}
It will close all the windows open by test class.
And in the Next class create new instance of Webdriver() as shown below
Webdriver driver = new FireFoxDriver(); //Or some other driver

#BeforeClass runs multiple times for the same class in eclipse

I am writing some junit tests in eclipse and I need to do some time consuming setup before the tests. Appeared that #BeforeClass should be the way to do this. I currently tested this on a class that has 2 #Test functions.
When I right click on a class in eclipse and chose "Run As" -> "JUnit Test" I can see that the #BeforeClass is executed before both functions.
I even tried to change #BeforeClass to #Before and stored in a boolean whether we had already executed this function, but it seems that eclipse created two class objects from the same class, one for each test to run so that did not help either.
So what should I do to have a setup function run only one time even if I have many tests ? Or am I just using eclipse incorrectly when trying to run the tests ?
The setup is something like this:
public class SuperClass {
#BeforeClass
public void { // do timeconsuming setup }
}
public class TestClass extends SuperClass {
#Test
public void test1() { // perform first test }
#Test
public void test2() { // perform second test }
}
Making static the method annotated with BeforeClass may be the solution:
#BeforeClass
public static void
#BeforeClass methods should be static in order to be executed only once.

Categories

Resources