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.
Related
With JUnit you can use #RunWith(Parameterized.class) to provide a set of parameters to pass to the test constructor and then run tests with each object.
I'm trying to move as much test logic as possible into data, but there are some tests that won't easily be converted into data-driven tests. Is there a way to use JUnit's Parameterized runner to run some tests with parameters, and then also add non-data-driven tests that aren't run repeatedly for each test object construction?
My workaround for this was to create a single class and place the programmatic and data-driven tests in two separate sub-classes. A sub-class must be static for JUnit to run its tests. Here's a skeleton:
#RunWith(Enclosed.class) // needed for working well with Ant
public class MyClassTests {
public static class Programmatic {
#Test
public void myTest(){
// test something here
}
}
#RunWith(Parameterized.class)
public static class DataDriven {
#Parameters
public static Collection<Object[]> getParams() {
return Collections.emptyList();
}
private String data;
public DataDriven(String testName, String data){
this.data = data;
}
#Test
public void test() throws AnalyzeExceptionEN{
// test data string here
}
}
}
one way is to use Junit's Enclosed runner. it's very verbose but also pretty powerful. it allows you to combine multiple different runners in one file.
other option is to use custom junit runner. for sure zohhak supports tests with parameters and without. small extract:
#RunWith(ZohhakRunner.class)
public class CoercingTest {
#TestWith("ONE_OF_ENUM_VALUES")
public void should_coerce_enum(SampleEnum param) {
assertThat(param).isEqualTo(SampleEnum.ONE_OF_ENUM_VALUES);
}
#Test
public void should_run_standard_junit_test() {
//this will also work
}
}
if it's not enough for you, for sure you can find other runners that support both kind of tests.
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);
}
}
Is it possible to run a JUnit #Test method in a class that has a method annotated with #Before, but to ignore the #Before method only for this test?
Edit: I am interested if JUnit supports this functionality, not workarounds. I am aware of workarounds like moving the test(s) in another class or removing the annotation and manually calling setUp() in each test method.
Suppose in a class there are 30 tests, and for 29 of them #Before really simplifies the testing initialization, but for one (or more than one) of them is useless/it complicates things.
public class MyTestClass {
#Before
public void setUp() {
//setup logic
}
#Test
public void test1() {
//[...]
}
#Test
public void test2() {
//[...]
}
//more tests here
#Test(ignoreBefore = true, ignoreAfter = true //false by default)
//something equivalent to this
public void test20() {
//[...]
}
}
You can do this with a TestRule. See my answer to Exclude individual test from 'before' method in JUnit. Basically, implement ExternalResource, and in the apply method, check if there is a specific annotation on the method, and if there is, don't run the before/after method. You'll have to specifically call the before/after from your rule though.
If it useless it should not be a problem - does it harm to run the setUp once more?
However I don't think it's possible and looks for me as a cripple feature.
Another approach - move that test to a separate test-class.
With JUnit 5 You can have nested tests using #Nested annotation :
public class MainClass {
#Nested
class InnerClass1 {
#BeforeEach
void setup(){}
#Test
void test1(){}
}
#Nested
class InnerClass2 {
// No setup
#Test
void test2(){}
}
}
Just to add to this, something that I found out on a recent visit to this area.
Junit/Mockito seems to give preference to mocking behavior defined in a test, over a #Before annotated method.
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.
I am writting jnuit test case for testing API.
my class is as follows
class MyTest extends TestCase{
List<String> argList;
public MyTest(){
//read argList from File
}
testMyTest(){
//callmy api
myApi(arg1);
}
}
Now i want make a seperate testcase for each of the 50 args.Args are read from File. I dont want to write a seperate method for calling myApi with different args.How can i do it?
I dont want to write sperate methods like
testMyTest1(){
//callmy api
myApi(arg1);
}
testMyTest1(){
//callmy api
myApi(arg2);
}
You can use a parameterized test for this.
You can use a Parameterized tests or Theories (since JUnit 4.4). For more details use
http://blogs.oracle.com/jacobc/entry/parameterized_unit_tests_with_junit
http://blogs.oracle.com/jacobc/entry/junit_theories
private static final String[] args = new String[] {.....};
#Test
public void myTest(){
for (int i=0; i<args.length; i++){
myApi(args[i];
}
}
The above answers your question I think, however it is not good JUnit practice. It is best that each test method only invokes the method under test one time with one test condition. That way if multiple things are wrong, you get a separate error for each rather than dealing with one at a time. This would suggest the following:
private static final String[] args = new String[] {.....};
private void testMyTest(String arg){
myApi(arg);
}
#Test
public void myTest0(){
testMyTest(args[0]);
}
#Test
public void myTest1(){
testMyTest(args[1]);
}
Probably the best mechanism is to do the first option above but using the ErrorCollector rule to allow for multiple errors to be reported.
Edit I stand corrected, jordao's answer regarding parameterized tests is really the best way to do this.
Unit testing usually is made with assertions. You don't need to write a method for each argument, but execute different assertions based on your arguments.
One way for doing it would be:
class MyApiTest extends TestCase {
List<String> argList;
public MyApiTest() {}
public testMyApi() {
assertTrue(testMyApi(arg1));
assertFalse(testMyApi(arg2));
assertNull(testMyApi(arg3));
assertEquals(testMyApi(arg4), testMyApi(arg5));
}
}
I'd even prefer using annotations, like
class MyApiTest {
#Before
public setUp() {}
#After
public tearDOwn() {}
#Test
public testMyApi() {
Assert.assertTrue(testMyApi(arg1));
Assert.assertFalse(testMyApi(arg2));
Assert.assertNull(testMyApi(arg3));
Assert.assertEquals(testMyApi(arg4), testMyApi(arg5));
}
}