Different tests are important, while others are not needed.

    Why write tests? When to write them? When not to write them? Habr was and remains indifferent to these and other eternal questions, and more than one Habrovsk citizen spent a sleepless night, coming up with convincing answers to them (so that the opponents finally shut up).

    I decided to take the opponent not by skill, but by number, and so here you have 19 reasons why writing tests is still worth it (in chronological order). So tests
    1. They help to develop the API of the created class. Instead of inventing the interface of a class, you develop it in the process of writing a test.
    2. Help develop application architecture. At a minimum, this is low-level architecture — a way that classes interact with each other. As experience shows, such an architecture, as a rule, turns out to be the most flexible and economical.
    3. Check if a specific piece of code is working right now.
    4. Check if a certain piece of code will work after the changes are made.
    5. Document the functionality of individual classes.
    6. Document system behavior (from the point of view of the user).
    7. I haven’t come up with yet, maybe someone will tell me?

    It is clear that the test is different for the test, and not all tests can bring such great benefits. Let's try to figure it out.

    Do we write tests before or after the code?


    Everything is more or less clear. When we write a test after code, we lose the invaluable opportunity to let tests help us write code. In my opinion, this is the greatest value of tests. However, it is also the most difficult to understand, because here it is required to shut up the internal Architect and let the tests steer.

    The second important point: as experienced people say, tests that are postponed until later, in most cases, remain unwritten.

    Verdict: we write tests after the code only in those cases when you need to quickly cut money, without really worrying about the consequences.

    Which piece of code to test?


    There is no “either-or," but rather a continuous spectrum: from a one-line method to a whole scenario that includes a sequence of user actions. The first extreme is called unit (unit), the second - acceptance (acceptance) testing, and somewhere in the gap are integration (does anyone know a better word?) And functional testing, and everyone understands something different by these terms. Unit testing is much more popular among the people, and when it comes to Test Driven Development, unit tests are meant by default. Firstly, they are much easier to write - in the sense, it requires less code, and secondly, this is due to the fact that developers love to write development tests (about them later).

    Now let's see how such and such tests relate to our list of Good things:

    Unit tests:
    1. They help to develop the API of the created class.
    2. Help develop application architecture.
    3. Check if a specific piece of code is working right now.
    4. Check if a certain piece of code will work after the changes are made.
    5. Document the functionality of individual classes.


    As you can see, there are a huge amount of benefits, it lacks only one (the most important) thing - checking the correct operation of the entire system, or at least some meaningful piece of it. Just as a set of healthy neurons can produce a diseased brain, a set of correctly working classes does not guarantee the normal operation of the system. Even if we test the interaction of classes with each other, a unit test will only give us a guarantee that this class sends certain specific signals to its neighbors. But whether these signals of universal harmony are needed, the unit test will not tell us.

    And here the integration test comes to the rescue. It is harder to write because it is necessary to create a context consisting of several parts, it is more difficult to maintain, because if the test crashes, it takes a long time to figure out which piece of code to fix, so that the test can be raised, and others do not fall. But then we can now be sure that our system is behaving correctly under certain specific conditions.

    Does the integration test help in the design of the application? It is not in itself, it checks a huge piece of code, and by itself this piece can be organized completely ugly. But if we start with the integration test, and then, in the process of refactoring, we add modular tests to individual sections of the code, then this will bring truly countless benefits.

    What should we test in general?


    Most developers will give an obvious and, quite frankly, very blunt, simple-minded answer to this question : we will test classes and their methods. No sooner said than done. For each class that our ingenious chump invented, we start a test class. For example, if we have MyClass, we ingeniously create the MyClassTester class. Further, since we already know for sure that we have the DoSomething method, we start the TestDoSomething method. And, most interestingly, we sleep peacefully after that at night.

    They say that in Visual Studio there is even a team that automatically generates this whole thing.

    If we ask the customer, well, or even for example the tester, then we will have another very obvious answer: we will test the behavior of the system. We have a specification, or user stories there, we take and rewrite them in an executable form. And now this is work for the brain: it is in the process of writing such tests that this sacred process for many present called Test Driven Design begins.

    The first type of test is sometimes called development, and the second - custom. There is a tendency to confuse this division into unit and integration tests. I declare with all responsibility that this is not so. Sometimes you can turn development tests into user tests by simply renaming and rearranging test methods. A typical example is search. We can have one class responsible for selecting data for several parameters. In the case of development tests, we have one test class with a bunch of tests. We divide it into classes by script: search by name, date, etc. We got custom tests. How to write and organize them is not entirely obvious, but the benefits are enormous. In addition to the following, we get a system in which there is no redundant testing. It means,

    So, development tests:
    • They do not help to develop the API of the created class. After all, we have already come up with all the classes and methods.
    • They help to develop the architecture of individual methods and the interaction with other classes.
    • Check if a specific piece of code is working right now.
    • Check if a certain piece of code will work after the changes are made. However, it is not clear whether it works as the system needs with the new requirements.
    • Document the functionality of individual classes. However, more often than not, in order to figure this out, one has to climb into the method code.
    • Do not document system behavior.


    User tests:
    • They help to develop the API of the created class.
    • Help develop application architecture.
    • Check if a specific piece of code is working right now.
    • Check if a certain piece of code will work after the changes are made.
    • They do not document the functionality of individual classes.
    • Document the behavior of the system. At the same time, it is possible to organize these tests so competently that the behavior of the system will be clear based on the name of the test (no need to delve into the code). There are even systems that automatically generate documentation based on the names of the tests.


    That is, if I want to understand what this class does, I will have to look at the code of the class itself. To understand an example of its use, I'll take a look at the code for the development test. But to understand how the system does one or another useful thing, I will look at the user test code.

    Verdict: despite the fact that I have always fiercely ignored development tests, I am ready to assume that in certain situations they can be useful. But I still choose custom ones.

    Final thoughts


    I never came up with anything final, so I leave everything as it is.

    Also popular now: