How a Culture of Testing can assure your application's quality
Tags: php, testing, culture, selfimprovement
Published: 2020-04-06 22:27:56

How many times you needed to implement a quick fix right after doing a deploy, errors created by a programming mistake or by an unforeseen scenario, or yet a little mistake that could be caught by another programmer in a code review preventing uploading bad code to production.

The culture of testing is still shortly diffused at Brazilian companies that are applying PHP language in its core business leading to a poor quality code and creating a stigma of second class programming language. However, for those with good background, is very clear that PHP language offers all necessary resources to get the job done, and in the end the main responsible for not taking advantage of fully resources are ourselves, and this can happened by unfamiliarity or little skill.

More recently, the PHP language has been received tons of changes about performance and functionalities, becoming an even more friendly language to newcomers and easy to teach, keeping it as one of the preferred entry level programming languages because developers adopt it without having a solid formation by skipping very important phases to reach a monthly salary of 5 digits, and one of those important phases is simply the one that could guarantee his/her job in the end of the month: The Tests.

The fact of a test being existent will not guarantee that your application will run perfectly just as planned, it is exactly the opposite, they will give you a false safety sensation in each deploy made, and the only way to mitigate the risks is by maturing the whole culture of testing of your application, what makes necessary the involvement of the whole project team and so, everybody should have a commitment with the tests.

The most important element to develop this culture of testing is called collaboration, with a lot of humble among developers, by doing code reviews very well elaborated by reviewers and with great acceptance from the reviewed ones. First of all, when we implement an application we should keep in mind that it does not belong to us, but in fact it has been developed to everyone else. This kind of thinking will impact directly the way we write our code. Other important elements to be considered are in depth knowledge about SOLID, Design Patterns, Clean Code, Data Structure among others. These knowledge are truly help because they work as universal communication players for discussion and to make decisions. Remember, the reviewer commonly will not know the business rules implemented in the code, but he/she should be able to distinguish what your code is intended to do.

With this in mind we have some questions that we should constantly ask to ourselves. Am I able to change my application without having a change in its behavior? Do I know which is its expected behavior? Will a new programmer understand which is the expected behavior? Fortunately we have good ways to assure those kind of behaviours by implementing tests. In most cases we can start with Exploratory Tests just from the beginning, but they must be complemented with more assertive tests such as Unit Tests followed by Integration Tests.

## Unit Tests

They are the minor part of your application that you can test and it is this part you are supposed to use your skills about SOLID and Clean Code, fragmenting your application in a best possible level, shortening the Ciclomatic Complexity and making its functions more deterministic. In other words, every time the application receives same entries it will produce the same results. Let's take a look in the sampling function down below, it does not return the same result making the test being impossible.

