May’s Book Club selection is Sierra’s Badass: Making Users Awesome

lrgJoin us for the May News Nerd Book Club hangout on Wednesday, May 13, 2015 at 1 p.m. ET.

This month we'll be reading Badass: Making Users Awesome by Kathy Sierra.

From the book's description:

"Imagine you’re in a game with one objective: a bestselling product or service. The rules? No marketing budget, no PR stunts, and it must be sustainably successful. No short-term fads.

This is not a game of chance. It is a game of skill and strategy.

And it begins with a single question: given competing products of equal pricing, promotion, and perceived quality, why does one outsell the others?"

The meeting this month will be held via Google Hangout and the invite and link to RSVP are right here.

Hope to see you in a few weeks. Happy reading!

Contributing to the INN Nerds docs repo using

This guide is for those of us who are not regular Terminal/shell users and those who do not want to or can't use the Gitbub client to make changes to a Github repository.

While this is written specifically for folks that want to contribute to our docs repo, the steps are the same for any repo.

Keep in mind that our docs repo is just a collection of Markdown files, making it an ideal candidate for this approach to contributing.

Since you can't run your code on to test changes, the potential to introduce bugs by editing code directly on seems extraordinarily high, in my opinion. If you have a repo with actual code, I'd suggest learning command line git or dive into the Github client (for Windows, for Mac). The learning curve is steep, but the tools are more powerful.

Getting started

First of all, you'll need a account if you don't already have one. It only takes a minute. We'll wait for you.

After you have your account set up, go to the INN docs repository.

From there, you can use the "Fork" button in the top right to create a full copy of the repository under your Github account.

Fork this repo

If you are a member of multiple organizations on Github, you will be asked where you'd like to fork the repository. In this case, I want my fork of the docs repository to live under my personal Github account:

Choose account for fork

After you choose an account, Github creates your new fork and drops you on its homepage. Notice the URL and the message just below the title of the fork indicate that this is a derivative of another repository.

Fork homepage

Step one: complete. Not so bad, right?

Editing a file

Now let's make a simple change to one of the files in our fork of the repository. In this case, we're making a superficial change to the file as an example.

From the homepage of the fork, find the link and click:

Once the has loaded, look for the edit icon near the top on the right side of the page:


Once you click the edit icon, you are presented with a text editor where you can make changes to


Towards the bottom of the file, I notice that the spacing between the heading Version 0.1 and the list that follows is not consistent with the style of the rest of the document. So, I add a new line after Version 0.1.

Before and after:

Before and after

Next, we must add a message to go along with our change. At the bottom of the page, you'll see an area labeled "Commit changes". In the first input, you should provide a brief but sufficiently descriptive message regarding your change, so that anyone browsing the history of changes made to the repository will have an idea of what changed and when. For example:

Commit message complete

The secondary input is optional. I'm going to skip it here.

Once your message is in place, click "Commit changes".

Submitting a pull request

Great! So far you have your own fork of the repository and you're making changes left and right. But how do we let the maintainers of the original repository know that we have lots of good stuff for them to incorporate in the original?

The answer: submit a pull request.

To do so, go to the homepage of your fork. In my case, Towards the top, right side of the page find the "Pull request" link and click.

Pull request

On the page that follows, you'll see something like:

Pull request details

If you've followed these instructions, the pull request page should default to settings that essentially say, "Submit a request to the maintainers of the original repository, asking them to pull in the changes made to my fork of this repository."

We'll gloss over the details of what each of the dropdowns at the top of the page can do for the pull request's settings. Let's stick with Github's sensible defaults for now.

Towards the bottom of the page, you can see the "diff" (i.e., difference) between the original version of the file (left) and the changes made to the file in your fork.

Now, click the big green "Create pull request" button at the top.

You'll be presented with another dialog, asking you to include any relevant details about your changes, consequences it might have for other areas of the repository, why your change is the "right way" to do it, etc.

Pull request details

Once you add a sufficient message, click "Create pull request" (this time, with feeling!).

Hooray! We now have an open pull request on the original repository's page:

Open pull request

Note that the URL and the repository title no longer reflect our Github account or fork of the repository.

What happens next?

When you submit a pull request, a notification is sent to the maintainer(s) of the repository. They can then review your proposed changes and either merge (e.g., pull) your changes back into the original repo or reject them.

In this case, since I am a maintainer for the original repository, the pull request page in the screenshot above displays a "Merge pull request" button. This will not appear if you do not have permission to make changes directly to the original repository.

Congratulations, you're now well on your way to contributing to our docs repo (or any other repo, really). Drop us a line in the comments or @INNnerds with your questions and pro tips for contributing to projects using

How to debug email-related theme and plugin functionality in WordPress

Let's say you're having trouble with a WordPress theme or plugin that uses wp_mail. How can you inspect the email that wp_mail composes or verify that it is actually sending (or at least attempting to send)?

Well, one simple way is to tell WordPress to use Python's smtpd DebuggingServer to "send" email.

