# Testing
To develop a robust package, it is important to have test coverage for the provided code. Not only to confirm proper behavior of the existing code, but also to verify everything still works whenever new functionality is added. This ensures our package can be refactored with confidence at a later stage.
Tests also allow other developers to understand how certain features of your package are to be used, and gives them confidence about the reliability of your package.
# Installing PHPUnit
There are many options to test behaviour in PHP, however we'll stay close to Laravel's defaults which uses the excellent tool PHPunit.
Install PHPUnit as a dev-dependency in our package:
composer require --dev phpunit/phpunit
Note: you might need to install a specific version if you’re developing a package for an older version of Laravel.
To configure PHPUnit, create a phpunit.xml
file in the root directory of the package.
Then, copy the following template to use an in-memory sqlite database and enable colorful reporting.
phpunit.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
>
<coverage>
<include>
<directory suffix=".php">src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<php>
<env name="DB_CONNECTION" value="testing"/>
<env name="APP_KEY" value="base64:2fl+Ktvkfl+Fuz4Qp/A75G2RTiWVA/ZoKZvp6fiiM10="/>
</php>
</phpunit>
Note that a dummy APP_KEY
is mentioned in the example above, in case your test suite uses Laravel's encrypter (opens new window). For most cases, the dummy value will be fine. However, you are free to either change this value to reflect an actual app key (of your Laravel application) or leave it off entirely if your test suite does not interact with the encrypter.
# Directory Structure
To accommodate for feature and unit tests, create a tests/
directory with a Unit
and Feature
subdirectory and a base TestCase.php
file. The structure looks as follows:
- tests
- Feature
- Unit
TestCase.php
The TestCase.php
extends \Orchestra\Testbench\TestCase
(see example below) and contains tasks related to setting up our “world” before each test is executed. In the TestCase
class we will implement three important set-up methods:
getPackageProviders()
getEnvironmentSetUp()
setUp()
Let’s look at these methods one by one.
setUp()
You might have already used this method in your own tests. Often it is used when you need a certain model in all following tests. The instantiation of that model can therefore be extracted to a setUp() method which is called before each test. Within the tests, the desired model can be retrieved from the Test class instance variable. When using this method, don’t forget to call the parent setUp() method (and make sure to return void).
getEnvironmentSetUp()
As suggested by Orchestra Testbench: “If you need to add something early in the application bootstrapping process, you could use the getEnvironmentSetUp() method”. Therefore, I suggest it is called before the setUp() method(s).
getPackageProviders()
As the name suggest, we can load our service provider(s) within the getPackageProviders() method. We’ll do that by returning an array containing all providers. For now, we’ll just include the package specific package provider, but imagine that if the package uses an EventServiceProvider, we would also register it here.
In a package, TestCase
will inherit from the Orchestra Testbench TestCase:
// 'tests/TestCase.php'
<?php
namespace JohnDoe\BlogPackage\Tests;
use JohnDoe\BlogPackage\BlogPackageServiceProvider;
class TestCase extends \Orchestra\Testbench\TestCase
{
public function setUp(): void
{
parent::setUp();
// additional setup
}
protected function getPackageProviders($app)
{
return [
BlogPackageServiceProvider::class,
];
}
protected function getEnvironmentSetUp($app)
{
// perform environment setup
}
}
Before we can run the PHPUnit test suite, we first need to map our testing namespace to the appropriate folder in the composer.json file under an “autoload-dev” (psr-4) key:
{
...,
"autoload": {},
"autoload-dev": {
"psr-4": {
"JohnDoe\\BlogPackage\\Tests\\": "tests"
}
}
}
Finally, re-render the autoload file by running composer dump-autoload
.