I have a JUnit Framework with the following annotations #before, #test, #After.
However when I run through my tests the #After Annotation is never initialised and therefore the browser doesn't close.
I've run my tests using JUnit and they all pass but the tear down step never works.
I decided to try see if any of the annotations worked, so I removed the #before and #test and the test still run and passed which suggests to me that they are not being used at all.
This is my Selenium set up:
public SeleniumSetup() {
}
#Before
public void prepareBrowserForSelenium() throws Exception {
// setup();
if(DriverSingleton.getDriver() == null)
{
setup();
}
else
{
driver = DriverSingleton.getDriver();
}
}
public void setup() throws Exception {
System.setProperty("webdriver.chrome.driver", "C:\\Users\\antho\\Automation\\WebAutomation\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://www.ultimateqa.com");
driver.manage().window().maximize();
DuringTest();
}
#Test
public void DuringTest() throws Exception{
System.out.println("test has started");
assertEquals(true, driver.getPageSource().contains("Learn Critical Automation and Dev Skills"));
System.out.println("Learn Critical Automation and Dev Skills copy has been verified");
driver.findElement(By.linkText("Automation Exercises")).click();
assertEquals(true, driver.getPageSource().contains("Automation Practice"));
System.out.println("Automation Practice copy has been verified");
driver.findElement(By.linkText("Big page with many elements")).click();
}
#After
public static void tearDown() throws Exception {
driver.close();
}
This is my DriverSingleton;
private static WebDriver driver;
public DriverSingleton () {
}
public static WebDriver getDriver() {
return driver;
}
public static void setDriver (WebDriver driver) {
DriverSingleton.driver = driver;
}
}
After my tests have run I expect the browser to close down.
I have added DuringTest(); to my #Before class, which I suspect is the only reason the #Test class is getting called, without that this the #Test doesn't work.
First you shall not invoke #Test inside your setup method by calling DuringTest(). JUnit framework would take care of Test Method by looking #Test annotations. So you do not need to call it explicitly.
Make both #Before & #After method as non static.
If you were running a test with this code you should have seen an exception with the following message being thrown by JUnit:
Method tearDown() should not be static
Method annotated with JUnit test annotations should always be non-static and located inside dedicated classes used exclusively for running tests. Use the following code as a base to further build your test class:
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class SeleniumTest {
#Before
public void prepareBrowserForSelenium() throws Exception {
System.out.println("Running method annotated with #Before");
}
#Test
public void DuringTest() throws Exception {
System.out.println("Running main test method");
}
#After
public static void tearDown() throws Exception {
System.out.println("Running method annotated with #After");
}
}
Console output:
Running method annotated with #Before
Running main test method
Running method annotated with #After
As you see everything work just fine. I would suggest reading more about JUnit testing in general and here is a good place to start:
https://github.com/junit-team/junit4/wiki/Getting-started
Related
I recently switched to using ThreadLocal in my test suite, and while it has worked great for parallel tests, it has now broken non-parallel tests.
I have #BeforeClass/#BeforeMethod methods that handle creating a new instance of WebDriver based on the test class's driver instance policy. However, when they are creating a new instance of WebDriver it is tied to the thread of "Test Worker" which is only used in configuration methods, like #BeforeClass and #BeforeMethod. This doesn't happen when running with parallelization enabled. Here's a very simplified example:
public class DriverWrapper () {
private static ThreadLocal<WebDriver> driver = new ThreadLocal<>();
public DriverWrapper() {}
public void newInstance(){
driver.set(new ChromeDriver());
}
public WebDriver getDriverInstance(){
return driver.get();
}
}
abstract public class AbstractTest {
DriverPolicy policy;
DriverWrapper driver;
public AbstractTest(DriverPolicy policy){
this.policy = policy;
}
#BeforeClass
public void setUpClass() {
if (policy == DriverPolicy.NEW_INSTANCE_PER_CLASS) {
driver = new DriverWrapper();
driver.newInstance();
}
}
#BeforeMethod
public void setUp() {
if (policy == DriverPolicy.NEW_INSTANCE_PER_METHOD) {
driver = new DriverWrapper();
driver.newInstance();
}
}
}
public class SomeTest {
public SomeTest() {
super(DriverPolicy.NEW_INSTANCE_PER_CLASS);
}
#Test
public void doSomeThings() {
SomePageFactoryClass somePageFactoryClass = new SomePageFactoryClass(driver.getDriverInstance());
// it does some pagefactory stuff
somePageFactoryClass.login();
// login() tries to do some WebDrivery stuff
// It's here that I hit the NPE because the thread ID that got assigned to the WebDriver in
// DriverWrapper is different from the thread ID in #Test, so it's just null.
}
}
My testng.xml that runs these tests only encounters this issue when parallel is disabled. As soon as I enable parallel, #BeforeClass and #BeforeMethod methods are running on the same thread as their class's #Test methods.
I've come up with a messy work around where I'm just creating the new instances of DriverWrapper in each individual #Test method, but it feels wasteful when I have the code already sitting in AbstractTest.
Is there something obvious I'm missing? Maybe I should just not use ThreadLocal for non-parallel tests?
My #Before and #After methods are not picking up by Junit
public class TestSetup {
#Before
public void browserSetUp() {
// code for before a test
}
#After
public void tearDown() {
// code after a test
}
}
In Another class file I have defined
public class Steps{
#Step
public void step1() {
//Code for step 1
}
#Step
public void step2() {
// Code for Step 2
}
}
Finally I am calling those steps for my Test
public class Tests {
Steps step = new Steps();
#Test
public void TC_0001 {
step.step1();
step.step2();
}
}
#Test method are getting executed but the #Before and #After methods are not executing before #Test method.Do I have to include the TestSetup class to somewhere ? Any help will be appreciated.
**Thought 1: As I am using Maven to build, my #Before #After methods resides in a class (TestSetup.java - Name is not ending with *Test.java and may be thats why Maven is not picking it up for execution?
#Before and #After are used in the same class that your test is running. You should put this methods on your test class:
public class Tests {
Steps step = new Steps();
#Test
public void TC_0001 {
step.step1();
step.step2();
}
#Before
public void browserSetUp() {
// code for before a test
}
#After
public void tearDown() {
// code after a test
}
}
#Before and #After are only executed before a single test, if they are defined in the same class as the #Test. In your case, the TestSetup class contains no tests. So either you let Test inherit from TestSetup or you create a rule that is executed "around" your test.
I am starting to use selenium webdriver with TestNG. I have created a multiple-test class which can run multiple tests, however, how do I call the other classes in each test block without copying the whole code over?
public WebDriver driver;
//Test 1
#Test(priority = 0) //Set Priority of Test - Priority of test always starts from Zero
public void one() {
System.out.println("This is Test Case 1");
}
//Test 2
#Test(priority = 1) // Test priority 1
public void Two(){
System.out.println("This is Test Case 2");
}
Would I need to create a function to call in each test block to run the other classes?
Use the setUp() method as described here to instantiate that class and keep it as an attribute.
The method setUp() will be invoked after the test class has been built
and before any test method is run.
import org.testng.annotations.*;
public class MyTest {
private MyService myService;
#BeforeClass
public void setUp() {
myService = new MyService();
}
#Test
public void testSomething() {
myService.doSomething();
}
}
I have few JUnit Tests and I want to decide which one to use at runtime. I checked previous answers at SO and I ended up creating Test Suite dynamically.
This class is where my application starts. I have CustomTestSuite class and Main class adds Tests to my custom suite.
public class Main {
public static junit.framework.TestSuite suite()
{
CustomTestSuite suite = new CustomTestSuite();
suite.addTest(new JUnit4TestAdapter(BTest.class));
suite.addTest(new JUnit4TestAdapter(ATest.class));
return suite;
}
}
CustomTestSuite.java
public class CustomTestSuite extends TestSuite {
#BeforeClass
public static void setUp() throws Exception {
System.out.println("Before class test");
}
#After
public void tearDown() throws Exception {
System.out.println("After class test");
}
}
My ATest and BTest are simple Test classes, I will just show ATest as sample:
public class ATest{
#Test
public void testMethod() {
System.out.println("testMethod");
}
}
When I start running my project from Main class, it is expected to run the method with #BeforeClass first, do testing, and then run the method with #AfterClass annotation.
Tests are working fine but it skips setUp method and tearDown method. I tried #Before and #BeforeClass annotations both.
I am confused with suite structure. Any help would be appreciated.
Thanks
#Before and #BeforeClass are supposed to be used in Test class not in TestSuite. If need to have common setUp and tearDown for more than one Test class, then put those both methods in a super class and extend that super by ATest and BTest test classes. And also the Suite can be built and run simply with #RunWith and #SuiteClasses annotations and the CustomTestSuite class is not needed.
So the changes are as below.
The CustomTestSuite becomes TestSuper
public class TestSuper {
#BeforeClass
public static void setUp() throws Exception {
System.out.println("Before class test");
}
#After
public void tearDown() throws Exception {
System.out.println("After class test");
}
}
Now the ATest extends TestSuper
public class ATest extends TestSuper {
#Test
public void testMethod() {
System.out.println("testMethod");
}
}
Similarly BTest also should extend TestSuper.
Simply add #RunWith and #SuiteClasses annotations to Main class as below and run Main.
#RunWith(Suite.class)
#SuiteClasses({ATest.class, BTest.class})
public class Main {
}
Have a go with these changes.
I have a the following selenium test suite inheriting from the same base class, how to I have the tests use the same web driver instance when i run the entire test suite?. I also want to run each tests in isolation aswell. I believe this will cut down the time it takes to run the suite considerably.
This test is run from maven that in turn runs each test class.
#RunWith(Suite.class)
#SuiteClasses({
AdminPortalTestSuite.class,
DevPortalTestSuite.class,
CommonTestSuite.class
})
public class SeleniumTestSuite {
}
Baseclass all tests inherit from
#BeforeClass
public static void setUp() throws Exception {
if (null == baseUrl || !baseUrl.startsWith("https://")) {
baseUrl = "https://localhost:8443";
}
if (null == browser || browser.startsWith("${")) {
browser = "firefox";
}
//retrieve properties including locale.
retrieveProperties();
Thread.sleep(4000);
setUpDriver();
}
#After
public void tearDownAfterTest() {
openUrl(LIST_PARTNERS);
adminPortalLogout();
openUrl(DASHBOARD);
developerPortalLogout();
driver.manage().deleteAllCookies();
}
#AfterClass
public static void tearDown() throws Exception {
BaseFunctionalTestCase.driver.quit();
}
test example
public class APApplicationFunctionalTestCase extends BaseFunctionalTestCase {
/**
* Test validation when creating a new application.
*/
#Test
public void testApplicationValidation() {
Assume.assumeTrue(preHtml5);
final String partnerName = randomize("partner");
//create partner
createPartnerThroughAP(partnerName);
adminPortalLogin();
openUrl(ADD_APPLICATION + partnerName);
waitForId("applicationView.applicationName");
findById("submit-button").click();
waitForId("submit-button");
//check validation
assertTrue("Failed to validate application name",
isTextPresent(resolveAPMessage("partner", "application.messages",
"NotEmpty.applicationEditView.applicationView.applicationName")));
assertTrue("Failed to validate application username",
isTextPresent(resolveAPMessage("partner", "application.messages",
"NotEmpty.applicationEditView.applicationView.applicationUserName")));
assertTrue("Failed to validate application password",
isTextPresent(resolveAPMessage("partner", "application.messages",
"Password.applicationEditView.applicationView.applicationPassword")));
assertTrue("Failed to validate application password confirmation",
isTextPresent(resolveAPMessage("partner", "application.messages",
"Length.applicationEditView.applicationPasswordConfirmation")));
}
This is how I did it. In SeleniumTestSuite, I added a static WebDriver and instantiate it in a setUp() method annotated with #BeforeClass. Then, in the Base class that all of my selenium tests inherit from, I added a getDriver() method, that will try to get the static driver from SeleniumTestSuite. If that driver is null, then a new one gets instantiated and returned. Thus, when the selenium test classes are running via the suite, they will use the driver from SeleniumTestSuite, and when they are running individually, they will use their own driver.
SeleniumTestSuite:
#RunWith(Suite.class)
#SuiteClasses({
AbcSeleniumTest.class,
XyzSeleniumTest.class
})
public class SeleniumTestSuite {
private static WebDriver driver;
#BeforeClass
public static void setUp() {
driver = new FirefoxDriver();
}
//driver getter/setter
}
BaseSeleniumTest:
public abstract class BaseSeleniumTest {
public WebDriver getDriver() {
WebDriver driver = SeleniumTestSuite.getDriver();
if(driver != null) {
return driver;
}
return new FirefoxDriver();
}
}
AbcSeleniumTest:
public class AbcSeleniumTest extends BaseSeleniumTest {
#Test
public void testAbc() {
WebDriver driver = getDriver();
// test stuff
}
}
I'm not great with JUnit... looks like you're trying the solution suggested here:
Before and After Suite execution hook in jUnit 4.x
which would suggest you should move your #BeforeClass into your SeleniumTestSuite class.