Press "Enter" to skip to content

FIRST – Principles Of Tests

Guide through the FIRST principles with a few general thoughts about them taken from my own experience as a software engineer.

FIRST is an acronym representing a set of rules that can help us write better tests. I have always believed that this concept should be more popular because of how helpful it may be.

That is why today I want to give you a more detailed explanation of these principles and why it may be beneficial for you and your team to stick to them.

What is FIRST ?

It is an acronym representing a set of rules with similar purpose as SOLID. However FIRST is applied to tests instead of object oriented programming.

Originally proposed by Robert. C. Martin in his book “Clean Code” to help us software engineers make the complex task of writing tests easier. By presenting a set of rules which we can follow when writing out tests.

Originally aimed to increase the quality of unit tests but, in my opinion, can be considered useful for any type of tests.

Let’s explain it letter by letter

FIRST Acronym Breakdown

F — Fast

Tests should be as fast as possible. The faster the tests, the more willing we are to run them and, by extension, the more profitable they are.

Execution time is especially important for unit tests which should be executed by every member of your team at least one time per each task they do (before committing changes to check if nothing got unintentionally broken down).

Tests are also the backbone (at least they should be) of all CI processes and nobody wants to wait a long time for CI to finish verifying our pull request.

In my opinion the execution of unit tests should not take more than a few seconds even for more complex systems with a large number, like a thousand, of unit tests. A longer execution time may indicate some issues with your code base.

Of course, an execution time of 10 or 15 minutes is something absolutely wrong and you can be sure that there are some serious problems with your production and/or test code.

On the other hand, more complex algorithms like sorting, especially on large data sets, are a completely understandable exception from this rule. Additionally, for very huge sets of unit tests — like hundreds of thousands or millions — execution time should not be a primary concern.

What is more, other types of tests may require a more complex setup and, by extension, take more time to execute.

Keep in mind that it may be profitable for you and your team to stop for a moment and think how you can make your tests faster without losing the assurance they give.

I — Isolated

Tests should not depend on one another — it is as simple as that. Each test should do any setup required to be executed correctly and clear any context which it used. It is a very good and useful rule for all types of tests and probably the most crucial one out of all five.

Its breaking may result in a large number of false positive or false negative tests with various results depending on the order of running tests. It is an easy way to make your tests lose their worth and do more harm than good.

The rule is quite easy to follow for unit tests but harder for integration or end to end tests — here concepts like fixtures may come in handy.

For security or performance tests this rule should not be taken into consideration, sometimes it even ought to be broken. As more complex performance issues or security vulnerabilities may occur only in very specific scenarios.

R — Repeatable

Tests should be able to run on every environment and, what is more important, their results should also be the same on each of them.

Tests whose results differ from environment to environment cannot bring any good to your team. Additionally, such tests can lead to any number of curious or even funny situations (or tragic ones if you prefer).

I believe that no one wants to see that during pre-prod or prod deployment all tests included in your CD process failed. While a few stages earlier during deployment to dev every one of them passed and everything was green. Especially, when it is Friday and all you want is to go home after pressing the deploy button.

Of course, performance or security tests on a software engineer’s local machine will give totally different results than one done on a pre-prod environment.

S — Self-Validating

Each of your tests should be able to auto detect if it passed or not.

If you are forced to do any type of manual comparisons to check if a test passed or failed then, the number of failed or passed tests may depend on various reasons and thus be completely random. Not to mention all the costs related to such an approach.

In the case of performance or security tests you can automate them to be able to easily verify if your application meets requirements or not.

T — Timely/Thorough

Robert. C. Martin included, explained this letter as Timely. He stated that tests should be written in correct time — for TDD it means while writing a production code.

Such an attitude should force you to write a cleaner and more testable code. Additionally, TDD enthusiasts claim that writing tests after your production code can lead to a more dirty and less testable code. It may bring some benefits for the unit tests but may not be so good for other test types.

That is one of the reasons why I, personally, prefer the second explanation of this letter — Thorough. It means that when we test a method, we should cover not only the execution of happy paths but also possible errors and negative paths.

It helps make our tests more meaningful, complete and give us a better understanding of more complex parts of our code. Naturally, there is no big deal in following both these two explanations together and combining their advantages.

With the whole acronym explained it is time to sum this whole thing up and complete today’s reading.

Summing up

Every programming paradigm has its own unique sets of rules which was created to help us — software engineers — build more fault tolerant and more maintainable systems. FIRST is their counterpart which you can follow while writing your tests.

It is independent from the programming style you are using and you may apply these principles for tests written in any language and for any type of code.

I hope that reading this article will give you some useful advice in writing your tests which will make your tests great again.

Thank you for your time.

Comments are closed.