DEV Community

Zaerald
Zaerald

Posted on

How to improve Java Unit Testing Skills to a more advanced level?

What are the efficient ways to improve and learn more about Java unit testing? Is there a repository where I can practice Unit Testing with ways how to solve it, so I can compare it with mine? How did you practice doing it? As sometimes when I'm doing stuff I get stuck and not able to test the other parts.

Discussion (6)

Collapse
martinhaeusler profile image
Martin Häusler

There are some principles when writing tests in general. They're so very basic it seems almost stupid, but I find that I constantly have to remind myself of them in order not to get dragged away:

  1. Test the interface, not the implementation. Otherwise you'll just keep updating tests over and over again. Your implementation details can change, and WILL change in a long-running project. This also entails that you should test some of the cases which seem trivial. A trivial case today may be tomorrow's edge case after the implementation has changed. An untested trivial case today may crash your production app tomorrow. When your feature takes numeric inputs, always check positive, negative and zero inputs. For strings, try the empty string as well, include spaces, or some crazy UTF-8 characters if that's a requirement. For any sorts of collections, try the empty collection, the one-element-collection, and a bigger collection. Basically, you'll want to cover the equivalence classes of input parameters as good as possible. Parameterized tests can help to do this in a quick fashion.
  2. A test without an assertion is (almost) worthless. Smoke tests (which just checks if a command executes without throwing an exception) have their place, but in general you should always include assertions in your tests. Assertions can become pretty complex, depending on the degrees of freedom your test allows. There are various assertion frameworks out there to make this job a little easier, check those out (e.g. Assert4J, Hamcrest Matchers, Strikt for Kotlin users). Sometimes, writing assertions can clash with principle #1, it takes some practice and a good amount of judgment to get this right.
  3. A test that cannot fail is (almost) worthless. Imagine you're testing an age filter function that returns all users above the age of 18. In your test, if you don't feed it a user which is below that age, and then you verify that all returned users are indeed 18 or above, the test literally cannot fail, because you didn't provide it any input data where failure is possible.

Testing really is something that takes practice. The more tests you write, the better you'll become. Just make sure you get the basics straight. Frameworks (JUnit is totally fine, but get a good assertion library) and best practices can get you started, but you'll need to work for that "gut feeling" what to test on your own. It will come in time.

Collapse
zaerald profile image
Zaerald Author

Agreed on all the principles, and I want to take action to improve my testing skills.

Testing really is something that takes practice. The more tests you write, the better you'll become.

Do you have a recommendation for my next steps? A practical step to efficiently practice? What I currently do is look for open source projects and read on how they test but it feels like it's a passive thing to do, so I want to explore different paths I can take to actively practice and if I failed to create a test for something, I can look and see some solution.

Collapse
khmarbaise profile image
Karl Heinz Marbaise

I can recommend to try some code katas or very simple things like write a fraction class and try to use tests to implement it. It's very helpful and see how testing and implementing works in combination. Yeah it sounds useless to write such a class...but it helps practicing writing tests etc. because the problem domain is (more or less) simple....

Another level of going is to follow the principles of Kent Beck (read the book and try to write the previously mentioned Fraction class by using the TDD principles and of course practice, practice, practice....

Thread Thread
zaerald profile image
Zaerald Author

Awesome! Will try out those code katas 💪

Collapse
nstandif profile image
Nathan Standiford

It’s important to consider the difference between unit tests and other forms of testing. You should be testing individual modules in isolation. If you’re not, it’s not a unit test. Tools like Mockito can help a lot in Java.

To get great at unit tests means you understand the scope of what you’re testing. Don’t just test the happy path. Try to find as many edge cases as you can. It is much easier to fix an issue if it arises during a unit test vs any other test or, even worse, a customer box.

Try not to put too much in a single unit test. A good unit test should be self documenting. Try to avoid excessive commenting. Unit tests are not the place to get clever. This is usually a sign that you may need to split up your test cases.

Collapse
tomavelev profile image
Toma

I also have a long way to go in testing but, in unit tests, I try to make testXXX to every public method, with parameters of the happy path and with invalid input. Obviously the wrong input scenarios should expand over time and the methods should still work as expected.