📜 ⬆️ ⬇️

7 rules of good tone when writing Unit tests


“Good manners have one
who is the least number of people
embarrassing. ”
J. Swift


Hello colleagues! Today I would like to talk about unit testing and some “rules” when writing them. Of course, they are informal and not obligatory for execution, but if they are followed, everyone will be pleased and easy to read and maintain the tests that you wrote. We at Wrike have seen enough Unit tests to understand the main problems that arise when writing and maintaining them, and formulate several rules to prevent them.

1. Unit tests need to be written . Yes, however banal it may sound, but they need to be written. Each piece of application logic must be tested to avoid problems in the future. And they can occur when changing the logic, refactoring, or even when updating the version of the dependent libraries. And the more code coverage tests, the faster the problem will be detected and fixed.

2. This rule is very important for those who are forced to cover the code with tests, and it sounds like this: Tests are also code, and should be treated as working code . This also applies to the naming of variables, and the formatting of the code inside the test, and, especially, the names of test methods. Of course, writing an adequate variable name takes a little more time and strikes the keyboard than “int i = 0;”, but this increases the readability of the tests and the ease of their support.
Guess what the fallen test method checks?)
image

3. The third rule

this gentleman - watch the paths . Of course, it is always unpleasant to see when running tests, such an error:

And not even because your name is not Andrey, but because you have a poppy. And how to be in this situation, you ask? The answer is simple - relative paths. Here is an example -

It is best to use the Unix separator (/). This is much more concise, and less likely to get an unexpected error.
')
4. Use caps (moki) more often than real objects. Moki is great! They can be managed as needed in a specific test. But, of course, do not forget to reset the state of the plugs before each test method. The use of plugs increases the autonomy of the test and its flexibility. You do not need to adjust the state of the system for a particular case, but simply set up a stub to return the desired value when calling a certain method and that's it. I want to check another situation - I fixed the return value to another. Simply and easily. And the most important thing is that the state of the whole system does not change at the same time - it does not write anything to disk, does not transmit over the network, does not recalculate data arrays, does not climb into other services. Just a stub and return value.
To use stubs in tests, I use the Mockito framework. Using it is very easy to create stubs. For example:

This is where the mock of the calendar object is created and passed to the calendarService object. Next, mocks are initialized in the setUp method. Then, directly inside the test, the card is configured and the test checks isModern , if the calendar type is different or not specified at all. It did not have to recreate CalendarService , and the creation of mocks and the generation of returned values ​​took only a few lines.

5. Write meaningful messages in case the test fails . The most common message I saw when analyzing dropped tests on TeamCity is

Well, immediately everything is clear! But it happens that the error message is still there, but the benefits of it ...

And here is a good, but not yet perfect, message, which immediately describes what was checked

The message can be considered ideal, which not only shows what we are checking, but why we expect it.

But here a fairly simple check is shown, and if you need to compare a pair of arrays with data in different order? What message should I write here? For this, I advise you to use the framework AssertJ. The link contains many simple and clear examples of use, after which you will want to use this framework! AssertJ allows you to think less about writing a message in the event of an error, and also to check a bunch in just one line, saving space. For example check:

Will give us a wonderful error message:

And everything is clear - what happened and for what reason! You can go and correct mistakes.
And once again - Adequate messages in error tests save time and nerves of those who will disassemble these tests. Perhaps it will be you yourself in a year.

6. Clean up trash (no, this is not about launching a GarbageCollector). Created a file, made an entry in the database or pulled the user creation pen? Do not be lazy and clean up after a test. Files are accumulating, the base is cluttered with a bunch of garbage and crowds of fake users appear in the system. Try to keep clean not only your workplace, but also your working environment. UPD As correctly indicated in the comments, this item applies only to integration testing.

7. Verify that the test runs somewhere else besides your local machine . If you have a CI server or some other place where you run the tests, check that the test has started there. For example, tests on a CI server are run from a specific package, and you put yours in another package. Or tests are run by a specific name, for example * UTest , and you called your class TestUid . Or tests are run in groups, and you forgot to put a certain group for your test. Or ... You can come up with many cases where the newly written test never starts up somewhere other than your local machine. And then the benefits of it are not so much!

The result was a small list of good tone rules when writing Unit Tests. I hope this article will help a little more to raise the culture of tests and testing in your team. If you have something to add to my list, welcome to the comments.

Source: https://habr.com/ru/post/337188/


All Articles