I am studing how to create java test cases. In internet I saw two structures:
public class XXX {
#Test
#Test
}
And
public class XXX extends TestCase {
//test cases
}
I am trying to use the second one but I can not create ignore case. In first example I can use #Ignore. What about the second one?
The second method is the old method with JUnit (up to JUnit 3). It doesn't use Annotations (those things that start with #).
The new method uses Annotations (#Test and #Ignore to name just two).
If you insist on using the old method (JUnit 4), check out this question for more information.
Related
I just started with Junit Testing very recently, so please excuse me if my terminology is not correct. As far as I know, the methods become a test method if we annotate it with a #test and we can run it with an IDE(I am using Intellij) by clicking on the play button next to it. In the background, it probably instantiates an instance of the Test class and run the selected method. My question is, in the example below, if test1 and test2 both use and edit the same hello string of the same instance of the Test class, since test2 runs after test1, it should print the edited version of the hello String? i.e: test2 should print "1". But in this case it prints an empty String. Why is this ?
class Test{
private String hello = "";
#Test
void test1() {
hello = hello + "1";
System.out.println(hello);
}
#Test
void test2() {
System.out.println(hello)
}
}
This happens due to the lifecycle of the test.
You've guessed correctly, indeed JUnit instantiates the Class of the test (class Test in this case).
In other words somewhere in the code of JUnit there is a line:
Test test = new Test() (in the real code it uses reflection, but it doesn't matter for the sake of the question).
Then it runs the test methods, so far so good - you were right:
Test test = new Test();
test.test1();
test.test2();
// handle failures, exceptions, etc.
However, JUnit is designed in a way that it instantiates the class of test before running every single test method. This is a design decision of the JUnit framework.
So, the "more accurate" representation of what happens in JUnit looks like this:
Test test = new Test();
test.test1();
....
test = new Test();
test.test2();
This is a default behavior of JUnit, all the data fields get instantiated over and over again for each test and it guarantees that test1 prints 1
and test2 prints an empty string.
This happens regardless the order of actual tests execution.
Now, this behavior can be altered by using #TestInstance(LifeCycle.PER_CLASS) annotation on the test class, but its a pretty advanced stuff. It will instruct the JUnit engine to create only one single object of class Test and run all the test methods in it. So if one test method will change the data field defined in the class Test the other test will actually see this change.
If you're interested to learn more about #TestInstance - consider reading this article for example
In most case Unit tests should not depend on the order or execution.
By default JUnit won't guaranty you an order of execution, in this case test1 could be executed after or before test2.
For tests you can use #BeforeEach or #BeforeAll to execute some code before your tests.
Also you can use #Order(1) to run force the test order. However I would strongly advocate again it except in really specific case.
How can i test several .java files(that implements the same method in different ways) with one unit test?
For example, i have a folder with different .java files(or different folders with the same name .java file), how can i select all of them to run it?
right now i need to select each time one of them and move it to the same folder with the unit test and run it.
Thanks.
Edit: I think i wasn't clear enough, so i will give more example:
I have files aa.java and bb.java, which both have the method "static public int fibonacci(int x)", i want to create a unit test, that will use aa and bb methods and see if they work properly(assertEquals(result, expected)).
P.S. i have more then only 2 files with the same method.
Assuming you want to adhere to DRY, write a utility method to do the testing, and have a unit test(s) call it.
Eg
private static void assertFibonacci(IntUnaryOperator op) {
int n = 5;
int expected = 8;
// or a loop of values, whatever
assert op.applyAsInt(n) == expected;
}
Then in your unit test:
#Test
public void testX() {
assertFibonacci(new aa()::fibonacci);
assertFibonacci(new bb()::fibonacci);
}
Or better, use separate Test methods, so errors in each are reported separately:
#Test
public void testAA() {
assertFibonacci(new aa()::fibonacci);
}
#Test
public void testBB() {
assertFibonacci(new bb()::fibonacci);
}
The Spock Framework, which runs on top of JUnit, has much better support for parameterized testing, which is what you seem to want, than either plain JUnit or TestNG.
If you can't use Spock, you can either use JUnit Parameterized and supply an instance of each of your classes as your data set, or (my recommendation) write all your common unit tests in an abstract base class WidgetTests with a method protected abstract Widget getInstance() and subclass for each kind of widget. This will still end up with multiple classes, but you won't repeat your test cases, and it allows you to write additional implementation-specific tests in an organized way.
I developed a java application and I want to write unit test for it. (I have never written a unit test in java before) I noticed that there are 2 different example by writing Junit test. like E.g. 1
public void testExample(){
//do something...
}
than E.g. 2
#Test
public void Example(){
//do something...
}
which one is the more usefull ?
Test convention have changed in JUnit4
There's no need for test prefix anymore, just use #Test annotation before the method:
JUnit 3 used naming conventions for the identification of test methods. JUnit 4 uses annotations for that purpose, so that the prefix "test" is actually superfluous. It is not only superfluous, but also redundant.
Instead writing something like:
#Test
public void testAverageTotalStartedThreadCount() {}
you could just skip the prefix "test" and go with the annotation only:
#Test
public void averageTotalStartedThreadCount() {}
The "test" prefixes are still generated by Eclipse and NetBeans, so if you don't like the superfluous naming, you will have to remove it manually. The "test" prefix in the test-class name, however, is still useful. It makes the search for test classes more easy.
For example 1, I assume you are planning to throw exception or log if something goes wrong.
Although you can do it, but the preferred way is to write proper unit test using frameworks like Junit (#Test is from Junit framework).
Junit framework makes testing easier and is considered standard in Java Development. You can use features like Assert to check the output of method or fields inside it. Thus Ex 2 is preferred in industry. refer this test file written using junit framework -
https://github.com/akashchandwani/Algorithms/blob/master/Algorithms/test/sorting/SortingTest.java .
Here's a junit tutorial you can refer to, there are several available on web, you can choose what suits you.
http://www.vogella.com/tutorials/JUnit/article.html
I have this problem. One class (and actually with one public method) to test, and ~30 test scenarios stored in the separate xml files. As one unit test class would be too long (need to test all the files in separate test), I decided to divide them into few groups (few classes), and now the questions occur.
The unit test itself implements few other methods, used in testing (for getting resources, formatting calendar in different matter), as I got few of those unit classes I should also copy those methods.
I just thought if I could create additional class for the methods, and use simply inheritance, or maybe I should create each unit test with the those copied methods? What is the good practice in such a case?
An alternative to inheritance is delegation, as mentioned by Alan Stokes. A good way to make use of this in junit is: use Rules. Some are provided, but you can rather easy create your own set of rules.
The major benefit we have experienced is that you can cherry pick the common features you want to have. Sometimes you just want a tiny bit of the common abstract test class. But as you can only have the full set or nothing, you may end up setting up a database state for a rather simple unit test.
In the sample below from the junit Wiki the TemporaryFolder Rule adds the ability to the test to create temporary folders and files. Those will be deleted after every test execution.
public static class HasTempFolder {
#Rule
public TemporaryFolder folder = new TemporaryFolder();
#Test
public void testUsingTempFolder() throws IOException {
File createdFile = folder.newFile("myfile.txt");
File createdFolder = folder.newFolder("subfolder");
// ...
}
}
Another good thing about it is that you can change the behaviour to class level rather easy. A situation where you might want to have this is the setup of an expensive fixture state in a database or search index. Or when you create a big sample XML for some ETL process for which you want to run an integration test. This should be used only when performing read only operations.
To move it to class level, you just need to make the member static and add the #ClassRule annotation instead of #Rule
public static class HasDataBaseState {
#ClassRule
public static DataBaseState dbState = new DataBaseState();
#Test
public void testUsingDataBaseState() throws IOException {
// perform tests
dbState.query("select count from table where attribute = 'x'");
}
}
There are more features, but those are covered rather good on the junit wiki. The facts I pointed out are the ones we like most about it.
If you need common test fixtures for a number of different test cases, it's perfectly fine to use an abstract base class for your unit tests. For example, small-scale integration tests using Spring will often use a base class that sets up the test runner and context and then add the specific components they're testing.
I Want to write my unit test in the same source file being tested (like you can do in D http://dlang.org/unittest.html).
I also want to be able to run the test in eclipse as i usually do with a dedicated test file.
In this example Junit complains if there is no public zero argument constructor:
public class Dummy {
private String _name;
public Dummy(String name) {
_name = name;
}
public String name () {
return _name;
}
#Test
public void testName() throws Exception {
assertEquals("dummy", new Dummy("dummy").name());
}
}
Any suggestions on how to put the test method in the "real" source code and be able to run the test (in other words how to fool the no arg constructor restriction)?
Thanks
You could consider classical TDD (based on Kent Beck's book "Test Driven Development By Example"), where the idea is not to write tests for specific classes/methods, but rather for features that you want to implement.
That way, it really doesn't make sense to put tests in production classes.
To run the JUnit Test framework, it internally requires a zero argument constructor to instantiate it. Generally it creates by default, if you don't have any constructor. But since you have one constructor with argument, the framework will not be able to instantiate the respective class to execute the test case. To avoid it create a blank no argument constructor.
Having test methods in the same class is not possible with JUnit and is also a quite strange design choice. Well, it would be possible if you had a zero argument constructor, but still, a test class is not meant to be the class that is tested. However, you can create a test class in the same file to carry out your test cases.
You can create a second constructor without parameters if you really want to put your JUnit tests inside the same class. Nevertheless this is not the way you do it according to the java conventions.
Also it bloats the class with unnecessary test cases (unnecessary for the actual task the class should do). You should maybe think about it if it would not be better to put the test cases in a separate class.
You can write your own Runner instead of using JUnit's default BlockJUnit4ClassRunner. Please let me know if you need help.