Start Small (but start somewhere) namespace PHPUnit_Demo\Tests; use PHPUnit\Framework\TestCase; use PHPUnit_Demo\Foo; class FooTest extends TestCase { public function testStripQuotes() { $result = Foo::stripQuotes('"text"'); $this->assertEquals('text', $result); } }
Use the Right Assertion namespace PHPUnit_Demo\Tests; use PHPUnit\Framework\TestCase; use PHPUnit_Demo\Foo; class FooTest extends TestCase { public function testStripQuotes() { $result = Foo::stripQuotes('"text"'); $this->assertEquals('text', $result); $this->assertSame('text', $result); } }
Constraints and Roadblocks » [OS] Supporting PHP 5.6 + 7.0 still required » Plugin tests often extend WP integration test suite » PHPUnit < 8.5/9.3 not compatible with PHP 8.0 - Mocking - @runInSeparateProcess » PHPUnit 7 Phar will not run on PHP 8.0 » Committed composer.lock file
Solution WP Core: "autoload-dev": { "files": [ "tests/includes/MockObject/Builder/NamespaceMatch.php", "tests/includes/MockObject/Builder/ParametersMatch.php", "tests/includes/MockObject/InvocationMocker.php", "tests/includes/MockObject/MockMethod.php" ], "exclude-from-classmap": [ "vendor/phpunit/…/MockObject/Builder/NamespaceMatch.php", "vendor/phpunit/…/MockObject/Builder/ParametersMatch.php", "vendor/phpunit/…/MockObject/InvocationMocker.php", "vendor/phpunit/…/MockObject/MockMethod.php" ] }, ▪ Composer, not phar ▪ Lock at PHPUnit 7.5 ▪ Downgrade to PHPUnit 5 in CI for PHP 5.6, 7.0 ▪ Use MockObject classes from PHPUnit 9.3 ▪ Separate process => separate group
Implementing PHPUnit Polyfills What you get: ▪ Polyfills via traits for all new assertions and expectations in PHPUnit ▪ Helper to work round removal of assertAttribute*() methods ▪ An cross-version compatible abstract base TestCase (to get round void) which includes all polyfills ▪ A cross-version compatible TestListenerImplementation
Implementing PHPUnit Polyfills use PHPUnit\Framework\TestCase; use Yoast\PHPUnitPolyfills\TestCases\TestCase; class MyTest extends TestCase { protected function setUp() { protected function set_up() { parent::setUp(); parent::set_up(); // Set up function mocks which need to be // available for all tests in this class. } }
Implementing WP Test Utils for BrainMonkey tests What you get: ▪ PHPUnit Polyfills ▪ BrainMonkey and Mockery set up and teardown ▪ Mockery tests not marked as risky ▪ Choice between BrainMonkey or opaque escape/translation stubs ▪ expectOutputContains() helper ▪ [YoastTestCase] Additional function stubs
Implementing WP Test Utils for BrainMonkey Based Tests use PHPUnit\Framework\TestCase; use Yoast\WPTestUtils\BrainMonkey\[Yoast]TestCase; class MyTest extends TestCase { protected function setUp() { protected function set_up() { parent::setUp(); parent::set_up(); // Set up function mocks which need to be // available for all tests in this class. } }
Implementing WP Test Utils for WP Integration tests What you get: ▪ PHPUnit Polyfills ▪ Access to all WP native test utilities ▪ expectOutputContains() helper ▪ Bootstrap utilities
Implementing WP Test Utils for WP Integration Based Tests use WP_UnitTestCase; use Yoast\WPTestUtils\WPIntegration\TestCase; class MyTest extends WP_UnitTestCase { class MyTest extends TestCase { protected function setUp() { parent::setUp(); // Set up function mocks which need to be // available for all tests in this class. } }
Further Reading ▪ The Grumpy Programmer's Guide to Testing PHP Applications https://grumpy-learning.com/ ▪ Your Mocks Won't Save You! https://24daysindecember.net/2020/12/08/your-mocks-wont-save-you/ ▪ My Top 10 PHPUnit Tips & Tricks https://speakerdeck.com/jrf/my-top-10-phpunit-tips-and-tricks-e6ea54ce- 2515-4ea9-aacf-9bf7ab3b3141 ▪ PHPUnit Documentation https://phpunit.readthedocs.io/ ▪ Path Coverage in PHPUnit https://doug.codes/php-code-coverage