The DebuggingServer doesn't actually send email, so don't go checking your inbox. It's only meant to show you the email that would be sent, headers included, if it were an actual SMTP server.

Note that this guide assumes you're debugging wp_mail issues during local development.

Let's get started.

Set up the smtpd DebuggingServer

If you have Python installed (comes with Mac OS X and most distributions of Linux by default), this is the one-liner you can use to get the debugging mail server running. From the command line, run:

$ python -m smtpd -n -c DebuggingServer localhost:1025

So that you don't have to remember that command, you can add an alias to your shell profile (e.g., ~/.profile), making it super easy to run the debugging mail server at a moment's notice.

To do this, open your shell profile in your favorite text editor and add the following line:

alias mailserve='python -m smtpd -n -c DebuggingServer localhost:1025'

Save your shell profile and source it in your shell to make sure the new mailserve alias is available:

$ source ~/.profile

Note: ~/.profile is probably the most common shell profile location. If you don't have this file, you can create one by running:

$ touch ~/.profile

Keep in mind that you might already have a shell profile for your specific shell. For example, ~/.basrhc for bash or ~/.zshrc for zsh. If you have a ~/.bashrc or ~/.zshrc, you can try adding the mailserve alias to one of them instead.

Once you have the mailserve alias defined and your profile sourced, running the server is as simple as:

$ mailserve

Note: there won't be any output from running this command initially. The debugging server runs, waiting for an application to connect and attempt to send a message.

Tell WordPress to send mail via the DebuggingServer

Now, in your WordPress theme or plugin, you can add some debugging code that will tell WordPress to send email via the debugging server you have running.

To accomplish this, add the following code to your theme's functions.php or to your plugin's main file:

