The Theory of Unit Testing, Part 3

In the past two articles, we've taken a close look at the theory behind unit testing and how it can help us in our WordPress development efforts. We've defined unit testing and examined various ways that it can help us throughout our projects.

But we still have more to cover.

In this final article, we'll review why we should even bother doing unit testing and we'll summarize the advantages and disadvantages of doing it. Next, we'll look at how we can retrofit testing into our existing projects. And to wrap up, we'll summarize a list of resources that are available specifically to us WordPress developers that will aid in beginning to unit test our themes.


Why We Unit Test: All About Quality

The overarching theme of this entire series has been about why we should bother with unit testing, but if it hasn't been succinctly stated, this is why:

Unit Testing helps us to uncover problems early, provide developers with a level of self-documenting code, and gives us a higher-level of quality of software.

Granted, this assumes that we follow through on practicing good unit testing techniques. Of course, this was covered in great detail in the previous article, but it's worth reiterating.

An important thing to note – especially if you're trying to apply this in a more corporate setting or in the context of a larger business – is that unit testing is not just something that developers do for themselves. Quality is two sided – it benefits the customer and it benefits the business.

By providing a higher level of quality for the customer – that is, more thoroughly tested software – they should experience fewer bugs. Since bugs result in time that developers must spend resolving rather than working on new projects or new features of existing products, this can ultimately save money.

By providing a higher level of quality for the business, developers are more confident in their efforts because they can execute a suit of tests each time a change is made knowing how their work affected the entire application. If a test fails, then they are able to resolve it before deploying it to production.

Unit Testing is about quality and it affects not just those writing the code, but the business that's shipping it, and the customers that are using it, too.


Advantages and Disadvantages

The truth is, we've already covered the advantages of unit testing. For completeness, let's summarize them here (although you can always review them in detail!). Unit Testing...

  • Helps developers find problems early and can save time as the application grows and new features are introduced
  • Provides a level of documentation in the code so that current and future developers can understand how the code is supposed to work
  • Drives architecture so that the application is testable throughout its lifecycle
  • Enhances the language of the code by providing more readable functions and flow of control

All sounds great, right? And yes, it's predicated on developers holding themselves accountable to high standards and practices when it comes to actually implementing this in day-to-day work, but unit testing is not without its disadvantages.

Time Is Money and You're Spending Time

This has been said throughout this series: unit testing takes a significant time investment. Admittedly, if you're starting a new project, the time investment is much lower than if you're fitting this into an existing application, but you're still having to write more code than without testing.

Because you're writing more code, you are taking more time – again, on the front end of the project. The benefits of unit testing often don't come until later, but if a project has a specific target date for release and that release includes a certain number of features, you're not likely to fit all of the unit tests and the features into the release.

If you want to avoid smaller feature sets at release or delayed target dates, you have to build in time for unit testing.

Complexity Kills and Other Cliches

You've heard 'em all: complexity kills, keep it simple stupid, less is more, and so on.

Honestly, all of these are true and they have their proper place in development, but the fact is that unit testing is additional code and additional code always introduces more complexity. As such, we have to make sure that we have a proper way to manage and organize all of our unit tests.

Perhaps it's file organization, or name spacing, or naming conventions, or versioned tests, or all of the above. Whatever it is that you end up doing, unit tests should not be treated as second-class citizens in the world of software – they should be subject to the same design principles as other classes or functions as much as possible.

The Downside of Design

Yep, in the last article we said that unit testing can help drive the design of an application and it can help foster a design that makes the entire application more testable. This is still true, but it comes at an expense: sometimes the most unit testable design isn't the clearest.

By that, I mean that because a set of functions – or even a class – is fully unit-tested, the cohesion has the potential to be compromised because we're making sacrifices to access certain functions to verify their processing of data. Of course, this isn't a hard and fast rule and this may not even be an issue for some, but you have to decide what you're going to be dogmatic about: is it a perfectly engineered set of classes and or functions or a contiguous system of tests and functions that work together?

Ultimately, I believe that it comes down to how you view tests as a larger part of the whole. If they are part of your application's design, then the design may not suffer. But if you view tests as an afterthought, then the design of the core application may be compromised just slightly.

Continuous Tweaking

As they say, software is never done and since unit testing is part of a piece of software, it's never done.

Because an application is always going to be evolving – be it bugs being squashed, new features being introduced (or even removed), the associated tests are going to need to be added or updated as well. And it always comes back to time.

Furthermore, if you're working in a team of developers, our lack of updating tests can negatively affect the team as the results that tests report may be false positives or false negatives. Once tests are written, it's imperative that they are updated; otherwise, they can result in a very poor product.


Incorporating Unit Testing Into Your Workflow

Unit Testing is a much easier sell when you're starting out with a project, but if you're looking to retrofit it into an existing application (or theme or plugin, in our case), it's going to take a bit of time and effort.

And though there's no silver bullet for how you can perfectly execute on this, there are a few good ways to begin implementing the practice in your daily work:

  • Make sure your project is under source control – This should be a given, but if it's not, get started as soon as possible. The "how's and why's" are outside the scope of this article, but it's critical to have your work under source control especially once you introduce tests.
  • Introduce the WordPress Unit Tests – Get setup with the WordPress Unit Tests (instructions here). I recommend keeping them in a subdirectory in your project in order to more easily organize the tests. Make sure that they get committed to source control.
  • Begin Adding Tests – Each time that you work on a function or introduce a new function, add a corresponding unit test. If a pre-existing function isn't testable, then spend the time to make sure that it is. This is an uphill battle but it will pay off.
  • Remember Success and Failure – Remember that while you're writing tests, you also must introduce tests for the success cases and tests for failure cases, too.

If you follow the above steps, you'll eventually end up with a significant amount of code coverage. Yes, it takes time and yes you'll likely have to rework a lot of the code but that very same time investment will yield dividends in the future of your product.


Available Resources

Here's a summary of the resources that can contribute to successful testing of your WordPress-based projects:

  • The Beginner's Guide To Unit Testing – A series of articles that I wrote introducing unit testing and how to test plugins and themes.
  • PHPUnit – The framework on which the WordPress Tests are based.
  • PHPUnit Documentation – The manual for PHPUnit. This is useful for when you're looking for available methods for writing assertions in your code.
  • Hello Reader – A simple plugin that I wrote to demonstrate how to unit test plugins.
  • WordPress Tests – The official WordPress Tests and testing framework available for checkout via Subversion.
  • Basic Theme – A simple WordPress Theme used to demonstrate how to unit test themes.

Between the first series of articles and this series of articles, a strong foundation has been laid on which you can continue to build your unit testing practices.

Tags:

Comments

Related Articles