Core Java

It’s All About Tests – Part 1

This post is the first of a series of three.

  1. Mindset of testing
  2. Techniques
  3. Tools and Tips

The Mindset

Testing code is something that needs to be learned. It takes time to absorb how to do it well. It’s a craft that one should always practice and improve.

 
Back in the old days, developers did not test, they checked their code. Here’s a nice twit about it:

Today we have many tools and techniques to work with. XUnit frameworks, mock frameworks, UI automation, TDD, XP…

But I believe that testing starts with the mind. State of mind.

Why Testing

Should I really answer that?
Tests are your code harness and security for quality. Tests tell the story of your code. They prove that something works. They give immediate feedback if something went wrong. Working with tests correctly makes you more efficient and effective. You debug less and probably have less bugs, therefore you have more time to do actual work. Your design will be better (more about it later) and maintainable. You feel confident changing your code (refactor). More about it later. It reduces stress, as you are more confident with your code.

What to Test

I say everything. Perhaps you will skip the lowest parts of your system. The parts that reads/writes to the file system or the DB or communicate some external service. But even these parts can be tested. And they should. In following blogs I will describe some techniques how to do that.

Test even the smallest thing. For example, if you have a DTO and you decide that a certain field will be initialized with some value, then make a test that only instantiate this class and then verify (assert) the expected value (and yes, I know, some parts really cannot be tested. but they should remain minimal).

SRP

Single Responsibility Principle. This is how I like to refer to the point that a test needs to check one thing. If it’s a unit test, then it should test one behavior of your method / class. Different behavior should be tested in a different test. If it’s a higher level of test (integration, functional, UI), then the same principle applies. Test one flow of the system. Test a click. Test adding elements to DB correctly, but not deleting in the same test.

Isolation

Isolated test helps us understand exactly what went wrong. Developing isolated test helps us concentrate on one problem at a time.

One aspect of isolation is related to the SRP. When you test something, isolate the tested code from other part (dependencies). That way you test only that part of the code. If the test fails, you know were it was. If you have many dependencies in the test, it is much harder to understand what the actual cause of failure was.

But isolation means other things as well. It means that no test would interfere another. It means that the running order of the tests doesn’t matter. For a unit test, it means that you don’t need a DB running (or internet connection for that matter). It means that you can run your tests concurrently without one interfere the other (maven allows exactly this). If you can’t do it (example: DB issues), then your tests are not isolated.

Test Smells

When the test is too hard to understand / maintain, don’t get mad on it! Say:

thank you very much, my dear test, for helping me improve the code

If it is too complicated to setup environment for the test, then probably the unit being tested has too many dependencies.

If after running a method under test, you need to verify many aspects (verify, assert, etc.), the method probably does too much. The test can be your best friend for code improvement.

Usually a really complicated test code means less structured production code. I usually see correlation between complicated test and code that doesn’t follow the SRP, or any other DOLID principles.

Testable Code

This is one of my favorites. Whenever I do code review I ask the other person: “How are you going to test it?”, “How do you know it works?” Whenever I code, I ask myself the same question. “How can I test this piece of code?”

In my experience, thinking always on how to create testable code, yields much better design. The code “magically” has more patterns, less duplication, better OOD and behaves SOLIDly.

Forcing yourself to constantly test your code, makes you think. It helps divide big, complicated problem into many (or few) smaller, more trivial ones.

If your code is testable and tested, you have more confident on it. Confident on the behavior and confident to change it. Refactor it.

Refactoring

This item can be part of the why. It can be also part of the techniques. But I decided to give it special attention. Refactoring is part of the TDD cycle (but not only). When you have tests, you can be confident doing refactoring. I think that you need to “think about refactoring” while developing. Similar to “think how to produce testable code”. When thinking refactoring, testing comes along.

Refactoring is also state of mind. Ask yourself: “Is the code I produced clean enough? Can I improve it?” (BTW, know when to stop…)

This was the first post of a series of posts about testing. The following post will be about some techniques and approaches for testing.

Eyal Golan

Eyal is a professional software engineer and an architect. He is a developer and leader of highly sophisticated systems in different areas, such as networking, security, commerce and more.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
will
will
10 years ago

I think you have a typo there: “DOLID principles”, should probably be solid.

Back to top button