I recently started working on a project that will rely heavily on running commands on the terminal. It quickly got in my way of doing TDD, so I had to implement some sort of ProcessFake. This article is about how easy that was.
The mental process that I used to write a
Process::fake() was based on the same logic of
Queue::fake(). It’s basically a bridge between your system and some external service.
1- The Process Facade
The Process Facade is extremely simple: it executes a process. It’s a simple wrapper around Symfony Process.
2- A TDD Example
Suppose we want to write a
WebServerController that exposes the ability to restart the Web Server. Following the TDD approach, I would like to write a test like the following:
For the test to pass, we’ll need to write the
ProcessFake class as well as the actual implementation of the
3- The WebServerController
Special attention to
use Facades\App\Process. This is a Real-time Facade. It means that Laravel will generate a Facade on-the-fly for the class. You can read more about it here.
3- The ProcessFake class
To finish the details required on (2), an implement for
ProcessFake capable of asserting that a command was executed.
Don’t forget to register the Route before running your tests:
To recap, an extremely simple wrapper around Symfony Process as a Facade will allow us to execute commands that the application offers. Because we’re using a Real-time Facade, we can swap the implementation with a
Fake for our Feature tests.
One may raise the question: What guarantee that the
Process Facade actually works? A test coverage report can tell that there are no coverage for the actual
Process implementation. A solution for that is to write one simple Integration test.
5- [Bonus] Integration Test
For an integration test, we can write a simple
bash script that can be executed in any Continuous Integration platform (such as TravisCI). For that, we provide the bash file with the test and write a test that runs it.
And the simple bash script
echo 'process output'
For Travis, add execution permission to the script:
script: chmod a+x ./tests/Integration/process.sh && vendor/bin/phpunit --verbose
Feel free to follow me on Medium for more articles like this one.