Integration tests in Magento 2
Magento 2 is coming into the eCommerce world
and some modern programming principles are coming with it as well. One of those principles is automated testing.
Automated testing in software development is a process of creating and executing certain pre-written scripts that are used to compare predicted and actual results of the code that is under test. The purpose of automated testing is to provide a reliable means to verify that the code that we created actually does what we expect it to do.
We can divide such tests into three groups:
The purpose of unit tests is to, as the name suggests, test the smallest units of code - most usually the “methods” and to verify that they behave as expected. Because unit tests should cover only the smallest pieces of code these tests should be done in isolation so that the other parts of the system don’t interfere with our test results. Unit tests have one major disadvantage: even if the units work well in isolation, you don’t know if they work well together. To reduce this risk you should also have functional or integration tests, in some cases both.
Functional tests, also known as end to end tests, test the end result, by simulating clicks in browser and asserting the output html. They care about the results that our code produces rather than the code itself. There are some tools such as Selenium web server that help us achieve this by emulating browser behaviour.
Integration tests are somewhere in between. The purpose of integration tests is to test if the entire group of code (in our case module) works as expected. Integration tests should also check if our module works well with other modules.
Practising all these three types of tests in an application is a really good idea. Correct balance between these tests is also an important aspect to consider. This testing pyramid image gives us an idea of how many of each type we should have, width represents the suggested number of tests:
Integration tests and Magento 2
The good news about Magento 2 is that it comes with all the three types of tests that we mentioned. There are also other kinds of tests that Magento 2 provides such as performance tests and static code analysis tests, but that would be out of the scope of this article.
Let’s go through some aspects of integration tests in Magento 2:
New data in database on every run
Unit tests are supposed to run in isolation, therefore they are not supposed to interact with anything external such as database or some web service. Dummy objects such as mocks and stubs are used to mimic that external behaviour.
Integration tests are allowed to interact with the database, as sometimes it is necessary to check if data is correctly stored, for example. Therefore in Magento 2 integration tests database tables are recreated on every run, which gives us a clean environment to test in. That also brings us to the next important point.
Fixtures are predefined sets of values which give us the ability to populate the database with some data so that we can see if our code performs as we expected. A fixture could be a product that we need to create before running our test, or a quote object populated with some values. In Magento 2, fixtures are added with annotations, this lets us easily inject the desired behaviour.
It is also possible to change configuration values per test using fixtures which is useful in many situations.
More real objects instead of mocks
When using integration tests it is not necessary to always run every test in isolation. Therefore we will have less mocks and more real objects so that we could check their real behaviour.
If we integration test our Checkout module for example, a good candidate for a test would be the add to cart operation. While a real add to cart action is more suitable for a functional test, in integration test we could check if the quote object changed state or try to add an out of stock item into our cart.
Unlike unit tests that should run in isolation and check if some specific method returns what is expected, integration test care more about the entire system.
When we talk about integration tests we should also mention some drawbacks:
- They are a lot slower than unit tests because a new database is created on every run,
- Bugs are harder to diagnose because of the larger scope,
- It is not always so easy to find a boundary between something that should be covered in an integration test and something that belongs to a unit test.
Benefits of integration testing
At the start it may seem that writing automated tests in general increases the time required to develop some functionality. I think that it pays off at the end as less time will be spent on possible problems that may come as a result of untested software. It’s also evident that what is built works as expected. Installing third party modules and Magento upgrades will be much easier going forward as it will be easy for merchants to pinpoint unwanted consequences.
I think that integration tests will prove to be very useful in the Magento community. Hopefully there will be less cases where some functionality doesn’t work as expected or when some feature breaks the other. They are also easy to set up in continuous integration environments so they can be run on each deployment.
It’s good to see that our favourite eCommerce platform is adopting modern programming principles. I expect that in Magento 2 there will be many cases where integration tests will play a crucial role.