13

I am writing JUnit unit tests for my classes.

Is it better to have a separate class for each method, or have just one test class for every actual class?

18

How your tests are organized is rather unimportant compared to the importance of having them at all.

The most important thing for a good test suite is that it covers all of the functionality; that ensures that whenever a regression defect is introduced, you'll notice right away. Whether to write one test for each method, one test for each input value combination of a method, or even one test for each possible code path within that method is less important. Whether to organize these tests into few or many test classes is even less important: a test suite should always succeed in full, so it doesn't matter whether it fails one of three or two out of seventeen tests - both are wrong and must be fixed.

Of course, test code is also code, so it should follow the normal best practices for being maintainable, modular, etc. But that must be decided by how well-maintainable the test suite itself is, not by how the test classes relate to the classes they test. Both of the policies you mention can help you remember where to find things if you follow them consistently, but for that the consistency is more important than the choice of policy.

7

To your specific question, the JUnit convention, is to have a 1:1 correspondence between your application classes (Foo1.java, Foo2.java) and JUnit test classes (Foo1Test.java, Foo2Test.java).

That said, I agree wholeheartedly with Kilian's highlighting of the importance of the spirit/goals of unit testing over any organizational schemes that might be used. Pick some conventions and stick with them most of the time, while guardedly allowing exceptions to your conventions, when they're warranted.

4

Is it better to have a separate class for each method, or have just one test class for every actual class?

If you have the need to write separate test classes for methods of one class, then you have the wrong design. Methods should be small, easy to read, easy to test and easy to change. The tests could be a bit longer than the original code due to making up testdata, mocking etc., but should not be significantly longer. If they are, your class under test is too complex and does for sure more than one thing (single responsibility principle): Work on your design.

2

I think both "one test class per method" and "one test class per class" are usually too extreme.

In general, you want to have one check per test method/unit test. For instance, these could be multiple assertions to check that a list.isEmpty = true and list.Length = 0, so one test method/unit test per behavior.

This makes it easy to come up with a test method name that describes the behavior. You want to group test methods in a test class, so when you read the test classname.test method, it makes sense. Usually, those have some shared setup code that is then easy to put in the test setup/fixture. Depending on the class under test, this can be one test class for the whole class, and it can also be one test class for one method. But usually, it will be somewhere in between.

As with normal code, you want to have the tests as readable as possible. What helps for me is following the BDD given-when-then or arrange-act-assert style of organizing the test code. A test class could have that given, it's setup. Then, every test method in that class uses that given (or part of it) and has one when and one then.

Think also of the unit tests as documentation on how to use functionality of the class under test. With good unit tests, you can read the tests to find out how to use the functionality of the class you want to use, and what the effects will be exactly.

When something breaks and a unit test fails, you want it to be as easy as possible to understand what broke, one assertion per test helps a lot here. When there are multiple assertions in one test, only the first one fails and then the method exits, so you don't know if the other behavior tested in the following tests is also broken until you fix the thing that made the first assertion fail. With one assertion, all your other test methods still get executed and it's much faster to understand the depth of the fail.

Of course, I agree with Kilian Foth: in practice, you can be lucky to have a few unit tests for code you are working on. And any small localized test is better than no test at all, or only big integration tests that run on the build server take a lot of time and usually aren't very localized (they don't tell you fast where the error is - you'll have to work on it a little).

  • Good point: "You want to group testmethods in a testclass so when you read the testclassname.testmethod it makes sense". – MAChitgarha Jan 11 at 13:02
1

I think it's right that each class has its test class. The idea is to centralize all unit tests related to the target class in a single test class. Then, for example, MyClass.java will have its test class called MyClassTest.java.

0

It's good practice also to ask your colleagues whether there is documentation about how to test in your company, or what is the way they are following. If you follow their guideline, it makes your tests better readable for others.

New contributor
Sae1962 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.