WordPress Unit Testing with WP_Http

If you use wp_remote_request() or other wrappers for WP_Http methods in your code, this makes it difficult to test, especially if the remote server may not be reachable from your testing environment. That’s why I created the WP_HTTP_UnitTestCase to solve this by letting you mock the remote responses.

The usage details are there in the repository’s readme file.

It lets you mock the remote responses coming from the server, and also captures the data that was sent to the remote server so you can check that the correct requests are made.

As I continue to write unit tests for WordPress plugins I create, I think I’ll find this helper useful. I hope you might as well.

The end of PHP 5.3

PHP 5.3 is dead.

In some ways it’s sad when a version of PHP dies. But in other ways, it’s great. I mean, more time can go into making it a better language instead of backporting security fixes to old versions. Really, the only thing that makes it sad is that so many people will be using these dead and insecure versions for years to come.

The other day I wrote a post about how WordPress supports PHP back to 5.2. In fact, until recently most WordPress sites were running on 5.2. Now, it’s an even split between that and 5.3:

WordPress PHP versions pie chart

Only 21.8% of sites are now running on a living version of PHP.

I think that it is interesting to compare these stats to the number of sites running WordPress versions that receive security updates:

WordPress versions pie chart

39% of sites are running a living version of WordPress.

Why is there such a discrepancy here? Obviously, WordPress is web software, whereas PHP is a programming language, but is there another reason that more WordPress sites are up to date? I doubt that users are more conscientious about updating than web hosts are.

It’s not only that more WordPress sites are up to date, but more of them are running the latest version, 3.9. Whereas PHP 5.5 has a much smaller slice than 5.4.

I think the reason for this difference is probably that WordPress is easier to update than PHP. Not just that there is a difference in technical skill required, but that updating PHP is more likely to break things than updating WordPress. WordPress always aims for complete backward compatibility, but there are sometimes changes in PHP that can definitely break things. It could be that the difference here is the obvious: the less painful it is to update, the more people will do it.

WordPress Core and PHP version support

WordPress core has supported PHP versions >= 5.2.17 for a long time. And there’s been many a discussion by developers and contributors about dropping support for 5.2, making the minimum requirement 5.3. But the lead developers are standing against this move as long as 5.2 makes up a significant part of the user base. And less than a year ago it made up about 50%.

We know the approximate proportions of which versions are being used because this information is available through the stats page on wordpress.org. I’ve been watching this page for a while, and I’ve caught a definite trend away from PHP 5.2 toward newer versions, especially 5.3.

Today, David Anderson posted this to the wp-hackers mailing list:

Rejoice: PHP 5.3 is, at last, on the threshold of overtaking PHP 5.2 as the most common version that WordPress is being run on…

Stats

… just in time for the PHP 5.3 end-of-life! http://marc.info/?l=php-internals&m=140605526629324&w=2 (though for many, there will continue to be security patches for several more years, since PHP 5.3 was part of RHEL 5 and hence Cent OS 5).

From the end of this month, around 21.5% of WordPress installations will be running on non-EOL-ed PHP versions.

Best wishes,
David

You can see this for yourself:

PHP versions WordPress is running on

If you want to know where my sites are on the graph, they make up a part of that green streak for 5.5. :-)

As you can see, this is a mixture of good and bad news. The good news is that people are moving away from 5.2, which no longer recieves security patches from PHP. The bad news is that the majority of these folks, who are moving to 5.3, will just be back in the same boat at the end of the month. And so will WordPress.

It’s not that WordPress needs to drop support for 5.2 so that it can introduce cool new features or improve its performance. Sure, there may be a few ways in which 5.2 is holding us back, but they really aren’t that significant. It’s mostly that the grass is always greener on the other side of the fence.

The thing that really strikes me here is how openly vulnerable software is dominating the market. It isn’t just the PHP versions WordPress is running on, it’s WordPress itself:

Versions of WordPress Pie Chart

