At what point is it best to write tests? In general, there are three approaches:
- Write tests after your code
- Write tests while you're writing your code
- Write tests before the code
In some situations, there isn't exactly much choice, for example, in system testing, when the test simulates user behavior and performs actions in the browser. These tests are written after the code.
In lower-level tests, integration, and unit tests, you can usually choose from the above options. And the “tests after code” approach is probably the least useful. Why?
The process of writing code itself involves constantly running code and making sure that it works. Running is quite fast in the simplest tasks, such as training.
// Easy to run, easy to check that the result is correct
capitalize('hello'); // Hello
In real code, it can take a considerable amount of time, perhaps dozens of minutes, to prepare the data for code testing. On the other hand, the code under tests may do something complex, such as many records in a database or outputting a certain complex structure. Running the code to check it is now an adventure.
// It's hard to prepare data. It is difficult to check the result
// Load goods from SAP into the database
loadGoodsFromSAP();
This is where the “tests before the code” approach comes into play. This phrase confuses many novice developers. How can you write tests before the code has been written? It turns out you can, and it's quite nice.
Suppose we want to write a function that repeats a string passed to it a specified number of times:
repeat('$', 3); // $$$
We know what it takes and what its output should be (luckily there are pure function). Are we already able to write the tests? Of course!
test('repeat', () => {
expect(repeat('$', 3)).toBe('$$$');
});
How long would it take an experienced developer to write such a test? I think 15 seconds, which is how long it took me for the code above. But now you just have to type jest
into the console to check if this code works.
Testing before writing code has another powerful advantage. It forces the programmer to think about the code design and how it will be used before anything else. It's not about how wonderfully they write everything inside. Relevant interfaces are the key to success.
In the development world, the approach in which tests are written before the code is called Test-Driven Development (TDD).
TDD, as conceived by the inventor of this technique, means that the entire process of development consists of a repetitive cycle. The code is tested, it doesn't pass, and then more code is written to pass the test. After that, everything repeats. Thus, step by step, an application is made.
More and more people are starting to talk about this method. This method involves all parts of the code being tested with highly detailed tests. This type of TDD, although it draws attention to the importance of design, focuses on specific functions and classes instead of the whole picture. But there is another form of TDD, where tests for internal parts are rarely written. There's more about this in an article in the supplementary materials.
Hexlet itself is a prime example of tests being written before code. Absolutely all of our practice assignments in all languages have tests and no code :)
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.