Unit testing
About the setup
The unit tests are set up to use Pest, with the following utility add-on libraries:
- Patchwork for convenient mocking functions that support class methods
- Phluent for convenient plain-English assertion syntax.
Pest uses PHPUnit under the hood, but provides a syntax similar to JavaScript test runners such as Jest and Playwright.
Some custom utility functions are included in the PestUtils class, which can be found in ./test/unit/PestUtils.php and used in tests by importing the class at the top of your test file:
use Doubleedesign\Comet\TestUtils\PestUtils;
Important
If adding additional utility libraries for unit testing, they should go in the dev dependencies in the project root's composer.json file. All testing configuration should go in the root in the first instance, so it can be shared amongst packages while also helping to keep them lean for distribution.
If adding any testing utilities of your own that are relevant only to a specific package, ensure they are excluded from distribution in that package's composer.json under archive > exclude. See the core package's composer.json for an example.
Writing tests
Naming conventions
- Test classes and files should be in PascalCase with the word
Testappended to the class name. e.g., tests forContainerare inContainerTest.php.
Boilerplate for a new test file
<?php
use Doubleedesign\Comet\Core;
test('some test case description', function() {
ob_start();
$component = new YourComponent([], []);
$component->render();
$output = ob_get_clean();
$dom = new DOMDocument();
@$dom->loadHTML($output);
$component = $dom->getElementsByTagName('div')->item(0);
// assertions
});
Identifying DOM elements using DOMDocument
You can render a component within a test, capturing its HTML using output buffering:
ob_start();
$component = new YourComponent([], []);
$component->render();
$output = ob_get_clean();
Then, you can use the DOMDocument class to parse the HTML and find elements. For example:
$dom = new DOMDocument();
@$dom->loadHTML($output);
$wrapper = $dom->getElementsByTagName('div')->item(0);
In this example, $wrapper will be a DOMElement object representing the first <div> in the rendered HTML.
Warning
$dom->getElementsByTagName() ignores hierarchy. This means that, for example, if you want to get the first two inner divs of a component but they have their own inner divs, dom->getElementsByTagName('div')->item(1) will give you the first child's own first child, not the second child of your component.
A utility function, PestUtils::getElementsByClassName(), is available to get elements by their class name instead of just their tag name.
Running tests
To run a test file from the terminal:
Warning
// TODO: Updated instructions to come
To run all tests in a file in PhpStorm:
- Right-click the test file's tab in the editor or its name in the Project tool window and select
Run FileName.test (Pest). This will use the included Run configuration template unless you configure a custom one.
To run a single test from the gutter icon in PhpStorm:
- ⚠️ // TODO: This is not currently supported because the automatic filtering of the test name is not working. Run the whole file instead as a workaround.
To run all unit tests in PhpStorm:
- A Run configuration has been included for running all tests.
Coverage reporting
You will need Xdebug installed and enabled to generate coverage data and reports. See the PHP setup notes for more information.
A PhpStorm Run Configuration has been included in this repository for running all tests in the core package and generating a HTML coverage report. To see coverage data using the IDE coverage tools, use the "Run with coverage" option. By default, this is located in the top right corner of the PhpStorm window (shown below); you can also find it in the Run menu.
]
Troubleshooting
Logging to the console
print_r and var_dump may not work in unit tests. Instead, you can use:
fwrite(STDERR, 'something to output as an error');
fwrite(STDOUT, 'something to output as a basic message');
Even better, if you are using Laravel Herd you can send output to the Herd Dumps window which is much more powerful, allowing you to directly log entire objects and arrays:
\Symfony\Component\VarDumper\VarDumper::dump($variable);
PhpStorm not detecting Xdebug when using Laravel Herd
If you are trying to use Xdebug for unit test code coverage and nothing has triggered Herd's automatic Xdebug detection, you can enable it manually:
- Ensure the PHP version the default interpreter in PhpStorm (found in
Settings > PHP)is set to is the same as the one currently set as the global version in Herd. In the Herd dashboard, underActive Servicesit should also say that version is active with debugging - e.g.,PHP 8.4 (debug) - Back in PhpStorm >
Settings > PHP > CLI Interpreter, click the 3 dot button to go into the interpreter details and click theReload PHPInfobutton - If it's still not picking up Xdebug, try putting the path to the extension in the
Additionalsection. This will be something likeC:\Users\YOUR_USERNAME\.config\herd\bin\xdebug\xdebug-8.4.dll. Click the reload button again, and it should pick it up if you have the file path correct. - In
Settings > PHP > PHP Runtime taband click "sync extensions with interpreter".
Below is an example of the CLI interpreter settings using this method:

Try running the unit tests with coverage again. If using the PhpStorm run configuration for Pest, select "Run [test config] with coverage" as shown below:

If it works, the Coverage tool window should populate when the tests have finished (and coverage data should be shown in the Project tool window and in the files themselves until you close the active suite in the Coverage tool window).
Below is an example of the test run output and the coverage tool window.
[
