Author Archives: J.D. Grimes

Running Codeception WebDriver Tests For WordPress Plugins on Travis CI

Recently I’ve been exploring creating acceptance tests for my WordPress plugins. I decided that Codeception was the best tool for the job, and WP Browser was a good bootstrap for running WordPress-specific tests. That makes it fairly simple to run WebDriver tests locally using PhantomJS or even a real browser. I also wanted to run my acceptance tests on Travis CI though, and that proved to be a real challenge. After a lot of trial and error I finally got it to work. But rather than trying to tell you all about it, it is much easier just to show you. So I’ve created a demo GitHub repo just for that purpose. Head on over there to check it out and see it in action!

PHPUnit and the WordPress file system API

If you unit test your WordPress projects with PHPUnit, sooner or later you’ll want to test some code that interacts with the filesystem. If you are interacting with the filesystem properly, you’ll be using the $wp_filesystem object.

A few months ago I found myself needing to test some code that created a file using the WordPress filesystem API. I searched for a good solution, and found the information about mocking the filesystem on the PHPUnit website. But after tinkering with vfsStream, I decided it would be easier to build a simple filesystem mocker myself than to integrate vfsStream with the WP Filesystem API. So I did.

The result is the WP Filesystem Mock.

[It] Provides a class that can be used as a mock filesystem, and also a shim for the WordPress filesystem API that uses it. This is useful in unit tests that include simple filesystem operations.

Enjoy!

Unserializing Safely

Avoid object injection with this:

	
    if ( 1 !== preg_match( '~O:\d~', $maybe_dangerous ) ) {
        // All is well, this is safe to unserialize.
    }

For security it is best if you use json_* or something else instead. But if you are working with a project built by someone else and you have no choice, this will keep you from unserializing any objects.

Creating Your Own PHPUnit @requires Annotations

PHPUnit offers a feature that lets you skip a test when certain requirements aren’t met. This can be done in two ways:

  1. You can manually check if the requirements are met, and then skip the test with $this->markTestSkipped() if they are not.
  2. In some cases, you can use the @requires annotation, and the test will be skipped automatically when the requirements aren’t met.

Using the @requires annotation is nicer, but PHPUnit only has so many options built in. Sometimes you have custom requirements that can’t really be checked reliably with any of the built-in options. An example is when you need some tests you’ve written for a WordPress plugin to run only when WordPress’s multisite feature is enabled on the test site. In my tests, I find myself needing this a lot. So I’ve been writing this over and over:

if ( ! is_multisite() ) {
     $this->markTestSkipped( 'Multisite must be enabled.' );
}

But just yesterday I realized that this was silly, and that I could easily add my own custom @requires annotation. So I did. Here is the code:

	protected function checkRequirements() {

		parent::checkRequirements();

		$annotations = $this->getAnnotations();

		foreach ( array( 'class', 'method' ) as $depth ) {

			if ( empty( $annotations[ $depth ]['requires'] ) ) {
				continue;
			}

			$requires = array_flip( $annotations[ $depth ]['requires'] );

			if ( isset( $requires['WordPress multisite'] ) && ! is_multisite() ) {
				$this->markTestSkipped( 'Multisite must be enabled.' );
			} elseif ( isset( $requires['WordPress !multisite'] ) && is_multisite() ) {
				$this->markTestSkipped( 'Multisite must not be enabled.' );
			}
		}
	}

You just need to add that method to your base test case class, and you will then be able to use @requires WordPress multisite instead of messing with markTestSkipped() all the time. For tests that should only run when multisite isn’t enabled, you can use @requires WordPress !multisite.

You could easily add more options for any other requirements your tests commonly have.

Fixing a Chronically Corrupt Git Index File

A while back I was working on a project where the website was under version control using git. Whenever I would try to run git status before checking out new changes, I would always get an error:

$ git status
error: bad index file sha1 signature 
fatal: index file corrupt 
fatal: 'git status --porcelain' failed

A quick internet search brought up what I thought was the solution:

$ rm -f .git/index
$ git reset

I say I thought this was the solution. But it wasn’t. I’d try to run git status after this, and the index file would still be corrupt. I struggled with this for a long time, until I finally realized what the problem was. It turned out that there were two folders in the git repo that contained .git directories—in other words, what we had was nested git repositories. This wasn’t intentional, and I had no idea that these .git directories were there. Once they were deleted, everything worked again.

TL;DR

Check to make sure that none of the non-submodule directories under your project have .git directories in them.