TestNG: All subsequent Test classes are skipped when #BeforeClass method fails? - java

My setup:
A TestBase class containing a #BeforeClass method
Several Test classes extending from TestBase class and also containing a #BeforeClass method
testNG 6.8.8
Why this setup?:
I need the #BeforeClass in the TestBase class to provide setup that all testclasses will need and I don't want to repeat in every Test class. For example thread-id-dependent login credentials.
TestBase class also instantiates the Selenium WebDriver
I need the #BeforeClass in the Test classes to initialize everything that all #Test methods will need to use but that only needs to (or must) be built/invoked once for all tests. This includes calls to said WebDriver instance (that's why a "normal" constructor doesn't work here)
Here's what happens:
When I run the tests via a testNG xml file and there is an exception within the #BeforeClass method of one of the Test classes, then all subsequent Test classes are skipped by TestNG.
Why does this happen? How to prevent it?
When I change the annotation in the TestBase class to #BeforeSuite for example, then all tests are run, even if there is an exception in on of the #BeforeClass methods.
Example:
When you run the xml file, complete RunAllTestClasses02 class is skipped.
testNG xml file:
<?xml version="1.0" encoding="UTF-8"?>
<suite name = "MiscSuite">
<test name = "MiscTest">
<classes >
<class name="drkthng.misc.RunAllTestClasses01" />
<class name="drkthng.misc.RunAllTestClasses02" />
</classes>
</test>
</suite>
TestBase class with a #BeforeClass method:
public abstract class RunAllTestClassesBase {
#BeforeClass
public void beforeClass() {
// do something that all Test classes will need
}
}
Test class that throws Exception within #BeforeClass method:
public class RunAllTestClasses01 extends RunAllTestClassesBase {
#BeforeClass
public void beforeClass() {
Assert.assertTrue(false);
}
#Test
public void Test01() {
Assert.assertTrue(true);
}
}

This was a bug in Testng. solved in 6.9.5. Please upgrade.

Try to add #AfterClass(alwaysrun = true) or/and #AfterMethod(alwaysrun=true) as by default they are skipped if either BeforeClass or BeforeMethod are not completed.
The documentation on testNG Configuration Failures, Policy, and alwaysRun explains whether/when configuration failures cause listener methods (alwaysRun and other listeners) to be skipped, failure policies and best practices.

Related

How can I Run 2 Tests Using XML Runner at the same WebDriver?

I'm using Selenium with Java WebDriver and with test Runner Suit(XML), I have 2 tests to run.
I have put a setup method in each Test class and it was OK - the tests was working well (each test with its browser window).
Then I decided to move the setup method to the configuration class. This class is extended by each test class, and this creates a problem that the second test run overrides the first by using the same browser.
Setup class method code:
public class Configrations_And_ScreenShotsFunc_POM {
protected WebDriver driver;
public void setup()
{
System.setProperty("webdriver.edge.driver","C:\\Program Files (x86)\\Microsoft Web Driver\\MicrosoftWebDriver.exe");
driver = new EdgeDriver();
driver.get(URL);
}
Test 1 class Code:
public class TestCase1_POM extends Configrations_And_ScreenShotsFunc_POM {
#BeforeTest
public void Begain() throws InterruptedException
{
setup(); //Setup Browser
}
Test 2 class Code:
public class TestCase2_POM extends Configrations_And_ScreenShotsFunc_POM {
#BeforeTest
public void Begain() throws InterruptedException
{
setup(); //Setup Browser
}
Runner.Xml:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestSuite" thread-count="2" parallel="tests">
<test name="TestCase1">
<parameter name="browser" value="Edge" />
<classes>
<class name="POM.Tests.TestCa se1_POM"></class>
</classes>
</test>
<test name="TestCase2_POM">
<parameter name="browser" value="Edge" />
<classes>
<class name="POM.Tests.TestCase2_POM"></class>
</classes>
</test>
</suite>
Comment: The 2 tests files are in a folder, and the configurations class in another folder.
How can it be solved?
Use #BeforeTest annotation on your setup() method instead of your current Begin() and remove your Begin().
The annotation #BeforeTest is intended to be invoked only once per <test> tag in your suite.xml file. Resorting to browser instantiations in a #BeforeTest method which is available in a base class from which all test classes extend has the below disadvantage :
Depending on how the WebDriver instance is being saved (either as a static data member or as an instance variable), test methods can either end up using the same WebDriver instance (in the case of static data members) (or) end up getting NullPointerException (in the case of instance data members)
You can consider moving the browser instantiation into a much more granular level such as :
#BeforeClass (here also the drawback is there that if there are more than one #Test annotated test methods in your class which all use the WebDriver instance initialized by your #BeforeClass, then during parallel execution you will end up having race conditions amongst your test methods ) or into a
#BeforeMethod annotated method.
I had created a blog post that shows you how to do parallel executions with TestNG without using any of these configuration annotations, inheritance etc., Please see if it helps you.
Blog link : https://rationaleemotions.wordpress.com/2013/07/31/parallel-webdriver-executions-using-testng/

Junit set up once for whole integration tests(all test classes)

I have some own components, which I start before my Java application. It takes about 30 seconds to start this. In my integration tests, I start my components before the class and all test cases run. My question is, is it possible to run my components not before the test class, but rather before the whole test?
kind regards,
bilal
If you use JUnit suites you can use a #BeforeClass to execute a method before the entire suite runs and an #AfterClass after the entire suite runs:
#RunWith(Suite.class)
#SuiteClasses(
{
//list your test classes here
}
)
public class IntegrationSuite{
#BeforeClass
public static void setupSuite(){
//do your initialization here
}
#AfterClass
public static void tearDownSuite(){
//...if needed
}
}
Use the #BeforeClass annotation.
Please note that the annotated method has to be static.
#BeforeClass
public static void oneTimeInit() {
System.out.println("It runs only once for all tests in this class.");
}
If you are using maven you could use the maven-failsafe-plugin. It has a pre-integration-test goal intended for test setup. For an example take a look at Maven Failsafe Plugin: how to use the pre- and post-integration-test phases

Share object reference between different JUnit tests

I have a couple of JUnit tests which need a reference for a expensive resource (a WALA class hierachie), which needs about 30s to be created. I would like to share this reference in my whole test suite.
I thought about a static member in a base class which is laziely initiated with a #BeforeClass method. After test is run the JVM should be determined anyway.
Is there any other way to accomplish this? Or any other best practice?
Create an explicit test suite (cf. this answer) to run these tests, and use #BeforeClass and #AfterClass on the suite itself (cf. this answer):
#RunWith(Suite.class)
#Suite.SuiteClasses({Test1.class, Test2.class})
public class MySuite {
#BeforeClass
public static void initResource() {
MyExpensiveResource.init();
}
#AfterClass
public static void disposeResource() {
MyExpensiveResource.dispose();
}
}

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