Inherit a class in JUnit - is it a good practise? - java

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.

Related

How can i test multiple java files with the same junit?

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.

If I have multiple JUnit test classes, but they share a large amount of setup, is there a way to resuse some of this setup code?

I have a number of classes I'm testing, and I've seperated all of the tests for these classes out into their own files. i.e. I have the following sort of directory structure
src
ClassOne.java
ClassTwo.java
test
ClassOneTests.java
ClassTwoTests.java
I have a much larger number of classes to test than this however. I've started to write tests for many of these classes, and I realised that there is a lot of code in the setup that is the same between them all. I'd like to be able to reuse this code, both to reduce the time it takes to write more tests, but also in the event that I end up making modifications to my code base, I want to only have one point in the tests to change, rather than many dozens of almost identical instatiation of mocks.
An example of my code layout is like this:
public class ClassOneTests {
//Declare global variables that are dependencies for the test
AClass var1;
// etc...
ClassOne testThis;
#Before
public void setUp() throws Exception {
//instantiate and populate the dependencies
var1 = new AClass();
// etc...
testThis.setDependencies(var1, //And other dependencies....);
}
#Test
public void aTest() {
//Do test stuff
Var result = testThis.doStuff();
Assert.NotNull(result);
}
// etc...
}
This means a huge majority of stuff in my declaration and setUp method is duplicated across my class tests.
I have partially solved this by simply having a GenericTestSetup.java that does all of this setup and then each ClassXTest.java extends it. The problem lies with the few classes that are unique to each ClassXText.java file, but used in each method. So, in the example above AClass is a variable specific for ClassOneTests. When I do ClassTwoTests I'd have a bunch of shared variables, but then instead of AClass I'd have BClass, for example.
The problem I'm having is that I can't declare two #Before tags, one in the GenericTestClass for the generic setup, and then another in the ClassXTest class if any of the objects inside ClassXTest are dependant on something in GenericTestClass because you can't guarantee an execution order.
In summary, is there a way to have this generic test setup that's used for multiple class tests, but also have another setup method for each specific class that is guaranteed to run after the generic objects have been set up?
EDIT: It was suggested that my question is a duplicate of this question: Where to put common setUp-code for differen testclasses?
I think they're similar, but that question was asking for a more general approach in terms of policy, I have a more specific set of requirements and asking for how it would actually be implemented. Plus, none of the answers there actually gave a proper answer about implementation, which I require, so they're not useful to me.
What i usually do when overloading increases the complexity, I use, what i call Logic classes...
Basically class with static methods which takes the parameters that need to be initialized, and sets them up.
Logic.init(param1, param2)
and I usually use only one #Before with different logic methods.
Advantage is that the code might be shared between similar initializations, and you can reuse the code in the Logic class itself. Example
Logic.init(param1,param2,param3) can call Logic.init(param1,param2), and you can use different variants into the different #Before methods.
EDIT:
I do not know if there is pattern, or a name related to such solution. If there is i would like to know the name as well :).
You could use Template Method pattern. The #before method in the generic class calls a protected method in the same class which is empty but can be overriden in the implementing classes to add specific behaviour.

include test in source file java

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.

JUnit: new instance before invoking each #Test method. What are the benefits?

