Article series Test: Unit, Functional, Coverage

As a developer, you should always be able to rely on the fact that the code you write works as it should and that it has no side effects on older, existing functions. There are automatic tests for this purpose. You can read about how my team at punkt.de uses them in the series of articles on tests.

Es gibt keine Probleme. Nur Herausforderungen.

Christian Keuerleber
Frontend Usability ist sein Metier: mit SCSS und modernem JavaScript macht er jede Webanwendung fluffig
Reading duration: approx. 3 Minutes

The first part of the series was about checking that our code always has the same style, is used cleanly and that third-party libraries are up-to-date. Now we want to check that the code actually fulfills the function it is supposed to.

Unit tests - small but powerful

The first step is unit tests, which we write for the PHP code in the backend in particular. The tests themselves are implemented with the phpUnit tool.

The idea is to write code that calls individual methods of a class that you want to test and checks that the correct result is always output if the arguments are filled accordingly.

A small example test for a simple validator:

There are a few small ideas for unit tests:

  1. You test the "public interface" of a class: Normally, you only want to test the methods that are actually called from the outside, as these ultimately reflect the functionality
  2. Dependencies - especially foreign code - are mocked: Since you want to test exactly one function and not a large function tree (with code that you have no control over), you tell phpUnit "do not call the original dependency, but always return X at this point"
  3. AAA - Arrange, Act, Assert: A test is easiest to understand if you first prepare everything (Arrange), then execute everything (Act) and finally check whether the results were correct (Assert)
  4. No logic in tests: The logic you test is within the tested methods. If you write too much logic within a test, then you need a test for the test, and so you have too little profit

Of course, there are exceptions to these ideas; for example, years ago we had a test in the team that tested exactly one protected method in a class, as this was the core of the class and all public methods only called this protected method. This saved us testing effort. You can also mock too much and, for example, ensure that you no longer test real code, but only the mocks. These are pitfalls that you have to check again and again and that become relevant with every new test.

With unit tests, we now know that our puzzle pieces in the code work correctly, now we have to check that they are also put together correctly.

Functional tests - the sum of the small parts

In the unit tests, only a single code point is called. We now want to know that the code points work correctly together with the backend framework used (in our case TYPO3 Extbase) in the application logic. For this purpose, we write functional tests according to the corresponding TYPO3 documentation.

By calling the tests within a TYPO3 context, we ensure that the "outside" is initialized correctly. We can then write tests that have access to a (partially generated) database - in our case we are testing an importer, for example.

We prepare a CSV file, call the import method within the test and can then verify in the database that the rows have exactly the status we expect - again we see AAA (Arrange, Act, Assert). Importers are just one example here, you can theoretically also call scheduler tasks, controller actions, middlewares and others.

We know what we are testing - but what exactly are we testing?

One topic that is not yet implemented in our team, but will be in the future, is the recording of code coverage. You can configure in phpUnit which source code files are theoretically part of the test environment, and phpUnit then records for these files which methods, lines of code and the like are actually called within the tests.

From this you can then create a list in which you can see, for example, whether you have developed paths in a complex method that are not tested, or whether there are untested classes. A statistic is also created which shows the percentage of tested code.

Outlook

In the first article we looked at the quality of the code, in this part we looked at the functions within the php classes. In the next part of our series, we will look at how we test parts of our actual application.

Agile testing and process know-how for your team:

Whether you are an agency, an industrial company or an independent development team: if you want to establish or further develop agile testing processes, we will support you with our expertise - whether through practice-oriented workshops or direct, project-related collaboration. We support you from the introduction of agile testing methods and the optimization of existing processes through to the development and implementation of individual testing strategies. Feel free to contact us to raise your quality assurance and development processes to a new level together!

Share:

More articles

while(problem){ this->makeSolution()}
Ursula Klinger, Entwicklung / Scrum Masterin at punkt.de
Working at punkt.de