I am writing tests in testNG. Each test method shares a number of common attributes stored at the class level but each test method needs its own independent driver, so the driver cannot be stored as a class variable. This allows each test method to be invoked multiple times with different drivers while running concurrently.
Basically my sudo-code of what I am trying to do would look something like the following:
#BeforeMethod
public void setup(Argument someArg) {
Driver driver = new Driver(argArg);
}
#Test
public void test() {
driver.dostuff();
}
#AfterMethod (alwaysrun = true)
public void teardown() {
driver.quit();
}
My thought is that I might store the drivers in a concurrent map collection using the classname and test method as a key for storing and retrieving the driver, but I would like to find a simpler, less verbose way of doing this.
I apologize if there is an answer that already addresses this. I searched high and low and couldn't find the solution I was looking for or couldn't make the connection to how a specific idea would apply to my problem. My case is specific to Selenium Webdriver, but I imagine that there are other cases that may want to do something like this.
How about using a ThreadLocal<Driver>?
Related
I have a maven Java project in Intellij IDEA community. The TestNg version is very old i.e. 6.9.5 and I simply cannot update it. I have 6 TestNg test methods in a class. Only 5/6 of these methods use data provider methods, all of which are in one DataProvider class.
When I run the test class, only the method without data provider (say test_5) runs successfully. The others are marked as "test ignored". Moreover, when I comment or disable test_5, then all the other tests run. Can I make testng give a detailed reason for ignoring tests ?
Here is brief information about my project. I can't give the full code.
public class MyUtilityClass {
public class MyUtilityClass(){
//Load data from property files and initialize members, do other stuff.
}
}
public class BaseTest {
MyUtilityClass utilObj = new MyUtilityClass();
//do something with utilObj, provide common annotated methods for tests etc.
}
public class TestClass extends BaseTest {
#BeforeClass
public void beforeMyClass(){
//Get some data from this.utilObj and do other things also.
}
#Test(dataProvider = "test_1", dataProviderClass = MyDataProvider.class)
test_1(){}
#Test(dataProvider = "test_2", dataProviderClass = MyDataProvider.class)
test_2(){}
...
//test_5 was the only one without data provider.
test_5(){}
#Test(dataProvider = "test_6", dataProviderClass = MyDataProvider.class)
test_6(){}
}
public class MyDataProvider {
MyUtilityClass utilObj = new MyUtilityClass();
//do something with utilObj besides other things.
}
Your tests need to end in exactly the same environment in which they started.
You gave nary a clue as to what your code is like, but I can say that it is almost certainly either a database that is being written to and not reverted or an internal, persistent data structure that is being modified and not cleared.
If the tests go to the database, try enclosing the entire test in a transaction that you revert at the end of the test. If you can't do this, try mocking out the database.
If it's not the DB, look for an internal static somewhere, either a singleton pattern or a static collection contained in an object. Improve that stuff right out of your design and you should be okay.
I could give you more specific tips with code, but as is--that's about all I can tell you.
I solved my problem. Test_5 is the only test method which does not have a data provider. So, I provided a mock data provider method for it.
I'm trying to construct a suite of Cucumber tests using Selenium. The first step in each test logs in to a web application.
I'm using the Selenium ChromeDriver, and I can see that Cucumber is using dependency injection to initialise the driver. After each test completes I would like to start fresh with a new web browser, but Cucumber insists on using the same driver used in the previous test. I've tried a number of things to start from a clean point. I'm not sure what the recommended way of doing this is, I presume you have to use the 'Hooks' class, as that contains methods which run before and after each test scenario. Here's what I currently have:
public class Hooks {
private final WebDriver driver;
#Inject
public Hooks(final WebDriver driver) {
this.driver = driver;
}
#Before
public void openWebSite() {
}
#After
public void closeSession() {
driver.close();
}
}
As you can see, I put a driver.close() statement into the #After method, but I don't see a method to reopen, or recreate a new session, and I'm getting the following exception when the next test tries to log in:
Message: org.openqa.selenium.NoSuchSessionException: no such session
Presumably because it didn't like the fact that I just called close().
But really, I want to tell Cucumber that I'd like a completely fresh driver to be used for each test scenario.
I've searched around for Cucumber examples, but all the example code I've found just involves one single test. I didn't turn up anything which was using a suite of tests, aiming to do something similar to what I've described above.
What's the recommended pattern for this?
I have a Selenium test case that I need to write, but before it executes I need to get some information from the user for the Test to run.
Currently, my code is structured like this:
public class myTest {
private WebDriver driver;
#Before
System.setProperty("webdriver.ie.driver",
"C:\\Users\\ktuck\\Documents\\Selenium\\Selenium Server\\IEDriverServer.exe");
driver = new InternetExplorerDriver(); // I guess I don't need to fire this up as i'm only collecting information from the user?
#Test
// Code to collect user inputted data to use later in my test
#After
public void tearDown() throws Exception {
driver.quit(); // Do I need this?
}
}
My initial thoughts were to put the collection code inside of a main function and then call the rest of my test script which would be in a different file, passing the information collected into it. But I'm not quite sure how to do that as I'm quite new to Selenium/Java :p
Can anyone help?
If you are not using any testing framework , you can choose TestNG. TestNG supports Data driven and parameterized test.
you can pass param via testng.xml.
since you are using maven you can configure maven to pass parameters without using testng.xml.
you can also pass params to TestNG via maven through command line like below
mvn -Dtest=<testName> -D<paramName>=<paramValue> test
if you dont want to use any of the testing framework then you can pass the param via JVM arg
and retrive it using System.getProperty("paramName")
Consider using a test framework like JUnit or TestNG. This would enable you to use methods that are run before and after the actual test (as indicated by the pseudo-code given above).
Using this approach, you can do all the lookup stuff in the #BeforeClass method and quit the webdriver in the #AfterTest method. To keep the test class clean, I recommend to move the #BeforeClass and #AfterTest to an abstract super class which you inherit from.
Abstract Superclass
public abstract class AbstractSeleniumTest {
private WebDriver webDriver;
#BeforeClass
public void setup() {
// do all the initalization stuff, e.g. system property lookup
}
#AfterTest(alwaysRun = true)
public void tearDown() {
// do all the clean-up stuff, e.g. webdriver.quit();
}
}
Test Class
#Test
public class MySeleniumTest extends AbstractSeleniumTest {
public void testSomething() {
// do the actual test logic
}
}
I hope this covers most of your question. For further assistance, please give more information.
I'm testing different parts of a miniature search engine, and some of the JUnit tests are leaving entries in the index that interfere with other tests. Is there a convention in JUnit/Maven for clearing objects between tests?
There are 2 particular annotations that can help you with this, and are intended to be used in cases such as yours:
#After defines that a certain method must be executed after every #Test, while #AfterClass is the method to execute once the entire test class has been executed. Think of the latter as a last cleanup method to purge any structures or records you've been using and sharing between tests so far.
Here is an example:
#After
public void cleanIndex() {
index.clear(); //Assuming you have a collection
}
#AfterClass
public void finalCleanup() {
//Clean both the index and, for example, a database record.
}
Note: They have their counterparts (#Before and #BeforeClass) that to exactly the opposite by invoking the related methods before a #Test method and before starting to execute the #Tests defined on that class. This ones are the setUp used in previous versions of JUnit.
If you can't use annotations, the alternative is to use the good old tearDown method:
public void tearDown() {
index.clear(); //Assuming you have a collection.
}
This is provided by the JUnit framework and behaves like a method annotated with #After.
You should make use of the #Before annotation to guarantee that each test is running from a clean state. Please see: Test Fixtures.
Inside of your junit testing class, you can override the methods setup and teardown. setup will run before every one of your tests while teardown will run after every single junit test that you have.
ex:
public class JunitTest1 {
private Collection collection;
//Will initialize the collection for every test you run
#Before
public void setUp() {
collection = new ArrayList();
System.out.println("#Before - setUp");
}
//Will clean up the collection for every test you run
#After
public void tearDown() {
collection.clear();
System.out.println("#After - tearDown");
}
//Your tests go here
}
This is useful for clearing out data inbetween tests, but also allows you to not have to reinitialize your fields inside of every single test.
The selenium tests I'm gonna be doing are basically based on three main steps, with different parameters. These parameters are passed in from a text file to the test. this allows easy completion of a test such as create three of "X" without writing the code to do the create three times in one test.
Imagine i have a test involving creating two of "X" and one of "Y". CreateX and CreateY are already defined in separate tests. Is there a nice way of calling the code contained in createX and createY from say, Test1?
I tried creating a class with the creates as seperate methods, but got errors on all the selenium.-anything-, ie every damn line. it goes away if i extend seleneseTestCase, but it seems that my other test classes wont import from a class that extends seleneseTestCase. I'm probably doing something idiotic but i might as well ask!
EDIT:
well for example, its gonna be the same setUp method for every test, so id like to only write that once... instead of a few hundred times...
public void ready() throws Exception
{
selenium = new DefaultSelenium("localhost", 4444, "*chrome", "https://localhost:9443/");
selenium.start();
selenium.setSpeed("1000");
selenium.setTimeout("999999");
selenium.windowMaximize();
}
thats gonna be used EVERYWHERE.
its in a class called reuseable. Id like to just call reuseable.ready(); from the tests SetUp... but it wont let me....
public class ExampleTest {
#Before
public void setup() {
System.out.println("setup");
}
public void someSharedFunction() {
System.out.println("shared function");
}
#Test
public void test1() {
System.out.println("test1");
someSharedFunction();
}
#Test
public void test2() {
System.out.println("test2");
someSharedFunction();
}
}
The contents of the function after the #Before annotation is what will be executed before every test. someSharedFunction() is an example of a 'reusable' function. The code above will output the following:
setup
test1
shared function
setup
test2
shared function
I would recommend using JUnit and trying out some of the tutorials on junit.org. The problem you have described can be fixed using the #Before annotation on a method that performs this setup in a super class of your tests