Writing tests can be boring and lazy. But we promise, cover your plugin with tests for quality - we have covered you with the complete facility and configuration.
Follow this best practices to write good and maintainable tests:
- Writing Great Unit Tests: Best and Worst Practices
- The Front-End Test Pyramid: How to Rethink Your Testing
- Introduction to Front-End unit testing
- A guide to unit testing in JavaScript
- You Still Don’t Know How to Do Unit Testing (and Your Secret is Safe with Me)
- Top 5 Cucumber Best Practices
Unit- and snapshot testing
Each packages and plugins comes with a predefined and bullet-proof TypeScript implementation of Jest. Simply navigate to your package or plugin and run yarn test:jest. Test files are located in {packages,plugins}/*/test/jest.
If you have a look at the jest.setup.js file you will notice an inclusion of enzyme. Enzyme is a JavaScript library for React testing utilities - and is preinstalled ad configured in all your future packages.
Pro tip: If you write Jest tests you can start watching test files with yarn jest --watch.
Unit testing
Each packages and plugins comes with a predefined and bullet-proof implementation of PHPUnit. Simply navigate to your package or plugin and run yarn test:phpunit. Test files are located in {packages,plugins}/*/test/phpunit.
Unfortunately PHPUnit is not as handy as Jest, so we need to rely on further tools:
- WP_Mock is a WordPress API Mocking framework
- WordPress Stubs is needed to mock WordPress API functions and classes - brings also the advantage of VSCode autocompletion for WordPress resources
- Mockery is the player in PHPUnit testing frameworks and provides a lot of useful functionality to mock your source code in tests
- Patchwork is an awesome tool to mock PHP internal functions as this is not possible by default
The boilerplate provides a TestCaseUtils trait in common/phpunit.base.php file. If you use that trait in your Test classes you can abstract util functionalities. You will find a predefined expectCallbacksReached method allowing you to expect a given callback is reached - it plays well with redefine (Patchwork):
<?php
declare(strict_types=1);
namespace MatthiasWeb\Utils\Test;
use TestCaseUtils;
use WP_Mock\Tools\TestCase;
use function Patchwork\redefine;
final class MyTest extends TestCase
{
use TestCaseUtils;
public function testErrorLogWrites()
{
$this->expectCallbacksReached(['errorLog']);
redefine('error_log', function ($callback) {
$this->addCallbackReached('errorLog');
});
error_log("Something");
$this->assertCallbacksReached();
}
}Pro tip: If you write PHPUnit tests you can focus on single tests with yarn phpunit --filter testErrorLogWrites$.
For both Jest and PHPUnit you can collect coverage information, for this refer to yarn test:{jest|phpunit}:coverage. If you commit to GitLab repository and start a merge request you will notice a Code coverage percent right to your merge request (as you can see here).
Also, codecov.io is fully implemented if you just add an environment variable CODECOV_TOKEN. After you have setup Codecov you will get code coverage reports in your GitLab repository merge requests.
{% hint style="info" %} Jest and PHPUnit tests coming with the boilerplate does not covered example implementations as they are removed the most time after plugin creation. {% endhint %}
With coverage reports you will hear also about Coverage threshold. It means, if you do not reach a given percentage of coverage the pipeline will fail and you are not able to merge. The thresholds are configured in {plugins,packages}/*/package.json#phpunit-coverage-threshold and common/jest.base.js#coverageThreshold. The predefined threshold is 80.
{% hint style="warning" %}
If you want to locally collect coverage reports for your PHPUnit tests (yarn test:phpunit:coverage) you need to install XDebug.
{% endhint %}
Integration- and End-to-end testing for plugins
E2E are tests which runs directly in a (headless) browser and simulates a real user. The boilerplate comes with Cypress - currently the best E2E solution we know - together with Cucumber (a Gherkin syntax implementation for Cypress).
You can find the cypress related files (user interactions) in plugins/your-plugin/test/cypress/. The example implementation simply logs into WordPress and checks if the Hello World REST API endpoint is available, and adds a Todo item. When opening the folder you will notice the following important abstraction:
- 📁
integration- 📄
adminPage.featureDescribing your.featurefiles in Gherkin syntax
- 📄
- 📁
step-definitionsRepresents your.featureimplementations- 📁
adminPage- 📄
adminPage.tsExample E2E test for the WordPress admin page - 📄
AdminPageObject.tsAn page object describes a single page and exposes static methods. Generally you maintain all your "CSS" selectors there
- 📄
- 📁
common- 📄
common.tsShareable expressions you can use in your.featurefiles
- 📄
- 📁
With GitLab CI, Cypress brings a lot of cool features to you: Do E2E tests for each commit in a complete fresh WordPress instance and make a video if something goes wrong. Prerequisite is an own GitLab runner.
Pro tip: If you write E2E tests you can focus on single features e. g. with yarn cypress-tags run -e TAGS='@only'. Refer to Running tagged tests.
{% hint style="info" %}
Do not add configurations to cypress.josn file directly. Open plugins/your-plugin/test/cypress/plugins/index.js and have a look at the applyConfig function.
{% endhint %}