Learn how to write and run JavaScript, PHP, and end-to-end tests for WordPress Gutenberg
Gutenberg contains both PHP and JavaScript code, and encourages testing for both. This guide covers the testing frameworks, commands, and best practices for contributing tests to the project.
Provide concise examples of how to use a piece of code
Prevent regressions and unintended bugs
Document expected behavior
When writing tests, consider: What behavior(s) are we testing? What errors are likely to occur? Does the test actually test what we think it does? Is it readable for other contributors?
# Run all JavaScript tests with lintingnpm test# Run only unit tests (without linting)npm run test:unit# Run tests in watch modenpm run test:unit:watch# Run specific test filenpm run test:unit path/to/test/file.js# Run tests matching a patternnpm run test:unit -- --testNamePattern="<TestName>"# Run tests in a specific directorynpm run test:unit path/to/test/directory# Update snapshotsnpm run test:unit -- --updateSnapshot
Integration tests run much faster than E2E tests and cover most block UI functionality. Use E2E tests only for interactions requiring a full browser environment (file uploads, drag and drop, etc.).
# Run all PHP tests with lintingnpm run test:php# Run PHP tests in watch modenpm run test:php:watch# Run all PHP tests (using composer)composer test# Run only unit tests (without linting)npm run test:unit:php# Run specific test filevendor/bin/phpunit path/to/test/file.php# Run tests in a directoryvendor/bin/phpunit path/to/test/directory/
Gutenberg’s build system automatically prefixes PHP functions with gutenberg_. You must test the built (prefixed) versions of functions, not the source versions.
// phpunit/blocks/my-block-test.phpclass My_Block_Test extends WP_UnitTestCase { public function test_my_function() { // Test the built function (with gutenberg_ prefix) $result = gutenberg_block_core_my_block_render_function( $args ); $this->assertEquals( $expected, $result ); } public function test_my_class() { // Test the built class (with _Gutenberg suffix) $handler = new WP_Example_Block_Handler_Gutenberg(); $result = $handler->process( $input ); $this->assertEquals( $expected, $result ); }}
# Run all E2E testsnpm run test:e2e# Run in watch modenpm run test:e2e:watch# Run with browser visiblenpm run test:e2e -- --headed# Run specific test filenpm run test:e2e -- path/to/test.spec.js# Debug modenpm run test:e2e:debug
# Interactive mode (see browser)npm run test:e2e:watch -- --puppeteer-interactive# Control execution speednpm run test:e2e:watch -- --puppeteer-interactive --puppeteer-slowmo=200# Open devtools automaticallynpm run test:e2e:watch -- --puppeteer-devtools
Run React Native tests on Node without native dev tools:
# Run native mobile testsnpm run test:native# Watch modenpm run test:native:watch# Debug modenpm run test:native:debug# Update snapshotsnpm run test:native:update
Performance tests measure key metrics like editor load time, typing response time, and block selection time:
# Run performance testsnpm run test:performance# Debug performance testsnpm run test:performance:debug# Compare across branches./bin/plugin/cli.js perf trunk v8.1.0 v8.0.0# Use specific test branch./bin/plugin/cli.js perf trunk v8.1.0 --tests-branch add/perf-tests-coverage
Minimize background processes and avoid using your computer during performance testing to reduce external factors affecting results.
npm test # All JS tests with lintingnpm run test:unit # Unit tests onlynpm run test:unit:watch # Unit tests in watch modenpm run test:unit:debug # Unit tests in debug modenpm run test:unit -- --updateSnapshot # Update snapshots
npm run test:php # All PHP tests with lintingnpm run test:php:watch # PHP tests in watch modenpm run test:unit:php # PHP unit tests onlycomposer test # All PHP tests (alternative)vendor/bin/phpunit <file> # Specific test file
npm run test:e2e # All E2E testsnpm run test:e2e:watch # E2E in watch modenpm run test:e2e -- --headed # Run with visible browsernpm run test:e2e:debug # E2E in debug mode