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.

Background

The mental process that I used to write a Process::fake() was based on the same logic of Mail::fake() , Storage::fake() and 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 Controller .

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:

Route::post('/webserver/restart', 'WebServerController@restart');

4- Conclusion

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

#!/bin/bash

echo 'process output'

For Travis, add execution permission to the script:

script: chmod a+x ./tests/Integration/process.sh && vendor/bin/phpunit --verbose

Done!

Feel free to follow me on Medium for more articles like this one.