I have 3 tests defined in 3 different classes
Class 1
#Test 1
Class 2
#Test 2
Class 3
#Test 3
I have created another class 'Class Browsers' in which I am creating different browser drivers
Now I want to call #Test1,2 & 3 from the browsers class so that these tests are executed in different browsers
Is the following right approach?
Class Browsers
{
public static Class1 A =new Class1()
public static Class2 B =new Class2()
public static Class3 C =new Class3()
#Test
public void createCromeDriver(){
A.Test1
B.Test2
C.Test3
}
#Test
public void createIEDriver(){
A.Test1
B.Test2
C.Test3
}
}
(In the above scenario I am calling tests which belongs to other classes into another class having its own tests.)
While that does run all of the tests, it assumes you only want to know about one test failure per driver. If all three IE tests fail, do you want three failures so you know this all at once? I would.
To deal with that, you use a Parameterized JUnit Test. This lets you write code like this. JUnit will call each of the tests with each of the parameters. In my example, it runs the two tests with the IE browser. You can add as many drivers as you want to the browsers() method to have it call the two tests with each of those browsers.
#RunWith(Parameterized.class)
public class Browsers {
private WebDriver driver;
public Browsers(WebDriver _driver) {
driver = _driver;
}
#Parameters
public static Collection<WebDriver[]> browsers() {
List<WebDriver[]> list = new ArrayList<WebDriver[]>();
list.add(new WebDriver[] { new InternetExplorerDriver() });
return list;
}
#Test
public void test1() {
A.test1(driver);
}
#Test
public void test2() {
B.test2(driver);
}
}
Related
While migrating some tests from JUnit to TestNG, I'm facing an issue because of the difference in how these test frameworks treat their Test class instances.
JUnit creates a new instance of the Test class for each test method. So a common pattern I see is:
public class MyTest {
private Stream inputData;
#Before
public void setUp() {
// Set up some data in (non-static) instance fields
// This data is isolated per test
inputData = createInputDataStream();
}
#Test
public void testStuff() {
// Use the data from the instance fields
doStuff(inputData);
}
#After
public void tearDown() {
// Clean up the data from the instance fields
closeInputDataStream(inputData);
}
}
In contrast, TestNG uses a single instance of the Test class for all test methods. So the pattern above does not work! Because data is stored in instance fields, the values are no longer isolated. This can cause overwritten data mid-test if parallel execution is enabled.
So how would I do this with TestNG? Is there a way to store data which is isolated to each #BeforeMethod-#Test-#AfterMethod tuple?
I can do all 3 steps inside the #Test itself, but that would require adding ungainly try...finally blocks to every test. I also tried using ITestContext, but it also seems to be shared for the entire test run.
Yes, with TestNG you have way more power over those local variables that you did with JUnit AND the DataProvider handles your threading, per test-class-instance:
public class MyTest {
private Stream inputData;
#BeforeMethod
public void setUp(Object[] args) {
inputData = (Data)args[0];
inputData = normalizeDataBeforeTest(inputData);
}
#Test(dataProvider="testArgs")
public void testStuff(Data inputDatax, Object a, Object b) {
doSomethingWith(a);
doSomethingWith(b);
doStuff(this.inputData);
}
#AfterMethod
public void tearDown() {
// Clean up the data from the instance fields
closeInputDataStream(inputData);
}
....
#DataProvider
public static Object[][] testArgs() {
// generate data here, 1 row per test thread
Object[][] testData;
for loop {
// add row of data to testData
// {{dataItem, obja, objb}, {dataItem, obja, objb}} etc.
}
return testData;
}
}
At the moment I have the following code:
public class AlterServiceSelT
{
#Before
public void setupAndActivate()
{
System.out.println("setupAndActivate");
}
#Test
public void suspendService()
{
System.out.println("suspendService");
}
#Test
public void reActivateService()
{
System.out.println("reActivateService");
}
#After
public void terminateService()
{
System.out.println("terminateService");
}
}
and when ran I get the following in my console:
setupAndActivate
reActivateService
terminateService
setupAndActivate
suspendService
terminateService
The problem is that the full code for setupAndActivate() takes 15 minutes and its output is needed to run for the tests. Ideally I would like the console to output:
setupAndActivate
reActivateService
suspendService
terminateService
How could this be done?
Try looking at #BeforeClass in stead of using the #Before.
One of the downsides of BeforeClass is that it has to be defined on a static method, so all your fields that you set up have to be static.
Upside is that your setup is only done once for all the tests in your class.
Are you sure that a setup of 15 minutes is optimum for your application?
I have a class, which I use as a basis for my unit tests. In this class I initialize the whole environment for my tests, setting up database mappings, enter a number of database records across multiple tables, etc. That class has a method with a #BeforeClass annotation which does the initialization. Next thing, I extend that class with specific classes in which I have #Test methods.
My question is, since the before class is exactly the same for all these test classes, how can I ensure that they are run only once for all the tests.
One simple solution is that I could keep all the tests in one class. However, the number of tests is huge, also they are categorised based on functional heads. So they are located in different classes. However since they need the exact same setup, they inherit the #BeforeClass. As a result the whole setup is done at least once per test class, taking much more time in total than I would prefer.
I could, though, put them all in various subpackages under one package, hence if there is a way, how I can run set up once for all the tests within that package, it would be great.
With JUnit4 test suite you can do something like this :
#RunWith(Suite.class)
#Suite.SuiteClasses({ Test1IT.class, Test2IT.class })
public class IntegrationTestSuite
{
#BeforeClass
public static void setUp()
{
System.out.println("Runs before all tests in the annotation above.");
}
#AfterClass
public static void tearDown()
{
System.out.println("Runs after all tests in the annotation above.");
}
}
Then you run this class as you would run a normal test class and it will run all of your tests.
JUnit doesn't support this, you will have to use the standard Java work-arounds for singletons: Move the common setup code into a static code block and then call an empty method in this class:
static {
...init code here...
}
public static void init() {} // Empty method to trigger the execution of the block above
Make sure that all tests call init(), for example my putting it into a #BeforeClass method. Or put the static code block into a shared base class.
Alternatively, use a global variable:
private static boolean initialize = true;
public static void init() {
if(!initialize) return;
initialize = false;
...init code here...
}
Create one base class for all tests:
public class BaseTest {
static{
/*** init code here ***/
}
}
and every test should inherit from it:
public class SomeTest extends BaseTest {
}
You can make one BaseTest class with a #BeforeClass method, then have all the other tests inherit from it. This way, when each test object is constructed, #BeforeClass gets executed.
Also avoid executing it just once for all the test suite, since all the test cases should be independent. #BeforeClass should execute only once each test case, not test suite.
If you can tolerate adding spring-test to your project, or you are using it already, then a good approach is to use the technique described here: How to load DBUnit test data once per case with Spring Test
Not sure if anyone still is using JUnit and trying to fix it without using Spring Runner (aka no spring integration). TestNG has this feature. But here is a JUnit based solution.
Create a RunOnce per thread operation like so. This maintains a list of classes for which the operation has run.
public class RunOnceOperation {
private static final ThreadLocal t = new ThreadLocal();
public void run(Function f) {
if (t.get() == null) {
t.set(Arrays.asList(getClass()));
f.apply(0);
} else {
if (!((List) t.get()).contains(getClass())) {
((List) t.get()).add(getClass());
f.apply(0);
}
}
}
}
Back in your unit test
#Before
public beforeTest() {
operation.run(new Function<Integer, Void>() {
#Override
public Void apply(Integer t) {
checkBeanProperties();
return null;
}
});
}
private void checkBeanProperties() {
//I only want to check this once per class.
//Also my bean check needs instance of the class and can't be static.
}
My function interface is like this:
interface Function<I,O> {
O apply(I i);
}
When you use this way, you can perform operations once per class using ThreadLocal.
I have a java package which contains all my test case classes. Each class contains a lot of test cases. Each class is loaded and run one by one by JUnit. However each of the classes contains common configuration code which is run again and again and initialised everytime each of the classes are run.
These initializations take a lot of time.
Is there some way to load these configuration changes first and then run the test case so that I do not need to load them everytime.
JUnit4 has #BeforeClass annotation.
Just do something like this:
public class TestClass {
private static SomeConnection connection;
#BeforeClass
public static void setUp() {
//do common setup
connection = new SomeConnection();
}
#Test
public void testSomething() { }
#Test
public void testSomethingElse() { }
#AfterClass
public static void tearDown() {
//do teardown operations
connection.close();
}
}
Method marked with #BeforeClass will run only once. Just make sure you use JUnit4.
Update:
Also note, that it should be static, and as #ChristopheRoussy mentioned, you can use #AfterClass to destroy your common setup.
You can create a static method that is run before the tests within the class are ran.
#BeforeClass
public static void ranOnlyOnce() {
/*...*/
}
Moreover, if you want to run this once before all of your tests, then you should group your tests in a suite, and put this method in this class, and use JUnit to run the suite instead of the tests.
#RunWith(Suite.class)
#SuiteClasses(value = { Test1.class, ... , Testn.class })
public class AllTests {
#BeforeClass
public static void beforeAllTests() {
/*...*/
}
}
Note that annotations can be used only in Junit 4+.
I would recommend grouping your tests into a testsuite and doing the initialization from the testsuite. There is a good discussion of the possibilities here http://www.xoriant.com/blog/software-testing-and-qa/using-customized-junit-testsuite-for-testing.html
There are a number of possibilities. The first and easiest is to use #BeforeClass and #AfterClass as has been suggested by Matyas and jFrenetic. This is the easiest way to do it if none of the test classes share setup code.
If the classes share the same setup and teardown, look at using the TestRule, specifically the ExternalResource, which allows you to run code before and after each class. The difference between this and #BeforeClass and #AfterClass is that it uses the same class, and therefore the code can be shared more easily. This can be done for example:
#RunWith(Suite.class)
#SuiteClasses({A.class, B.class, C.class})
public class UsesExternalResource {
public static Server myServer= new Server();
#ClassRule
public static ExternalResource resource= new ExternalResource() {
#Override
protected void before() throws Throwable {
myServer.connect();
};
#Override
protected void after() {
myServer.disconnect();
};
};
}
This works in a test class as well, so you could have different, but shared setups for different classes.
Suppose, I have a junit test class:
class MyComponentTest {
private void test(File file) {...}
#Test public void test1() {test("test1.txt")}
#Test public void test2() {test("test2.txt")}
#Test public void test3() {test("test3.txt")}
}
The test method reads the input data from the file and test the component with the input data.
What if I am changing the MyComponentTest ?
class MyComponentTest {
private void test(File file) {...}
#Test public void testAll() {
for (String name: dir.list())
test(new File(name))
}
}
Now I have only one test (testAll) instead of three tests (test1, test2, and test3) as it was before. The Runner for example will not recognize three separate tests as it did in the previous version of the class.
My question is: how to make each test method invocation a separate test from the junit point of view ?
Though you can use Junit's Parameterized tests for this it is bit involved and ugly. I suggest you looking at the spockframework which simplifies this a lot. And there is also another option in TestNG.