Simple TDD in Laravel package development with 10 steps
Last 2017, I have written an article on how to get you on the ground with test-driven development of TDD. In that article, I have laid down the foundation on how to get your development environment running with PHPUnit.
I am also in my early years doing test-driven development at that time and the unit testing I have discussed is actually integration tests because it hits your controller.
In this article, I will discuss the same PHPUnit principle but on package development.
Here is the final app: https://github.com/jsdecena/simple-tdd-10-steps once you have finished the whole article.
1. Download the latest Laravel app.
Download the latest Laravel app and install it on your local machine (as of this writing, it is on Laravel 8). Then create a packages
folder inside it.
The packages folder will be the location of all the packages that we will be developing.
2. Setting up your development environment
First, make sure your phpunit.xml is all good.
You can find this on: <laravel>/packages/simple-tdd-10-steps/phpunit.xml
This part is the most important:
Make sure that during testing, your database connection is set to sqlite
and database is :memory:
to run your tests faster.
3. Use the testing helper orchestra/testbench
In your composer.json
file, add this
...
"require-dev": {
"phpunit/phpunit": "^8.5",
"orchestra/testbench": "~3.0"
},
...
We need this package to help us in our package development which will I will show you later. If you want to know more, here’s the documentation.
4. Create your package.
For this tutorial, I will be creating a package named simple-tdd-10-steps
First, on your package, initialize the composer with composer init
to lay out the structure of your package.
Once the composer config is generated, you can now define your psr-4
autoload classes. If you have followed me, this is the before and after of the composer.json file
Before:
After:
Inside your package, add an src
folder and we will create our Service Provider in this location.
5. Define your Service Provider
Your Service Provider will be the heart of your package. This is the connection to the main Laravel app. To know more about the service provider, look it up on Laravel Docs.
We are halfway through! We now have a simple package inside your main Laravel app. You should have now like this:
The config is a simple PHP file.
6. But where are the tests?
If we look back on our composer.json file, we have defined also the location of the test folder.
Now, we just need to create the tests/
folder alongside the src/
folder
We can do it like this:
We can see here the power of the orchestra/testbench. We can set the environment we want in the tests since the config on the main app is not available on your package.
7. Write your simple test
Let’s write a simple test on your package. Create a TimezoneTest that will check the timezone you set in your config will be the correct timezone to use.
Create your test in <laravel-app>/packages/simple-tdd-10-steps/tests/Unit
Inside the package, run this command: vendor/bin/phpunit
The rules in TDD by Uncle Bob
- You are not allowed to write any production code unless it is to make a failing unit test pass.
- You are not allowed to write any more of a unit test than is sufficient to fail, and compilation failures are failures.
- You are not allowed to write any more production code than is sufficient to pass the one failing unit test.
This test fails because the app is getting the default timezone set in the app which is UTC. Now, let’s make it pass by adding the code
/**
* Define environment setup.
*
* @param Application $app
* @return void
*/
protected function getEnvironmentSetUp($app)
{
// Setup default database to use sqlite :memory:
$app['config']
->set(
'simpletdd.timezone',
'America/Los_Angeles'
);
}
This is basically altering the default config values (Asia/Manila) to what you want it to be in the test (America/Los_Angeles). This is the power of orchestra!
Now, it is getting the correct timezone and is now passing!
8. How to use your package in your main app?
Once you have a passing test in your package, you are now able to use this on your main app.
You can now add this to the require block and add the location of the repository just like below:
9. Run root composer
Do a composer install
on the root Laravel application to make your package available to your main app. It will symlink the package into the vendor folder and it will be as if you have installed this via Packagist.
Whenever you reference the classes of your package in the main app, you will be able to use the namespace like: Jsdecena\SimpleTdd\TimezoneUtil
which is a different namespace from the main app like App\User
10. Enjoy!
Next will be publishing your package into the Packagist so that anyone can use your package and contribute to the open-source community! Well done!