What has always seemed strange to me is that only a fifth of sites are running the latest major version of WordPress (3.9). It makes me wonder what the breakdown of PHP versions is relative to WordPress versions, but if I remember correctly, we’ve been told that it’s pretty much the same as overall.

The maintained WordPress versions (3.7, 3.8, 3.9), make up only about 38% of the live websites it’s running on out there. In other words, 62% of WordPress sites are vulnerable right off the bat. And, what really strikes me, is that WordPress 3.0 continues to maintain a larger portion of the market than any other version.

Why is this? Why do folks continue to run old versions of WordPress? I assume it has much to do with a perceived difficulty in upgrading, whether that difficulty is real or imagined. I’m guessing people think of it like this:

  1. Oh, there’s a new version of WordPress.
  2. Updating takes time though, and what if something goes wrong?
  3. I hear there are new features, but do I really need them?
  4. Nah, my site is running fine, it isn’t worth the trouble.

Basically,

updates = (new features) - time - (the chance your site will break)

It seems that many people think that

new features < time + (the chance your site will break)

And in that case, it really doesn’t make sense to update.

But, of course, the equation is wrong. The truth is that

updates = (new features) + (bug fixes) + (security patches) - time - (the chance your site will break)

It’s those security patches that push updates from the trivial to the must.

That’s why I wrote a post asking plugin developers not to add backward compatibility code to support older WordPress versions. Basically, nobody should ever be running those versions.

Which brings us back around to the unmaintained PHP versions that most sites are running on. Should WordPress continue to support these versions? You might think I’d have to say “No”. But in this case, it’s a little more complicated. People know they are running WordPress (at least most of them do), and they either know or could easily find out what version of it they are running. But PHP, well, most people don’t know what on earth that is. And even those that do often have no control over what version they are running. In other words, it is up to the web host.

That doesn’t mean WordPress couldn’t drop an older version of PHP. But it means that if it did, people who use WordPress would panic, because they don’t really understand what is happening, why it is happening. And most of them have no control over what version of PHP they are running. So, you’d have to tell them to contact their host. But their host may or may not be able to just provide a newer version of PHP with a snap of the fingers. In other words, dropping a PHP version that 40% of sites are running on would probably alienate a lot of users, who are using WordPress precisely because they don’t have to worry about all of that technical stuff. But does that mean that we have to put up with hosts running dead PHP versions “for the sake of our users”, when that is possibly making those same users’ sites more vulnerable?

Let’s go back to what I said about WordPress’ lead developers reluctance to drop support for 5.2:

It’s not that WordPress needs to drop support for 5.2 so that it can introduce cool new features or improve its performance. Sure, there may be a few ways in which 5.2 is holding us back, but they really aren’t that significant. It’s mostly that the grass is always greener on the other side of the fence.

In other words, it’s the same false argument being used by folks who don’t feel like updating WordPress: I don’t really need the features, so it isn’t worth the trouble.

Of course, there is a difference. WordPress isn’t responsible for whether a user’s hosting is secure, the host is. And, as David Anderson pointed out, many OS’s and hosts will be providing their own security patches for PHP. In other words, the equation is much harder to solve than it looks. Offering security updates for WordPress, and hoping hosts patch their PHP, may indeed be the best course of action.

One time the unit tests failed me

Since my initiation into the world of unit testing about a year or so ago, I’ve been a huge fan of unit testing. I write unit tests for almost everything now, rather than doing repeated manual testing, which is sometimes more tedious (and certainly gets boring after a while).

But just now, the unit tests failed me. I’ll explain the case in a moment, but let me just say that, as great as unit tests are, they aren’t the only kind of testing you need. Doing manual beta testing is always needed for good measure.

So here’s what happened. I had written a custom module for my WordPoints plugin, with unit tests, of course. And the unit tests were passing fine.

That was last week. But before I tried it out on a live site, I wanted to test it manually on one of my local setups. And guess what. It didn’t work.

I eventually figured out that the issue was a bug in WordPoints, that was caused by WordPress having a 64 character limit for option names. I knew about this limit, but it hadn’t bitten me yet. I’d actually forgotten whether I’d handled the limit properly or not. But that is by the by.