function phpmailer_debug_settings($phpmailer) {
    $phpmailer->Host = 'localhost';
    $phpmailer->Port = 1025;
add_action('phpmailer_init', 'phpmailer_debug_settings');

This code changes the configuration of the $phpmailer object used by wp_mail, telling it to use the SMTP server on localhost, port number 1025. If you look back at the Python command used to fire up the debugging mail server, you'll see the $phpmailer settings correspond to the arguments passed in that command:

$ python -m smtpd -n -c DebuggingServer localhost:1025

Once you have the debugging mail server running and the code above included in your theme/plugin, you can try sending mail with WordPress and see the entire message contents, SMTP headers, etc in your shell. Here's some example output:

vagrant@precise64:~$ mailserve
---------- MESSAGE FOLLOWS ----------
Date: Thu, 12 Mar 2015 16:21:54 +0000
Return-Path: <>
To: "\"Investigative News Network\"" <>
From: Ryan <>
Subject: [INN Website Contact] This is a test email subject line
Message-ID: <>
X-Priority: 3
X-Mailer: PHPMailer 5.2.7 (
X-Mailer: WP Clean-Contact (
MIME-Version: 1.0
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This is the test email body.

------------ END MESSAGE ------------

Why do I need this?

This can be helpful if you're trying to track down missing parts of an email (e.g., hey, where'd my "from" address go?) or need to verify the contents or formatting of an email that your theme/plugin sends to users.

Keep in mind that, although this post describes how to use the Python smtpd DebuggingServer with WordPress, you can also use this guide with other applications as long as you can configure said applications to connect to the DebuggingServer.

Nerd Alert Issue 12: On the Road Again

We’re packing our bags and heading to Atlanta. See you at NICAR next week?


What we're reading this week

  Adam: For new users of CSS preprocessors the allure of nesting is strong, but if you have to maintain the CSS you write for some time to come, it can really come back to bite you. I have felt this bite this week as we’ve been refactoring some of the navigation elements in Largo and it’s gotten pretty ugly, at times. Don’t let this happen to you.

  Ben: Programming languages grow and evolve over time. How do the changes come to be? Boucoup has proposed an addition to JavaScript that would simplify raising numbers to powers. Their blog post on how they chose the syntax and what has to change to support it is, to my eye, fascinating.

 Denise:  I am in love with this new tool — and it’s acronym. LMGTDFY (Let Me Get That Data For You) is a free, open-source tool from U.S. Open Data that returns a machine-readable inventory of all the data files found on a website. Fun, huh?

  Kaeti:  Too often it feels like we have to choose between excellence or getting things done. Clair Byrd recently shared some thoughtful ideas about how we can make striving for excellence a daily practice.

  Meredith: I share an interest in gaining a better understanding of code and how it impacts journalism (keeping up to my thoughtful teammates), I found a journalist based in the Czech Republic, David Bauer, who shares the story of his year spent learning code.

  Ryan: A little computer science history for you this week: read about Grace Hopper — WWII veteran, early computer scientist and developer of the programming language that eventually became COBOL. Also, watch her 1986 interview with David Letterman.

  Will: If you like computer science, and you like considering “what if,” check out this Reddit thread that asks r/compsci, “How different would Computer Science be if we were to reinvent it?” Maybe we’d live in a world where Java didn’t exist and PHP wasn’t so terrible.

  Bert: Helpful robot is helpful.

This week's guest contributor: Heather Billings, NU Knight Lab - @hbillings

In the beginning were computers, and women programmed them. A lot of women. So what happened? Turns out, computer programming isn't the first activity to shift from being relatively gender-neutral to being full of bros, broads and beer. Maybe it's time tech learned some lessons from skater culture (and I don't just mean how to look wicked cool in a hoodie).

Each week we ask someone from outside our team to contribute a link, tool or idea. Are you our next guest star? We think you might be. Send us a note at

We Made A Thing

Our projects, manifest

Screen Shot 2015-02-20 at 10.19.44 AM

This week, we shipped the first release of the PMP for WordPress plugin. Check out the code on Github and read more about the Public Media Platform.

Also, don't forget — the INN Nerds Book Club will meet during NICAR in Atlanta. We're reading and discussing The Design of Everyday Things by Don Norman. Join us!

Shout outs

Transformicons: A beautiful and useful library of animated icons, symbols, and buttons using SVG and CSS.

Some Other Stuff

Gather ye rosebuds

LISTEN: February 26 is Johnny Cash's birthday. Celebrate with Big River live at the Opry, 1962.

COOK: ICYMI: The scientific approach to seasoning your cast iron.

WATCHCustom Buffalo-mobile.

GIF: I think we've all spent quite enough time on the internet this week.

Did you read the whole thing? Feel free to forward it to all your friends. Human or canine. 

Nerd Alert Issue 11: It’s Dangerous to Go Alone

It's dangerous to go alone! Take this.


What we're reading this week

  Adam: Even if you don’t work in public media, a new weekly podcast from called The Pub is worth checking out. A few episodes in and producer Adam Ragusea has covered topics ranging from how pick theme music to how women, people of color, and everyone else can sound more like themselves on the radio. Here’s the link to subscribe in iTunes.

  Ben: The FAA has proposed rules for drone operation in the US, and we're going to start seeing a lot more drone footage in news. But drones have more uses than just taking photos: check out these 3D maps of the Donetsk airport, created using drone footage. What can you do that isn't just a plain photograph or video?

 Denise:  Where do you even start looking for stories in all that Census Bureau data? Anthony DeBarros breaks down the household and relationship questions in this post from the Source blog and, with specific tips on where to find the most relevant data.

  Kaeti:  We could all stand to be better listeners. Sarah Green collected some classic wisdom from the HBR archives and what she found is as relevant as ever. Turns out, it all starts with actually caring what other people have to say.

  Meredith: "I read the news today, oh boy." The Guardian enlists Will Bulter of the Arcade Fire to write a song a day based on a Guardian article to be premiered on their site. Inspired in part by Bob Dylan, his week long residency begins Monday, February 23rd.

  Ryan: I've been using submodules for quite a while now and never really had a problem with them. However, after reading Christophe Porteneuve’s post, I think I may have developed a mild case of Stockholm syndrome. This post covers the pros and cons of using git submodules to account for a project's external dependencies. It’s worth a read if you’re starting a new project and considering the best approach to this problem.

  Will: User interface design is the responsibility of everyone involved in making a piece of software. That’s why keeps a running list of ideas to make interfaces better. Not every idea is great (and might not apply to every product), but each has its merits.

  Bert: See Spot. See Spot run.

This week's guest contributor: Erin Harper, Chicago Tribune — @ehrpr

As a multimedia editor at the Chicago Tribune, I often make decisions about publishing graphic content. This piece by Storyful outlines their method of vetting sensitive content as a news agency. But it also reminds us of our complex responsibility as journalists to balance being both analysts and messengers. The question we face is not just whether or not to publish, but also how to publish. As our industry evolves, we must always be having this conversation.

Each week we ask someone from outside our team to contribute a link, tool or idea. Are you our next guest star? We think you might be. Send us a note at

We Made A Thing

Our projects, manifest


Screen Shot 2015-02-20 at 10.19.44 AMWe’re excited to be working with The Public Media Platform (PMP) on a new WordPress plugin for their API to make it easier for public media organizations to share content with one another. We’ll be working on the plugin over the next couple of months and plan to release the final plugin late this spring. Look for future announcements as we roll it out over the coming months.

Shout outs

In anticipation of NICAR 2015, Ben Welsh and friends have updated their wonderful step-by-step guide to publishing a news app for the first time. Check it out: First News App.

Some Other Stuff

Gather ye rosebuds

LISTEN: This week’s soundtrack is brought to you by Sleater-Kinney with an assist from the folks at Bob’s Burgers.

FOOD & DRINK: (Re)discover this nearly-lost style of beer: Gose.

WATCH: Your weekly dose of cute/majesty.

GIF: Fin.

Did you read the whole thing? Feel free to forward it to all your friends. Human or canine. 

Nerd Alert Issue 10: Happy Something Day!

Here's hoping your President's Day celebration is a blast!


What we're reading this week

  Adam: Every time the design team at Medium writes about their work I’m at once super inspired, jealous and perhaps a little depressed. This week they published an epic series on how they think about typography for the site that has lots of tips that are applicable to any site and some that are...well, a little depressing because they would take forever to implement. But one can dream!

  Ben: You’ve heard that journalists and their support organizations should be more conscious of information security, but you haven’t been sure where to start? Check out the book Learning Security: Information Security Education for Journalists by the Tow Center for Digital Journalism.

  Kaeti: A lot of advice reads like a sort of infallible prescription for success, when in reality it’s just what happened to work for that person. Eileen Webb’s thoughtful essay reminds us that, “Our journeys are our own, and the key to each person’s success does not — cannot — lie on someone else’s path.”

  Meredith: Word clouds aren’t always silly. I discovered this suggestion for using Wordle to improve design research. Discovered via a Huffington Post list of Awesome Blogs Every UX Designer should follow in 2015.

  Ryan: A few weeks ago, the developers at Facebook released React — a javascript library for building user interfaces. I’m always excited to try shiny, new libraries. React promises ultra-high performance, stateful components and an intuitive data pipeline. For a closer look at how to build things with React, read Thinking in React.

  Will: If you're anything like me, you cringe at the thought of building rewrite rules. That's why you'll probably want to star this new repo by phanan on github — a list of .htaccess snippets to make at least that part of your day suck a little less.!

  Bert: Harder, better, faster, stronger.

This week's guest contributor: Aaron Williams, The Center for Investigative Reporting — @aboutaaron

As a news developer, I strive to build graphics and applications that meet people where they're at. In most cases, that's been the web -- and more specifically -- the mobile web.

So, Quartz's recent story on how millions of Facebook users perceive the popular social network, not as a web site, but as platform in and of itself, shocked me.

Facebook's accessibility and reach around the world is important and gives journalists a great vehicle to share their content. But, we must remember that Facebook certainly has its own interests. As we ponder journalism's new model, let's hope we as reporters can convince these Facebook provincials that the web is just as diverse as the world they live in.

Each week we ask someone from outside our team to contribute a link, tool or idea. Are you our next guest star? We think you might be. Send us a note at

Shout outs

The folks at Mapbox developed hubdb — a database adapter which uses Github for storage. Props to them for creative use of git and Github!

Some Other Stuff

Gather ye rosebuds

LISTEN: J Dilla passed away this week in 2006, but left us with his incredible music. To celebrate Dilla Day (Feb. 7, J Dilla’s birthday), give It’s Your World a listen.

COOK: Here in Chicago, we’ll be cooking up a hearty meal of shrimp and gritsto help get through this cold weather.

WATCH: Sister Rosetta Tharpe performs This Train.

GIF: Pro tip for your first custom computer build: this is not supposed to happen.

Did you read the whole thing? Feel free to forward it to all your friends. Human or canine. 

Nerd Alert Issue 9: Grab a Napkin, You Just Got Served

Serving up hot, fresh links since 2014.


What we're reading this week

  Adam: Design sprints are a technique Google Ventures has developed to allow the companies they work with to build and test nearly any idea in just 40 hours. Their findings will eventually be released as a book, but for now they’ve shared a list of articles and resources they’ve developed over three years spent refining their process.

  Ben: How to Check a Website for Accessibility is up, and it’s an interesting read. Carrie Dils is publishing a series on online accessibility, and I’m curious to see where it goes. Yes, you can subscribe to her newsletter.

  Denise: I don’t know about you, but I usually do my best thinking in the shower. Probably because I can’t take my phone in there with me. I am loving WNYC’s Bored and Brilliant project, which is making the case to bring boredom back. The project has great stories on the science and consequences of smartphone addiction, apps to track your usage and a week’s worth of daily challenges to help you find a better phone-life balance. And if you’re interested in the journalistic takeaways from this project, Poynter has a good piece about WYNC’s innovative audience engagement.

  Kaeti: “Designing your team is just as important as designing the product itself.” Cap Watkins writes about how he’s approaching the needs of the design team at Buzzfeed. A lot of this advice resonates with me, especially the importance and value of transparency.

  Meredith: Courtesy of, this API Explorer Tutorial is an effort to banish boring static documentation. You can read and listen to more about interactive documentation.

  Ryan: If you haven't had the chance to use Oculus Rift yet, I highly recommend seeking out the opportunity. As Zac Nielson covers in this piece, this device has the ability to create a level of "presence" (i.e., immersion) which is nearly impossible to achieve via traditional writing, audio and video. It's a tremendous innovation that has implications for a variety of fields. For news organizations, it means a new medium for story telling. What better way to create empathy than to convince your audience that they are truly a part of the narrative?

  Will: I found myself rereading this piece on Vox Product earlier this week about how the algorithm to populate their homepage works. If you haven't read it yet, check it out!

  Bert: Bow to your snake bot overlord.

This week's guest contributor: Becca Aaronson, Texas Tribune - @becca_aa

The way a user navigates a website plays an essential role in how story unfolds on the web. This guide to efficiently simplifying navigation in Smashing Magazine includes a bunch of simple tips on how to keep your website’s navigation intuitive. As news organizations continue to experiment with novel ways of telling stories on the web, we’re seeing more outlets go beyond the basics to create interesting nonlinear narratives, such as NPR’s Borderland and the Tribune’s Shale Life series.

Each week we ask someone from outside our team to contribute a link, tool or idea. Are you our next guest star? We think you might be. Send us a note at

We Made A Thing

Our projects, manifest

Screen Shot 2015-02-06 at 10.56.00 AM

ICYMI: We announced Largo 0.4 last week and published a sample child theme to help you get started on your own Largo-based project. Sites using the new version of Largo now include:, and

Shout outs

Screen Shot 2015-02-06 at 10.44.09 AM

This fun, open-source UX project checklist will help you keep track of all your important project milestones.

Some Other Stuff

Gather ye rosebuds

LISTEN: Alice Gerard, Strange Land, nominated for a Grammy at 80.

COOK: On chilly mornings, a warm breakfast helps, and the video is elegant: Buckwheat Porridge with Poached Pears.

WATCH: How to build a cat lamp.

GIF: It's Friday. Kick back, relax and have yourself a drink.

Did you read the whole thing? Feel free to forward it to all your friends. Human or canine. 

Writing Stupid Simple Unit Tests

In this post, we'll cover the basics of unit tests and walk through the process determining what types of tests you should write for your code. We'll also write a few tests to show just how simple most unit tests are.

The aim here is to make tests a bit more familiar and less daunting and mysterious. Unit tests are good. I'm by no means an expert on software testing. I'm just someone that's discovered the joy and freedom that writing tests provides.

If you are an expert on software testing and notice I'm wrong, please tell me!


What are unit tests?

If you’re not familiar with unit tests, they’re essentially software written to test discrete units of functionality in a system.

Unit tests test the expected behavior of your software as it exists (or existed) at a specific point in time. They make sure that everything works as expected based on the rules established for the software at the time it was written.

If those rules change -- and your software along with them -- your tests will fail. When they fail, you'll gain insight into how the change affects the rest of the system.

For example, if a change is made in code for your site’s user profile management, you'll want to make sure that the change does not affect the behavior of your site’s payment processing code.

Tests can save time and money by acting as the first line of defense in catching problems before they result in a late night emergency or catastrophic failure. When things go wrong, they can also serve as the first response team. You can run your unit tests to see if any rules/expectations have been broken by some recent change, either in your code or some external API dependency, and fix the bug introduced by the change.

Sometimes the tests become outdated. Again, the tests will fail, letting you know that you’re no longer testing for the right thing. When this happens, you should update your tests to make sure they are in line with the new rules for your software.

Getting started

Unit tests are rarely difficult to write or run if you’re using a testing framework (e.g., phpunit).

You can write your tests before you write your business code if Test-driven Development (TDD) is your thing or you can write them after.

It doesn’t matter much when you write them as long as you have them.

The brilliant thing is that almost all tests you write will be stupid simple.

Tests usually assert some condition is true (or false, depending on what outcome you expect).

On top of that, most testing frameworks have convenience functions built in for performing these types of tests and several others, including testing the expected output of a function (i.e., what the function prints to the screen).

The three test functions we've used most frequently when writing tests for Largo are assertEquals, assertTrue and expectOutputString.

Our stupid simple example plugin

So, let’s say that we want to write tests for a WordPress plugin. Our plugin simply prints the message “Hello world!” in the top corner of the WordPress dashboard (sound familiar?).

This is the extent of the code:

 * @package Hello_World
 * @version 0.1
 * Plugin Name: Hello World!
 * Plugin URI:
 * Description: Just a simple WordPress plugin that prints "Hello world!" in the top corner of the WordPress dashboard.
 * Author: Ryan Nagle
 * Version: 0.1

function hello_world() {
  return "Hello world!";

function hello_world_markup() {
	echo "<p id='hello-world'>" . hello_world() . "</p>";
add_action('admin_notices', 'hello_world_markup');

function hello_world_css() {
	$x = is_rtl() ? 'left' : 'right';

	echo "
	<style type='text/css'>
	#hello-world {
		float: $x;
		padding-$x: 15px;
		padding-top: 5px;
		margin: 0;
		font-size: 11px;
add_action('admin_head', 'hello_world_css');

Couple of things to note:

  1. We have one function -- hello_world -- that returns a string.
  2. Two other functions -- hello_world_markup and hello_world_css -- that echo strings but have no return statements. This means we'll have to check the output of these functions rather than the return value to properly test them.
  3. Note that hello_world_markup relies on hello_world to provide the the “Hello world!” message.

So, how do we test this plugin? Well, if you don’t have your test framework installed and configured, you’ll want to get that ready and raring. The details are beyond the scope of what we'll cover here, but for an overview of setting up unit tests for WordPress plugins and themes, see Will Haynes’ Unit Testing Themes and Plugins in WordPress.

The INN Nerds also have a collection of deploy tools to make developing WordPress sites and writing tests much easier. You can read about using the deploy tools for testing themes and plugins here: Updates to INN’s Deploy Tools.

Disclaimer: getting unit tests working WordPress can be daunting at first. It’s a lot to digest and may take some time to set up if you’re coming to this cold, so be patient. It’ll be worth it.

If you’re really dedicated to the cause and need a hand, reach out to us.

How do I write a unit test?

With that out of the way, let’s design some unit tests for our “Hello World!” plugin.

The first thing we’ll want to do is enumerate the features of the code which we need to test.

There are many ways you can approach this. My preference is to create a single test file per file in my source code and have my tests directory mirror the structure of my source directory.

Each test file has tests for each function (or member functions of classes) in the corresponding source file.

So, the directory structure for our plugin would look like:


We’ll be doing our work in test-hello-world.php where we’ll set up the skeleton of our test case, which is as simple as extending WP_UnitTestCase:


class HelloWorldTest extends WP_UnitTestCase {}

We can then stub out test functions for each function:

 class HelloWorldTest extends WP_UnitTestCase {
  function test_hello_world() {
    // Test hello_world()

  function test_hello_world_markup() {
    // Test hello_world_markup()

  function test_hello_world_css() {
    // Test hello_world_css()

Now, let's look at each function and consider what we're testing:

1. For hello_world, we want to verify that the string returned is "Hello World!":

function test_hello_world() {
  $this->assertEquals("Hello World!" == hello_world());

Easy enough. Now if for some reason someone changes the return value to "Hello world!" -- capitalization be damned -- the test will fail.

I can hear you now, "This is stupid, no one writes code like this." Yes, the example is stupid and that's the point. Don't get caught up focusing on the wrong thing.

It makes no difference how complex the function is, the only concern is verifying that the return value or the outcome is what is expected.

So, if instead you're testing some_made_up_function which returns an object, you may want to verify that it is actually a PHP Object:

$this->assertEquals(gettype(some_made_up_function()), "object");

Or that the object has a specific member attribute:

$test_obj = some_made_up_function();
$this->assertTrue(property_exists($test_obj, 'name_of_attribute_goes_here'));

2. For hello_world_markup, we want to verify that the function prints "<p id='hello-world'>Hello World!</p>":

function test_hello_world_markup() {
  $this->expectOutputString("<p id='hello-world'>Hello World!</p>");

Notice that we're expecting "Hello World!" to be part of the output. This might not be a good thing. If the return value of hello_world changes, this test will fail, too.

For the sake of example, let's say we only care about testing the markup and not the message. We can take this test a step further and decouple the two so that we're only testing the markup by changing it to read:

function test_hello_world_markup() {
  $result = ob_get_contents();

  $this->assertTrue(!empty(preg_match("/^<p\s+id='hello-world'>.*<\/p>$/", $result)));

Essentially what we're saying is, we don't care what the message is as long as it is wrapped in <p id="hello-world" /> tag.

Simple, right?

3. For hello_world_css, we want to verify that the function prints the CSS rules for our "Hello World!" markup:

function test_hello_world_css() {
  $result = ob_get_contents();

  // Make sure there are style tags being printed. Duh.
  $this->assertTrue(!empty(preg_match("/.*?.*<\/style>/s", $result)));

  // Make sure we're using the right selector
  $this->assertTrue((bool) strpos('#hello-world', $result)));

And with that, we're done! You can see the entirety of test-hello-world.php here.

When to write tests

As mentioned earlier, you may want to write your tests first. This is called Test-driven Development.

Writing your tests first has lots of awesome benefits. When you write tests first you are forced to think about the design of your system and how best to structure the software so that it is actually testable. It’s a good practice and will help increase the orthogonality of your code.

However, it's never too late to start writing tests. When you write tests for existing code, you'll find places where things need to be refactored (sometimes completely rewritten or redesigned) to clean up the spaghetti code.

If you really can't afford the time it takes to write tests for all your code (or aren't being allotted the time to do so), you might still be able to lobby for time.

It's extremely important that you can verify your code works, especially in cases where you're using code to make an assertion about the world. For example, if you're writing code that processes a data set which will later be used in a story or investigation, it's crucial that your code produces results that are precise and correct.

The other case where you should absolutely be writing tests is for critical customer interactions. Saving sensitive information or processing payment information are things that you don't want to get wrong.

Updates to INN’s Deploy Tools

We've made a lot of changes and added a bunch of new commands to our deploy tools since the last time we checked in.

Most notably, we've added commands to help scaffold and run unit tests for your plugins AND your themes. Behind the scenes, our scaffolding and tests works as described by Will Haynes in this post.

Other changes include migration to Fabric's new-style task declaration and updated documentation.

Unit testing tools

To scaffold/set up tests for your theme:

$ fab dev wp.tests.setup:largo-dev

This command:

  • Drops and recreates your testing database (which should always be throw-away, ephemeral)
  • Copies essential test files (e.g. phpunit.xml and a tests directory with test-sample.php and bootstrap.php files) to your theme or plugin directory if they are not already present
  • Installs the WordPress test framework to /tmp/wordpress-tests-lib/includes
  • Configure a wp-tests-config.php file and place it in /tmp/wordpress-tests-lib

With those files in place, you can run tests for your theme or plugin:

$ fab dev

Example output:

Screen Shot 2014-11-25 at 9.45.54 AM

Namespaces and aliases

The other big change we made was moving all commands to Fabric's new-style task declaration. Using new-style tasks gives us all the benefits described in Fabric's documentation on the subject.

While the deploy tools are not taking advantage of every feature of new-style tasks, they are better organized thanks to namespacing and aliases.

Here's some example output from fab -l:

Screen Shot 2014-11-25 at 10.00.07 AM

Here you can see each module (and submodules) along with defined tasks. Tasks use dot-syntax, which should feel more explicit and intuitive if you're familiar with Python (which is what Fabric is built on).

Also note that the command wp.migrations.s2m is an alias for the much-longer, sometimes-harder-to-remember command wp.migrations.single_to_multisite.

I'm very lazy, so anytime I can save some mental energy and type a bit less, I consider it a win. This is as true for commands I use very frequently as it is for commands I use once in a great while.


We also expanded the deploy tools' documentation to include all commands. You can find the documentation on Github.


Remember, the deploy tools were built with our situation in mind. We deploy to WP Engine, so some stuff is very WP Engine specific.

For example, the wp.fetch_sql_dump command only knows where WP Engine stores recent SQL dumps. The wp.maintenance.start and stop commands assume you are deploying to a host that uses Apache and that you have a .htaccess file in the root of your FTP server.

With that said, much of toolkit will work with any host provided you have (S)FTP access, including the push-button deployment rig I wrote about previously.

If you are using or thinking about using the deploy tools, have questions or suggestions, let us know.

Stealing the NPR App Template for Fun and (Non-)Profit

What we learned building an election app for INN members with the NPR visuals app template

Screen Shot 2014-11-13 at 5.40.59 PMLast week, just in time for the election, our team at the Investigative News Network (INN) launched Power Players — a state-by-state exploration of campaign finance and top political donors across the country. The project is a collaboration between thirteen INN member organizations who did their own reporting and analysis of the data we provided to them. To support this reporting, our team built a national app with easy to embed components.

As this was one of the first editorial projects we built as a team, we decided to start things off on a solid foundation by creating an app template — something that contains a library of components we might want to reuse for future projects and allows us to create those projects more easily.

Fortunately for us, NPR’s Visuals team has generously open sourced their app template, which we used as the foundation for our own. We shamelessly stole NPR’s code and set up an INN-specific template by following the steps outlined in Tyler Fisher’s excellent post “How to Setup the NPR App Template for You and Your News Org.”

It was a (mostly) painless experience but we learned some things along the way and wanted to share our experience to help others who might tackle this process in the future.

Why use NPR’s app template?

For one, we didn’t want to build our own toolkit for deploying news apps from the ground up.

When someone (or some team) builds and open sources a tool that addresses a problem you’re facing, using it will almost certainly save you time, money, blood, sweat, tears and heartbreak. Do yourself a favor and try really hard to seek out and use stuff that other smart people have already built.

The other motivating factor was that we’ve never had the chance to use NPR’s app template and a number of us have been curious. Being that this was INN’s first news app and we had a short amount of time to get something up and running, we thought this might make the perfect opportunity to take it for a test drive.

Setting up the app template for INN

Tyler acknowledges in his post that the process “seems like a lot.” But we discovered it’s just a matter of knowing where to find all the NPR bits so you can make the template your own.

In fact, it took just seven commits to completely scrub NPR specific stuff from the app template.

For your reference, here is our fork of the NPR app template and the code for the Power Players app itself.

Building with the app template

The structure of the Power Players app

Our project concept was relatively simple. There are a total of five views and their corresponding templates.

An example of a individual power player embed.

They consist of:

One of the goals for us was to create a resource that any of our member organizations could use to bolster their coverage of the elections — either by hosting information for an entire state, or including individual power player cards in articles covering campaign finance and the election.

Thus the embeddable versions of the state and power player pages. These are essentially the same as the normal templates, with a simple full-width layout and simplified INN branding (a credit link at the bottom of each embed).

The Kentucky Center for Investigative Reporting is one INN member making great use of the app. Here is a complete list of all the members organizations participating in the project and the stories they've published (so far).

The entire project is responsive (thanks to pym.js, yet another NPR project), made to look great no matter what size container the embeddable elements get placed in.

Snags and snafus

In working with the NPR app template we encountered some things that aren’t well documented (yet).

CSS and JS pseudo-tags

Tyler covers this briefly in another blog post on the app template.

What wasn’t clear at first was how the JS and CSS pseudo-tags interact across templates.

We ran into a problem where, in separate templates, we “pushed” or queued different sets of javascript files to be rendered. In both templates, we were passing the same file name to the render function, which resulted in the second file overwriting the first when deploying.

Here’s what NOT to do:

{# Template file no. 1 #}
{{ JS.push('js/lib/jquery.js') }}
{{ JS.push('js/lib/underscore.js') }}
{{ JS.push('js/lib/bootstrap.js') }}
{{ JS.push('js/lib/template_1.js') }}
{{ JS.render('js/app-footer.min.js') }}
{# Template file no. 2 #}
{{ JS.push('js/lib/jquery.js') }}
{{ JS.push('js/lib/bootstrap.js') }}
{{ JS.push('js/lib/template_2.js') }}
{{ JS.render('js/app-footer.min.js') }}

Once you realize that JS.render outputs a file, the contents of which are determined by preceding calls to JS.push, you realize that having different calls to JS.push before rendering to the same file just won’t work.

In this case, if template 2 is rendered after template 1, “js/app-footer.min.js” will be missing “underscore.js”, potentially breaking functionality in template 1.

Do this instead:

{# Template file no. 1 #}
{{ JS.push('js/lib/jquery.js') }}
{{ JS.push('js/lib/underscore.js') }}
{{ JS.push('js/lib/bootstrap.js') }}
{{ JS.push('js/lib/template_1.js') }}
{{ JS.render('js/app-footer-1.min.js') }}
{# Template file no. 2 #}
{{ JS.push('js/lib/jquery.js') }}
{{ JS.push('js/lib/bootstrap.js') }}
{{ JS.push('js/lib/template_2.js') }}
{{ JS.render('js/app-footer-2.min.js') }}

By making the filename passed to JS.render unique to each template, we can be sure we’re not clobbering any javascript files.

Flask’s url_for function and your project’s path prefix

Another issue we encountered was that the app template, using Flask’s default url_for function, doesn’t take into consideration your project’s path. That is, when you deploy your app to S3, it is meant to live at something like whereas the development server uses something like http://localhost:8000/ without the project slug.

For example:

<a href="{{ url_for('some_view') }}">Hey, a link to a page</a>

Renders as:

<a href="/some-view/">Hey, a link to a page</a>

What we want when deploying to staging or production is an URL that includes the project slug:

<a href="/project-slug/some-view/">Hey, a link to a page</a>

To remedy this, we created an app_template_url_for function to replace Flask’s standard url_for. The app_template_url_for figures out the current target environment (i.e. development, staging or production) and inserts the project slug as necessary.

View the source code here and here.

Another change we made to INN’s version of the app template is modifying the Flask app’s static_folder:

app = Flask(__name__, static_folder='www/assets')

View this change in context here.

What this does is allow you to use url_for to build urls for static assets kept in www/assets.

<link rel="shortcut icon" href="{{ url_for("static", filename="icons/favicon.ico") }}" />

This provides the flexibility to include assets outside of the CSS and JS pseudo-tag framework if you find yourself with the need or desire to do so.

Working with Member Organizations

The Power Players project presented other challenges, too, because of the number and diversity of INN member newsrooms participating.

First, the data needed to be analyzed and populated in the app template for about a dozen states. Campaign finance data is notoriously dirty (especially when trying to look at individual donors, as we were), plus we were combining data from different sources, so the cleaning and analyzing stage took longer than expected. Some member organizations also wanted more custom analysis, such as looking at local data only rather than statewide data as most members were. This forced us to make some compromises in the design of the app like using the state outline for California but labelling it “San Diego.”

A project such as this also takes a great deal of communication. INN’s director of data services, Denise Malan, held a kick-off conference call with members and stayed in contact with them as she was analyzing the data and the tech team was designing and building the app. We also provided members with instructions on how to add photos and customized content to the app while it was still a work in progress.

As is the case with all our editorial collaborations, INN members can publish stories according to their own timetables, and several ran their stories before the app was finished because we were working right up to the deadline on Election Day. Others have yet to publish because they choose to wait for updated data with post-election numbers.

Ideally, we would love for all members participating in a project to use our work, and we learned some valuable lessons in the process of building our first editorial app.

In future projects, we would like to have mockups of the news app ready as early as possible so our members are able to visualize what we will be providing and how this will fit with their reporting. We also want to provide a firmer deadline for launching an app so members can plan their publishing dates accordingly and leave time to implement the stuff we build. We’ll also do a better job providing the partners with documentation to make it as easy as possible for them to adopt our work.


We learned a lot in the process of building our first app, both about the NPR app template and also what it takes to manage a complex project working with so many partner organizations.

Will we use our fork of the NPR app template for everything? Probably not. We’ll continue to experiment and try out different things before settling on our default set of tools and templates. For projects where it’s a good fit or where we need to deploy something quick and easy, we definitely plan to use it as a solid starting point in building future apps.

Since this is our first app and we’re still learning, we’d love to hear your thoughts and feedback. You can find our team on Twitter @INNnerds or send us email at