I have been practising test-driven development (TDD) for quite some time on projects where I was working alone or my own side projects. But when it comes to working with a team, you come up with new and very interesting challenges. I wanted to ensure that everyone runs PHPUnit before they commit code and yes there are chances even I can forget to check. Human errors are possible, right?
I feel this is a perfect situation to take advantage of automation. Running PHPUnit to ensure that all my tests are passing before creating a merge request is important and it will be great if the developers don't need always manually run and then let me know that tests are passing. And, this requirement directed me towards reading up on Continuous Integration (CI).
My company uses Gitlab for almost all software development projects and the CI support on Gitlab is very easy and works so nicely that you won't even have to think about it. Every commit shows a "green" or a "red" icon indicating the test status for that commit and this is also visible for every commit in a merge request.
This saves a lot of my time while doing code review, gives me a lot of confidence in shipping code. But I think the most important thing that I am able to achieve is empowering the developer with a confidence that he can also confidently write a piece of code and would generally come to know if anything goes wrong the moment the tests start to fail. So, let's see how I went about setting up Gitlab with CI and how the flow looks like once you have your tests written already.
So as the first step we need to create a ".gitlab-ci.yml" file and here we will tell Gitlab how to run our tests. What I understand is that Gitlab runs Docker containers which will first clone our code inside that container (this container will have everything which we need to run Laravel and PHPUnit) and run the PHPUnit command using the bin file which is available when we do a composer install of all our composer dependencies (basically it runs "./vendor/bin/phpunit" command along with certain flags).
Below is the YML file code:
So, let's see what is going on inside this YML file. Initially, we do a few declarations like what are the different stages (in my case I wanted only 1), certain environment variables, defining some cache items.
Then, from line 25 we define what happens in our stage "Test". We declare that we need the Mysql service, we define the image required to be pulled and then what scripts we need to run in order for us to be able to execute the tests. Here, you will see I am pulling composer packages, creating the .env file, migrate and seed the database. Once these things are done, I run the tests.
This entire step is done everytime we push a commit to Gitlab. When everything is complete, it will either return a success or a failure. If any test fails, we typically get a failure and Gitlab will take that feedback and mark that commit as green or red.
Below is a screenshot of two screens from one of my project Atlantis where I am using CI and I can see the history of pipelines which were triggered based on the git commits and also a screenshot showing the commit status. By the way, in the screenshot, you will see all the commits in green and that's only because of the urge to get every commit green I have been able to make it muscle memory to run all my tests before making any code commit.
So, this is how I have enabled CI withing my workplace and I and my team members are able to see the advantages of doing this. And the best part - it's just placing this one YML file and the magic starts to happen.