{% gist https://gist.github.com/yurivecchi/82d21e385c57f383719b4abb3c65e750 %}

However with a small adjustment it becomes testable and so we augmented the tests coverage.

{% gist https://gist.github.com/yurivecchi/d4b788b4227bd14a9f867ea442d4413f %}

You probably have realised that if we do not send the timestamp as an argument, it will never be possible testing the result.

{% gist https://gist.github.com/yurivecchi/ab97169ef5dbc064a2c07b7325e772e8 %}


## Integration Tests

Integration tests are commonly applied over external services, those could be an external API for collecting exchange rates or either an internal package working as subsystem for a core project at the same company, it really makes no difference from the main point of view. What really matters is the fact if your team has no access for making changes in those external services the task of creating tests for those services are much more complex to be applied because the results coming from the external services can change at anytime, and what we can do is get ready for the worst and hope for the best.

{% gist https://gist.github.com/yurivecchi/87589df9b00484c41a4720f2b3b07973 %}

Here we have once more another non deterministic function, but this time we just cannot isolate the HTTP client because the returned result is completely out of our control.

{% gist https://gist.github.com/yurivecchi/cfa65c189afa3bebc6d5be16b462e3f5 %}

So in this kind of scenario what we can do is making a usage of a technique known as "Mock" which allow us to control the returned results by simulating the external behavior. That way we can safely assure those returned results, and fortunately Guzzle library already brings this functionality right out of the box.

{% gist https://gist.github.com/yurivecchi/e7f73249840654fac88cd83d71d22ec3 %}

## Code Review

Even if your test coverage is about 100% of your code, it is a fact that you still can find bad code written or business rules not very well clarified among other singularities. For all these kind of issues there is nothing better than getting a code revision from another dev, which will have another perspective about the implemented solutions and still shield the good practices. In this process is it imperative that all team members, both reviewers and reviewed, are fully of empathy. It is healthy to understand that all members are in a situation of constant learning and, although all team members are high tech devs, none of us is God and cannot have omniscience to dictate which is wrong or right.

As a reviewer the most important thing is pointing errors in a very transparent manner providing as many details as possible, with tons of patience because it is very common that a dev being reviewed thinks the only possible solution it is his solution avoiding any others suggestions.

In the other hand, for the reviewed it is good to keep his/her mind opened to accept new ideas for resolving the same problem, even if this means to rewrite all the code from scratch. It is also important to take in consideration that the reviewer does not make comments or ask changes for personal reasons, but the real motivation is because both of them are the responsible for keeping the application running in a best possible way.

## Summary

At EBANX we have a very strong Testing Culture and this is taken very seriously, so we promote Clean Code sessions weekly to improve even more our skills set, we incentive code reviews by more than one reviewer and even sessions with small teams to exchange ideas about solutions already available, we have a huge unit test base running to assure our automated deploys can really work on CI mode. In every single deploy the whole base of unit tests will run to assure the changes implemented will not break code already in production. And last but not least, we value the attention and respect from all teams involved in this process.

A culture of testing is much more than simply delegate the responsibility about your code to another person, to write a very well clean code, to have a 100% of test coverage or being prepared for a chaos testing and having a resilient application. Actually the testing culture works going from learning with our own mistakes up to accepting new ideas. It is about improving ourselves as devs and guarantee a nice sleeping tight night to all those that are dependent on your application running without flaws. This is just a little bit of the acquired experience from passing by years, and each one of you can identify, partially or completely, that it pays off to keep working in this amazing and dynamic profession that coding is.

 #TAMOJUNTO #EBANXLIFE #DEVSHIELD

Contributors: [João Pedro L.](https://www.linkedin.com/in/joaorlima/), [Jorge Carboni](https://www.linkedin.com/in/jhcarboni/), [Leonardo Strozzi](https://www.linkedin.com/in/leonardo-strozzi/), [Lucas Maldaner](https://www.linkedin.com/in/lucas-maldaner-59993a90/), [Marcelino Janing](https://www.linkedin.com/in/marcelinojaning/) e [Yuri Vecchi](https://www.linkedin.com/in/yurivecchi/)

References:

[https://blog.cleancoder.com/uncle-bob/2014/11/15/WeRuleTheWorld.html](https://blog.cleancoder.com/uncle-bob/2014/11/15/WeRuleTheWorld.html)

[https://en.wikipedia.org/wiki/Cyclomatic_complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity)

[https://en.wikipedia.org/wiki/Deterministic_algorithm](https://en.wikipedia.org/wiki/Deterministic_algorithm)

[https://grumpy-learning.com](https://grumpy-learning.com/)

[https://martinfowler.com/articles/practical-test-pyramid.html](https://martinfowler.com/articles/practical-test-pyramid.html)

[http://docs.guzzlephp.org/en/stable/testing.html](http://docs.guzzlephp.org/en/stable/testing.html)

[https://phpunit.de/getting-started/phpunit-9.html](https://phpunit.de/getting-started/phpunit-9.html)

[https://en.wikipedia.org/wiki/Chaos_engineering](https://en.wikipedia.org/wiki/Chaos_engineering)