I am trying to write integration tests and want to make it in a best way regarding programming best practices, etiquette, etc.
First I had a question on how to reuse existing tests in another test class and I found the answer in topic How to reuse existing JUnit tests in another test class?
After moving the base test functionality and relevant member fields into the base class I found out that I need to make the member fields protected or I need to have their appropriate getters and setters in order I could use them in inherited test classes. Here is an example:
public abstract class BaseTests {
private Class classObj; // or protected without getter/setter?
protected void somethingHelper() {
// Test something
}
protected void somethingElseHelper() {
// Test something for classObj
}
public Class getClassObj() {
return classObj;
}
public void setClassObj(Class other) {
classObj = other;
}
}
public class TestClass1 extends BaseTests {
@Test
public void testSomething() {
somethingHelper();
}
}
public class TestClass2 extends BaseTests {
@Test
public void testSomethingAndSomethingElse() {
somethingHelper();
ClassObj obj = new ClassObj();
// set obj member fields
// and then test something else
setClassObj(obj); // or classObj = obj;?
somethingElseHelper();
}
}
It is not necessarily bad practice to have getters, as long as you keep in mind that unit testing is about isolating behavior and testing specific units of work. Following that, you should make sure that your getters are always returning new instances of objects, instead of dishing out the same copy to all of your unit testing methods.
Sharing objects can cause a lot of issues in unit tests. Most test runners execute tests in parallel, and don't guarantee order execution. Your tests will most likely be modifying the objects, so sharing objects can break other tests in unpredictable ways.
I often create small factory methods for creating objects that I use in all my tests. Especially for the specific class that is being tested.
public ClassUnderTest GetNewClassUnderTest()
{
return new ClassUnderTest("My favorite string", 1234);
}
As far as breaking test functionality into helper methods, I prefer not to do that. It makes test code difficult to scan over quickly. If it is something simple like one or two lines of code, I always include it inline in my tests. Anything more than that and I start to think about refactoring my tests into something more simple, if possible.
EDIT: I would also highly recommend reading The Art of Unit Testing. It's a great book that has a lot of great advice for building and structuring your unit tests.
Jay Fields ( se-radio podcast ) points out there are somehow different rules when writing unit tests.
Of course you should still try to avoid code duplication. But the primary thing that determines whether a unit test is helpful ... is the amount of time that you need in order to understand a failing test.
In other words: ideally, any test method within your test classes or suites are independent of each other. You just read that one method; and you understand what it is doing; you look at the failure; and you found all you need.
Compare that to a solution where (complicated) coupling exists; for example because your concrete test method relies on a lot of things that come even from outside of that class; for example via inheritance.
But as others have said: this very much depends on you and your team. You need a lot of experience in order to create really helpful tests; and there are no simply rules that guarantee great results when blindly following them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With