What struck me after I figured out what was going on was this: “What about the unit tests I wrote, they passed fine!”

Yep, they did. And here’s why. For the unit tests, WordPress’s testcase sets up a database transaction before each test. Of course it doesn’t actually commit the data to the database, instead it rolls back the transaction after the test is done. This way, the database stays clean between tests, so they don’t leak into each other.

And this is why my tests didn’t fail. The data wasn’t actually getting committed to the database, so saving the option value wasn’t failing like it normally would. I assume that the database checks that the table and column names are all good, but doesn’t realize that you’re trying to write 65 characters to a VARCHAR(64) field until the data gets committed (which in this case it doesn’t).

In the end, I really think the issue here is that WordPress should fail, or tell us that we’re _doing_it_wrong(), when we try to use option names that are too long. But until then, we need to be careful, when using dynamic option names, that we check they aren’t too long. Especially since unit tests won’t be enough to catch the issue.

Plugin back-compat with old WP versions

One of the great things about the WordPress project, is that it is committed to retaining backward-compatibility. That makes life easier for plugin developers, because we don’t have to constantly worry that the next update to WordPress will break our plugins. It won’t. And in rare cases where it could, we are given full warning ahead of time.

But sometimes things do get deprecated, and a new, better way of doing things is introduced. When this happens, we often need to update to the new way of doing things. Sometimes this means our plugins won’t work with older versions of WordPress out of the box, unless we write special code for backward compatibility.

This post is a plea to WordPress developers not to do this.

Actually, I’m all for maintaining backward compatibility with older versions of WordPress, as long as it doesn’t keep you from moving forward. I’ve actually done it myself. But before writing back-compat code, think a little bit about the out-dated version of WordPress that you are supporting. Should people actually be using that version of WordPress? Sure, some folks don’t need to have every new feature that WordPress comes out with, they’re doing just fine with the version they have. But it isn’t about the features. It isn’t even about the bugs. It’s not even about the fact that the admin panel feels like something brought through the flood on the ark. No. It’s about the vulnerabilities.

If you haven’t actually faced this yet, let me disillusion you. All web software has security vulnerabilities. Every. Single. One.

The old versions of WordPress have vulnerabilities, and the new versions of WordPress have vulnerabilities. In fact, there are vulnerabilities in WordPress trunk, that as you read this, are just sitting there waiting to be discovered. The difference is that we know what the vulnerabilities are in the old versions of WordPress. And we know something else. They aren’t fixed. They are still there on every site that is running that old WordPress version. That old, insecure version of WordPress.

Now let me ask you, is that something that you, as a WordPress developer, want to promote? Using vulnerable software?

But what can you do about it? You can decide not to waste your precious time writing code whose only purpose is to support these outdated WordPress versions.

I’m not asking much. I’m not asking you to write code to purposely break your plugin’s compatibility with old WP versions. If it happens to run fine on vulnerable versions of WordPress, that’s fine with me.

I’m actually not asking you to do anything, for starters. Just stop doing something that maybe you’re already doing: writing back-compat code for insecure WordPress versions. And if you do want to do something, here’s an idea: remove the back-compat code you’ve already written.

Maintaining backward compatibility is always a tough decision. It takes extra work, work that could be used to fix bugs or design cool new features. So why do it when you have such a good excuse reason not to? Writing back-compat code for insecure versions of WP is encouraging users to continue using those versions instead of updating to newer versions, where all known vulnerabilities have been fixed.

There was a time in the not-to-distant past, when only the latest version of WordPress received security updates. That time is no more. With the advent of automatic updates, making security patches available to users of older versions became much easier. Now all versions of WordPress back to 3.7, when automatic updates were introduced, are maintained. So you can provide backward compatibility to 3.7 in your code in good conscience. But please, don’t go any further than that.

Telling your users why you don’t support older versions is also a good idea. They will thank you. Or they’ll call you names, and wonder why they keep getting hacked. Either way, you know that you are doing something to make the web more secure.