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.feature
Describing your.feature
files in Gherkin syntax
- 📄
- 📁
step-definitions
Represents your.feature
implementations- 📁
adminPage
- 📄
adminPage.ts
Example E2E test for the WordPress admin page - 📄
AdminPageObject.ts
An page object describes a single page and exposes static methods. Generally you maintain all your "CSS" selectors there
- 📄
- 📁
common
- 📄
common.ts
Shareable expressions you can use in your.feature
files
- 📄
- 📁
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 %}