Currently, I am reading "JUnit in action" book. In this book I found text below:
JUnit creates a new instance of the test class before invoking each
#Test method. This helps provide independence between test methods and
avoids unintentional side effects in the test code. Because each test
method runs on a new test class instance, we can’t reuse instance
variable values across test methods.
Now I do not see much point in this approach:
For example:
public class CalculatorTest {
#Test
public void testAdd_1() {
Calculator calculator = new Calculator();
double result = calculator.add(1, 1);
assertEquals(2, result, 0);
}
#Test
public void testAdd_2() {
Calculator calculator = new Calculator();
double result = calculator.add(2, 2);
assertEquals(4, result, 0);
}
}
For test class CalculatorTest there are no any benefits.
Ok, lets go pay attention on another example:
public class OneTest {
static byte count;
public OneTest() {
count++;
}
#Test
public void test1() {
System.out.println(count);
}
#Test
public void test2() {
System.out.println(count);
}
}
For test class OneTest I found a way to use the same variable count for the many test methods...
so, How to see the real benefits of the approach described in the book?
How to see the real benefits of the approach described in the book?
The purpose of separate instance is not for any benefit but to maintain the contract that each test should be independently executed without any effect of the execution of a previous test. There is just no other way to ensure this contract other than using a different instance for each test.
For example, the Spring transaction management makes sure to rollback all changes made to the database by a test, by default, to maintain the same contract.
So, using static variables in a test is generally discouraged as it will defeat the whole purpose of one-instance-per-test to have a clean slate for each test.
Keeping the state clean between test methods is useful for unit tests but gets in the way for functional tests, where having dependencies between tests is often necessary (for example, when you are testing web pages using Selenium, it's useful to not bother running tests of a certain page if the tests for the login page failed).
This was one of the main reasons why I created TestNG, which doesn't instantiate a new class between each method, therefore giving you the choice instead of imposing this decision on you.
TestNG also supports dependencies of tests, multithread testing, has the notion of groups ("only run the servlet tests") and many more features.
If you're testing a mutable class, there's great value in having your tested object in a known state at the beginning of each test method, so that the order of test execution does not matter. The easiest way to accomplish that is to create a new instance of that class for each test, and to avoid static fields.
In your calculator example, it appears that your Calculator class is immutable and the results of method calls depend only on the parameters. So the risk of one test influencing another is just not there.
I don't quite see the point of your second example. You've written methods annotated as #Test that use a shared static field, but your methods have no assertions, and are not really testing anything.
If you want to do use static fields or indeed to hold onto and reuse a single instance of the class under test, it's certainly possible to to so, but to make your tests work and stay independent of each other will tend to require more care.

Best practice for naming unit and integration test methods?

I've recently inherited an application that is written by different people at different times and looking for guidance on how to standardize.
Assuming NUnit:
[Test]
public void ObjectUnderTest_StateChanged_Consequence()
{
Assert.That(tra_la_la);
}
[Test]
public void ObjectUnderTest_Behaviour_Consequence()
{
Assert.That(tra_la_la);
}
for example:
[Test]
public void WifeIsTired_TakeWifeToDinner_WifeIsGrateful()
{
Assert.That(tra_la_la);
}
[Test]
public void WifeIsTired_MentionNewGirlfriend_WifeGetsHalf()
{
Assert.That(tra_la_la);
}
I just write what it's for. It's not like you're going to have to type the names in anywhere else, so having a testWibbleDoesNotThrowAnExceptionIfPassedAFrobulator isn't a problem. Anything which is a test begins with 'test', obviously.
There is no standard as such, different people/places will have different schemes. The important thing is you stick to a standard.
Personally I'm a fan of the following - example code in C#, but very close to Java, same rules apply:
[Test]
public void person_should_say_hello()
{
// Arrange
var person = new Person();
// Act
string result = person.SayHello();
// Assert
Assert(..., "The person did not say hello correctly!");
}
Explicit
The test name should give the name of the class under test. In this example, the class being tested is Person. The test name should also have the name of the method that is being tested. This way, if the test was to fail, you'll at least know where to look to solve it. I'd also recommend following the AAA - Arrange, Act, Assert rule, it will ensures your tests are easy to read and follow.
Friendly fail messages
When it comes to asserting a result/state, its useful to include an optional message. This makes it easier when a test fails, especially when run as part of a build process or via an external tool.
Underscores
The final (though optional) stance I follow is using underscores for tests names. While I'm no fan of underscores in production code, their use in test names is useful as test names are often much longer. Quickly glancing at a test name that uses underscores proves to be much more readable, though this is subjective and the source of much debate with regards unit testing practices.
Integration Tests
The same standards apply to integration tests, the only difference being the location of such tests should be separate from unit tests. In the example code above, the test class would be called PersonTests and located in a file called PersonTests.cs. The integration tests would be named in a similar manner - PersonIntegrationTests, located in PersonIntegrationTests.cs. The same project can be used for these tests, but ensure they are located in separate directories.
It's instructive to look at BDD (behavioural driven development) and this blog post in particular.
BDD is essentially focusing on components and what they should do. Consequently it impacts directly on how you name/structure your tests, and the code they use to set up conditions and validate. BDD allows not only the developers to read/write the tests, but non-technical members of the team (business analysts etc.) can contribute by specifying the tests and validating them.
I ran across two good suggestions. Links here: http://slott-softwarearchitect.blogspot.com/2009/10/unit-test-naming.html
http://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStandards.aspx
http://openmrs.org/wiki/Unit_Testing_with_#should
In that situation I'd probably find the naming convention that was used the most and refactor the rest of the code to use that. If the one that was used the most is truly horrid, I'd still look to the existing code and try to find one that I could live with. Consistency is more important than arbitrary conventions.
I use a FunctionTestCondition construct. If I have two methods, Get and Set I would maybe create the following test methods:
GetTest being a positive test (everything is ok).
GetTestInvalidIndex to test an invalid index being passed to the method.
GetTestNotInitialized to test when the data is not inited before use.
SetTest
SetTestInvalidIndex
SetTestTooLargeValue
SetTestTooLongString
Group your tests by setup, make a test class around this setup and name is with suffix Test or IntegrationTest. Using a test framework like JUnit or TestNG you can name your test methods as you want. I would name the method as what it tests, a sentence in camel case, not test prefix. The frameworks use a #Test annotation to mark a method as test.

Categories

Resources