Categories
Software Development

Running PHPUnit Tests with WordPress Plugins (easily)

If you are developing plugins for WordPress, one of the pain points I’ve struggled with is getting tests running. In the future, I need to document getting javascript tests running. Today, I’m going to outline the method for running phpunit tests. I will also discuss several problems I encountered along the way.

First: use @wordpress/env

This tool deserves a post all on it’s own but long story short, it allows a quick method to bootstrap a local development environment using docker. After installation it’s available as wp-env or npx wp-env (and I’ll be using the shorter version in this post).

The most basic “working” version of this is a .wp-env.json file in your plugin directory that looks like:

{
	"plugins": [ "." ]
}Code language: JSON / JSON with Comments (json)

Launch the environment with wp-env start. (WordPress is downloaded and stored locally. Next it creates docker-compose file mapping several containers: wordpress, cli, mysql, tests-wordpress, tests-cli, and tests-mysql.

Second: use wp-cli to create the scaffolded plugin-tests

> wp-env run tests-cli wp scaffold plugin-tests $(basename $(pwd))
Success: Created test files.
✔ Ran `wp scaffold plugin-tests sample-plugin` in 'tests-cli'. (in 24s 436ms)Code language: Shell Session (shell)

The above command creates a bunch of files that aren’t technically necessary and you can remove them (e.g. .circleci, bin/install-wp-tests.sh, .phpcs.xml.dist).

By passing the --ci parameter you can change the continuous integration provider. With wp-env you’ll need to add -- --ci=github.

Third: get it running

In theory you should be able to run wp-env run tests-cli phpunit, but that runs in the wrong directory. Solution: pass the current working directory.

> wp-env run tests-cli --env-cwd=wp-content/plugins/sample-plugin phpunit
ℹ Starting 'phpunit' on the tests-cli container.

Error: The PHPUnit Polyfills library is a requirement for running the WP test suite.
If you are trying to run plugin/theme integration tests, make sure the PHPUnit Polyfills library (https://github.com/Yoast/PHPUnit-Polyfills) is available and either load the autoload file of this library in your own test bootstrap before calling the WP Core test bootstrap file; or set the absolute path to the PHPUnit Polyfills library in a "WP_TESTS_PHPUNIT_POLYFILLS_PATH" constant to allow the WP Core bootstrap to load the Polyfills.

If you are trying to run the WP Core tests, make sure to set the "WP_RUN_CORE_TESTS" constant to 1 and run `composer update -W` before running the tests.
Once the dependencies are installed, you can run the tests using the Composer-installed version of PHPUnit or using a PHPUnit phar file, but the dependencies do need to be installed whichever way the tests are run.
✖ Command failed with exit code 1
Command failed with exit code 1Code language: Shell Session (shell)

Whoops, it looks like some libraries are missing. Let’s add them.

composer require --dev yoast/phpunit-polyfillsCode language: JavaScript (javascript)

That installs the library, but also gives us a version of phpunit we need to use to ensure they are loaded. With that slight change we see:

> wp-env run tests-cli --env-cwd=wp-content/plugins/sample-plugin vendor/bin/phpunit
ℹ Starting 'vendor/bin/phpunit' on the tests-cli container.

Installing...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
[03-Oct-2024 18:17:14 UTC] PHP Warning:  Class "PHPUnit\Framework\Error\Deprecated" not found in /wordpress-phpunit/includes/phpunit6/compat.php on line 8
[03-Oct-2024 18:17:14 UTC] PHP Warning:  Class "PHPUnit\Framework\Error\Notice" not found in /wordpress-phpunit/includes/phpunit6/compat.php on line 9
[03-Oct-2024 18:17:14 UTC] PHP Warning:  Class "PHPUnit\Framework\Error\Warning" not found in /wordpress-phpunit/includes/phpunit6/compat.php on line 10
[03-Oct-2024 18:17:14 UTC] PHP Warning:  Class "PHPUnit\Framework\Warning" not found in /wordpress-phpunit/includes/phpunit6/compat.php on line 12
[03-Oct-2024 18:17:14 UTC] PHP Warning:  Class "PHPUnit\Framework\TestListener" not found in /wordpress-phpunit/includes/phpunit6/compat.php on line 15
Not running ajax tests. To execute these, use --group ajax.
Not running ms-files tests. To execute these, use --group ms-files.
Not running external-http tests. To execute these, use --group external-http.
PHPUnit 11.3.6 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.2.24
Configuration: /var/www/html/wp-content/plugins/sample-plugin/phpunit.xml.dist

No tests executed!
✔ Ran `vendor/bin/phpunit` in 'tests-cli'. (in 1s 34ms)Code language: Shell Session (shell)

Why weren’t any tests run?

Because WordPress doesn’t like the latest version of phpunit. Let’s change it with composer require -W --dev phpunit/phpunit ^9.6

> wp-env run tests-cli --env-cwd=wp-content/plugins/sample-plugin vendor/bin/phpunit
ℹ Starting 'vendor/bin/phpunit' on the tests-cli container.

Installing...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
Not running ajax tests. To execute these, use --group ajax.
Not running ms-files tests. To execute these, use --group ms-files.
Not running external-http tests. To execute these, use --group external-http.
PHPUnit 9.6.21 by Sebastian Bergmann and contributors.

No tests executed!
✔ Ran `vendor/bin/phpunit` in 'tests-cli'. (in 1s 32ms)Code language: Shell Session (shell)

Still no tests… 🤔

Oh! the phpunit.xml.dist is excluding the only test. Remove that line:

--- phpunit.xml.dist	2024-10-03 11:28:06.212985211 -0700
+++ 2phpunit.xml.dist	2024-10-03 11:28:39.641072205 -0700
@@ -1,16 +1,15 @@
 <?xml version="1.0"?>
 <phpunit
 	bootstrap="tests/bootstrap.php"
 	backupGlobals="false"
 	colors="true"
 	convertErrorsToExceptions="true"
 	convertNoticesToExceptions="true"
 	convertWarningsToExceptions="true"
 	>
 	<testsuites>
 		<testsuite name="testing">
 			<directory prefix="test-" suffix=".php">./tests/</directory>
-			<exclude>./tests/test-sample.php</exclude>
 		</testsuite>
 	</testsuites>
 </phpunit>Code language: Diff (diff)

And success! 🎉

> wp-env run tests-cli --env-cwd=wp-content/plugins/sample-plugin vendor/bin/phpunit
ℹ Starting 'vendor/bin/phpunit' on the tests-cli container.

Installing...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
Not running ajax tests. To execute these, use --group ajax.
Not running ms-files tests. To execute these, use --group ms-files.
Not running external-http tests. To execute these, use --group external-http.
PHPUnit 9.6.21 by Sebastian Bergmann and contributors.

Test 'SampleTest::test_sample' started
Test 'SampleTest::test_sample' ended


Time: 00:00.021, Memory: 38.50 MB

OK (1 test, 1 assertion)
✔ Ran `vendor/bin/phpunit` in 'tests-cli'. (in 0s 927ms)Code language: Shell Session (shell)

Other investigations/changes

  • phpunit 10 changes the way it finds tests. In the future, the file name and the class will need to agree (e.g. rename file to SampleTest.php and change phpunit.xml.dist to find files like *Test.php).
  • WordPress needs to update its support of phpunit too.
  • If you are using a javascript build process:
    • Add @wordpress/env as a development requirement.
    • Add a script to your package.json to run tests: "test": "wp-env run tests-cli --env-cwd=wp-content/plugins/sample-plugin vendor/bin/phpunit"
    • Now you can just run npm test!
  • Need more investigation about using wp-env in continuous integration environment.

Fin

As of October 3, 2024, these steps worked on getting an up-to-date sample plugin running phpunit tests using wp-env.

Categories
Software Development

MermaidJS & WordPress

I get confused by a lot of words. The combination of complex ideas and large walls of text short-circuit and crash my brain. I’ll have to read and re-read a text-only passage multiple times to understand exactly what’s being described. Speaking presentations exacerbate the issue.

However the adage “A picture is worth a thousand words” definitely applies to me. Given graphical clues demonstrating the principle helps me begin to make connections and jumpstarting my understanding.

graph TD
   start(Explain an idea) -->|with words| understanding
   start --> |with pictures| understanding

One of the tools I’ve found very helpful (if only for myself) is MermaidJS. This software lets you create several different types of charts using a markdown-ish syntax. For instance, the above chart was created with:

graph TD
   start(Explain an idea) -->|with words| understanding
   start --> |with pictures| understandingCode language: JavaScript (javascript)

This grants other benefits in addition to the quicker comprehension. Quick edits to the text automatically recreates the chart without requiring any manual intervention/tweaking to the rest of the diagram.

MermaidJS supports flowcharts, sequence diagrams, class diagrams, state diagrams, ERD (entity-relationship diagrams), Gantt charts, pie charts, requirement diagrams and User Journey diagrams.

On my last post I actually used it to show the sequence of flows between WordPress, WooCommerce and webhooks.

WordPress Plugins

Working at Automattic, all our internal documentation and institutional knowledge is recorded using WordPress (you should really checkout using p2’s — it’s an awesome tool). Using Mermaid in this environment has been fantastic — Mermaid can be supported anywhere you have HTML (and I can be exported to SVG too), but as WordPress is running 40% of the web, this seems like a pretty good place to start.

In fact MermaidJS has a page dedicated to integrations of their software and mention a couple plugins:

  • WordPress Markdown Editor (seems to have been rebranded to WP Githuber-MD — see below)
  • WP-ReliableMD: The page was in a different language than I understand and I made a snap decision to avoid it 😢. Should I revisit this decision?

Here is my un-asked for 2¢ about some different WordPress plugins supporting MermaidJS.

WP Mermaid (and WP Githuber-MD)

These plugins are both created & maintained by Terry Lin. I think they’re both great. They support Gutenberg blocks. They display the Mermaid text. Give them a shot and see if they float your boat.

Personally, I didn’t need the full markdown editor, and WP Mermaid had a couple small annoyances that I couldn’t solve. I submitted a couple PR’s, but decided I could use something a little simpler, which brings me to my own plugin…

MerPress

I can’t take full credit for this plugin. My coworker Michael Pretty actually did most of the work on this iteration and I submitted it to WordPress.org. I’m giving him full-credit. He did an awesome job with it.

A couple features I really like:

  • MerPress keeps the wptexturize functionality. Posts preserve the capability to convert simple characters like quotes and dashes into the nice curly quotes and dashes (e.g. “”, –, —).
  • In the Gutenberg editor, the block is encased in a code block letting you edit the code with a monotype font.

Some features I would like to see:

  • Ability to change the theme site-wide and per block
  • Add other configuration parameters to the block
  • Support 3rd party CDN (something that WP Mermaid already does)

Conclusion

If you learned nothing else, you now know I need pictures in order to comprehend complex concepts. Hopefully it’s also obvious that Mermaid is a neat tool and can be used to quickly share intention and purpose and thoughts without all the words.

graph TD
  ad(all done) --> te(the end)

Please let me know if I’m missing a plugin that I should try or if there is something you would like to see added to MerPress…

Categories
Uncategorized

How I Work :: 2021 Browser Edition

I’ve been surfing the web for almost 30 years and gone through many browsers in that time. I’ve tried configuring them, writing extensions & themes and evaluating them for personal use. In the future I might go more in-depth on my choices, but by way of introduction (to myself, and this site) — here’s a snapshot of how I work with browsers, y rather convoluted way of surfing the Internet.

Chromium Chromium-based browser

Google’s open source browser is ubiquitous. It powers something like 99% of the web (that’s a made-up statistic that may or may not be true). As the engine for many different browsers, this can lead to some interesting trade-offs.

  • It’s by far the most used, so it’s a de facto requirement for any development efforts.
  • I really enjoy Chromium dev-tools.
  • I don’t want to be too deep in the Google eco-system, so if I can avoid Chrome, I will. (Yes, they currently have my email, calendar and maps — but I don’t have to make it easy for them).
  • The less extensions I have to install the better.

For this reason Vivaldi is my chromium browser of choice. It has fantastic tab-management, configuration and even gestures available out of the box in addition to the other tools I need (e.g. profiles, extensions, etc.)

I use a different profile for work, gmail, and personal.

firefox Firefox Developer Edition

My first browser was Netscape Navigator and I have always been rooting for it. When Mozilla spun off of Netscape I tried to use it, but it wasn’t until Phoenix (early version of Firefox) came along that I really loved it. I’ve gone away and returned many times as features have improved or stagnated.

Today, I really enjoy the container feature to sandbox almost every open tab into mini/temporary profiles. And it’s very snappy these days too. Firefox serves as a great daily driver (and is my default browser).

 Finicky

The last browser that I use on a daily basis is Finicky. This is a macos-only application (although there are comparable Windows/Linux options available) to route links to different browsers. If I click on a link in a different application (e.g. slack) it uses a series of filters to decide if it should open the Vivaldi work profile, or send it to Firefox.

Other Browsers

Every so often, I retry different browsers to see if something has changed — if they’re faster or better than what I’m currently using — great! So I have a rotating cast of secondary browsers making guest appearances on my systems. Google Chrome, Chrome Canary, Chromium, Safari, and Brave to name a few. Even other esoteric ones few might have heard of (like Browserosaurus). (Sidenote: I still need to give Edge a closer look, but as it shares the Chromium engine, I haven’t felt a need to kick the tires).

If you have seen a new or interesting browser let me know, there’s always room for another one.