December 5, 2013
For Episode 8, Brad and I once again get together to discuss our latest projects and noteworthy plugins, while also extending our discussion onto the topic of unit tests in WordPress plugin development, something that all developers should consider at least becoming familiar with, even if choosing not to implement them.
Show Notes:
- What we have been working on
- Brad: WP Migrate DB Pro beta and Media Files add-on
- Pippin: updating bbPress extensions to support some of the new features in bbPress 2.5 and also the new EDD_Graph API.
- Noteworthy Plugins
- Pippin: bbPress Custom Reply Notifications, featuring Stephen Edgar
- Brad: Amazon S3 & Cloudfront
- Pippin: bbPress Custom Reply Notifications, featuring Stephen Edgar
- Unit Tests
Photo credit: Thimo94 on Deviant Art
Transcript:
PIPPIN: Hello, everyone, and welcome to Episode 8 of Apply Filters, the podcast all about WordPress development. I’m your host, Pippin Williamson, along with my cohost, Brad Touesnard.
BRAD: Hey, everyone.
PIPPIN: Today we’re going to talk, kind of do our standard format. We’re going to talk a little bit about what we’ve been working on each, some noteworthy plugins, and then onto our main topic of Unit Test. So we’ll probably go ahead and get started here with talking about what we’ve been working on recently. Brad, why don’t you start?
BRAD: Sure. I’ve actually been working on Migrate DB Pro, the plugin that I sell.
PIPPIN: It’s kind of your standard project recently.
BRAD: Yeah. It takes up a lot of my time. And we just released the beta 2 of version 1.3 that’s coming out, well, as soon as we’re out of beta, I guess.
PIPPIN: Awesome.
BRAD: Yeah, yeah.
PIPPIN: Do you have a list of beta testers that you have, or do you send them out to buyers? What do you do? How do you get your beta testers?
BRAD: Yeah. So we kind of started like a little spreadsheet of people, basically, and then I moved that to a list in Campaign Monitor to easily, you know, tap into and send emails to. And then today, I was just like, you know what, I’m just going to invite everyone to join this list. And then I added an auto responder to it that would send them the details to get started beta testing. So as soon as they sign up for the email list, they get this email that says this is how you can, you know, get started. And I don’t know. It seems to be working okay, but still an experiment.
PIPPIN: Sure.
BRAD: What about you? How do you do Easy Digital Downloads? How do you —
PIPPIN: When it comes to beta testers, it kind of depends on the plugin. Like for EDD, we usually send out to our entire mailing list, as well as like Twitter and Facebook, that we have a beta. And then we’ll post about how people can get the beta, how they can test it, where to put feedback. But we don’t have a list of like specific beta testers. And I think, honestly, probably the difference between a commercial plugin and a free plugin. I’ve done beta tests with some of my commercial plugins before too, and I’ve always done it exactly like you do where you have that list of people that you send it to, and it’s much more of a closed beta.
BRAD: Yeah, yeah. I mean, I’ve just opened it up today, and it’s just exploding. We only had like 20 people, and now it’s like, you know, 5 times that today. Well, it was, like a half hour after I sent the email, it like quadrupled in size.
PIPPIN: The number of people that are beta testing or the feedback coming back from those people?
BRAD: Well, they sign up for the email list, so they’re interested —
PIPPIN: Oh, I gotcha.
BRAD: — in getting the beta, so yeah.
PIPPIN: Do you actually get; do you get a pretty good kickback on beta testers in terms of quality feedback? I’ve always noticed that it’s hit or miss. Like sometimes I’ll send out a beta, and I’ll get like dozens and dozens of pieces of feedback. And then other times I’ll send out a beta and I get like one person.
BRAD: I guess it depends like what the new features are. In this version, there’s a lot of new features that people have been asking for, so they’re super excited to just try it out. I think that has a lot to do with it.
PIPPIN: Yeah, I guess that makes sense because you have the new media files add-on, right?
BRAD: Yeah, exactly, so that’s what people have been requesting a lot, so they’re ‑‑
PIPPIN: That’s cool.
BRAD: — pretty excited to try it out.
PIPPIN: Nice. I hope that goes well for you.
BRAD: Yeah. What have you been working on lately?
PIPPIN: This morning, I was primarily doing some bbPress extensions. bbPress 2.5 came out recently, which included a big new feature for like form subscriptions. So if you’re familiar with bbPress, there’s always been the ability to like subscribe to topics, and so you can get an email any time that somebody posts a reply to a topic that you’re subscribed on. But there’s never been a way for someone to subscribe to a forum to get notification any time a new topic gets posted to that forum. So that was introduced in bbPress 2.5. And so I was updating some of my bbPress extensions to take advantage of that feature.
BRAD: Interesting.
PIPPIN: Yeah.
BRAD: Are any of your bbPress expressions commercial, or is it all just open source? Free?
PIPPIN: No, all of them are free.
BRAD: Okay. Gotcha.
PIPPIN: Most bbPress extensions that I’ve done, I have about ten of them now, I think. They’re almost all I built like for my own use, and not to say that that couldn’t be commercialized by any means, but I just, I really like them being free extensions. And most of them are pretty small extensions too, like there’s nothing; there’s no major extension that would warrant a $20 or $50 plugin. And I don’t really like $5 plugins.
BRAD: Yeah.
PIPPIN: They tend to cause more problems than they’re worth in terms of the amount of support time.
BRAD: Exactly. Yeah.
PIPPIN: I have some old like $5 plugins, and I keep meaning to pull them off just because getting like 5 tickets a month on them is more than they generate in revenue.
BRAD: Yeah. I mean, are you talking like $5, and that’s it forever?
PIPPIN: Yeah, yeah. Like I’m talking about little widgets that are like sold on Code Canyon and places like that.
BRAD: Yeah. I can see where —
PIPPIN: A lot of times — I had done them originally just kind of for fun. And the problem with it is really that once you have a price on it, whether you want to support it or not, you should — at least I personally believe — you should be obligated to help people when they have problems with it.
BRAD: Oh, yeah. Well, the expectation is definitely that you have to support it.
PIPPIN: Yeah.
BRAD: Yeah.
PIPPIN: Yeah. So anyway, so for these —
BRAD: I gave you $0.25, then you must —
PIPPIN: You will help me.
BRAD: Yeah, you must give me the world, right?
PIPPIN: Yeah.
BRAD: Like as soon as anyone opens their wallet, the expectation changes, right? It’s just the way it is.
PIPPIN: Yeah, absolutely. And I don’t think that’s really wrong. I think if somebody is paying you money, they should have at least some expectation of some assistance if needed. But anyway, so all of my bbPress extensions are free, so I was doing that.
And then right now I’m kind of working on a new API for EDD. It’s a graphing API, so we have reports in the plugin that allow you to see like sales and earnings, and then those might be carried over to some extensions. So like for example, if you’re recording commissions for multiple authors, then you might be able to see a report of like commissions recorded per day.
But so these graphs that we built through these reports, they look really nice, but they’re really horrible to implement. Like they’re hard to build. They’re kind of janky. They’re not flexible, et cetera.
BRAD: What are you using to build them? Are you using like a JavaScript thing?
PIPPIN: Yeah, we’re using a jQuery library called a flot.
BRAD: Yeah.
PIPPIN: Which works really well, and it looks really nice. And the implementation, like the pain points, have nothing to do with flot. It’s just the way that I’ve built it. I didn’t build it to be flexible from day one. So what I’m building is a new graphs API that will allow an extension or somebody to basically just pass an array of data: one array for one axis and another array for the other axis, like X and Y. And it will just do all the graphing for you.
BRAD: Oh, nice.
PIPPIN: So that’s what I’m trying to build right now. Right now I’m just kind of in the figuring out how the heck to do it, how to structure it, and then hopefully it’ll be implemented some time soon.
BRAD: Yeah. I’ve worked a bit with flot as well and, yeah, it’s — I don’t know why, but it always seemed confusing or painful.
PIPPIN: It took me a long time to figure out how it worked.
BRAD: Yeah, and just like to create, to get the data from PHP into the graph, like using flot, I have found it a little cumbersome. It’s probably just because I wasn’t used to it, but yeah. The code that I wrote wasn’t that great either.
PIPPIN: Mine is kind of scary looking.
BRAD: Yeah.
PIPPIN: It’s a lot of JavaScript embedded inside of a PHP file, and it’s just not pretty.
BRAD: Right.
PIPPIN: So hopefully I’m going to fix that, so that’s what I’ve been working on.
BRAD: Cool.
PIPPIN: Should we jump over to our noteworthy plugins?
BRAD: Sure. I don’t know if they’re that noteworthy. They’re just stuff that we’ve worked on.
PIPPIN: Sure. Yeah, we’ll try and call them noteworthy this time.
BRAD: Right. Yeah.
PIPPIN: We say that because both the plugins that we chose were our own plugins today.
BRAD: Right.
PIPPIN: Why don’t you go ahead and start with yours?
BRAD: Sure. Mine is called Amazon S3 and CloudFront. And this is a plugin that I forked. So the plugin was originally called tantan-s3, a plugin by Joe Tan that was, I think he released it in 2009 or something. And a couple years ago, I forked it just for my own personal use, and I needed to make some changes to it, and I fixed up all the, you know, PHP notices and warnings and stuff like that. And I’ve just been using it kind of behind the scenes. And then, at the beginning of this year, I cleaned it up a little bit more, and then released it on .org.
PIPPIN: So I think I need to look into using this plugin, actually. So I have a question for you.
BRAD: Okay.
PIPPIN: So, first of all, tell me if I’m right. It takes any file that you upload through the media library and copies to Amazon S3, and then any time that media library is used on the site, it pulls from S3 instead of the media library, right?
BRAD: Exactly. Precisely.
PIPPIN: Cool.
BRAD: And it does have to go through your server though.
PIPPIN: Sure.
BRAD: So when you upload a file, it ends up on your server, and then it uploads it to S3.
PIPPIN: Sure. Does it work with any file uploaded to the media library? And by that I don’t mean like just any file, but like let’s say that I’m using the WordPress function like WP sideload image. Do those get added to the media library too?
BRAD: Yes.
PIPPIN: Or do they actually have to go through like the WordPress admin upload screen?
BRAD: I believe — I’m not 100% sure on the side loading. I’ve never tested that. But that’s basically you’re downloading an asset from a URL and sticking it into WordPress. Is that right?
PIPPIN: Yes.
BRAD: Yeah, and I’m pretty sure it does upload those to S3. I’m pretty sure anything that ends up in the media library goes to S3.
PIPPIN: Okay.
BRAD: And I’m almost 100% sure on that.
PIPPIN: I wonder if — this is something I’d want to look into and see what would happen. So like in EDD, for example, we have when we upload a file to a product, we actually stick it in a special directory inside WP content uploads that has HD access and other protection on the directory to keep those files from being shared.
BRAD: Mm-hmm.
PIPPIN: Is there a way to disable certain files from being uploaded?
BRAD: Disable the — just from being uploaded to S3 at all?
PIPPIN: Like let’s say I want to exclude anything that is inside a EDD directory, as an example.
BRAD: No, there’s no way to do that. I mean, you could definitely hook into the hooks that are available and accomplish that in code. But there’s no like UI to do that yet. But that’s definitely something that could be added in the future. And a good use case would be like say you wanted all attachments to the post type event, right? Any attachment to events, maybe you want those to be private. You don’t want them publicly downloadable.
PIPPIN: Right.
BRAD: So maybe you could do that through a UI. That would be kind of a cool feature, I think.
PIPPIN: That would be cool. All right. Nice.
BRAD: But anyway, yeah, so actually the story is not done. I’ve actually completely rewritten this plugin just a couple months ago, so it’s no longer kind of like a few fixes. Yeah, it’s completely redone. And I actually split it out into two plugins, and so you have like a parent Amazon Web Services plugin on .org now, and that just houses the AWS SDK, which is massive. It’s 10.2 megabytes actually. And so any plugin can, you know, use that as its parent plugin.
And then that’s what the Amazon S3 and CloudFront plugin does. So if you install just the Amazon S3 and CloudFront plugin, it’ll say, “Whoa, whoa, whoa. You need this other plugin.”
PIPPIN: Sure. So Amazon S3 and CloudFront is really just an extension for Amazon Web Services.
BRAD: Pretty much, yeah. That’s a good way of saying it, yeah. And so it doesn’t —
PIPPIN: That’s cool.
BRAD: It doesn’t have all, you know, the bulk that it would. So say like in the future I’d like to build an Amazon SES plugin, which is the simple email service that would hijack the email sending in WordPress. And I could use the Amazon Web Services parent plugin for that as well, right? I wouldn’t have to kind of double the efforts there.
PIPPIN: Nice.
BRAD: Yeah.
PIPPIN: That’s very cool. I might have to give it a try and see how it works.
BRAD: Yeah. Yeah, I’m looking forward to keeping up with it and kind of just making I better.
PIPPIN: It’s one of those — I think it’s a great like utility plugin. There’s those plugins that are just kind of fun to use, provide cool little bling for your site. And then there’s plugins like this that you’ve written that are really useful in terms of the overall functionality of your site, like how well your site functions, keeping it as a well-oiled machine.
BRAD: Yeah. I mean, there’s a number of other plugins out there that work with Amazon S3.
PIPPIN: Sure. It’s not a new thing.
BRAD: Yeah. But the thing is that they usually do other things as well. They’re like kind of like they do everything, whereas this thing does something very, very specific, and I try to keep it like, you know, very focused.
PIPPIN: Sure.
BRAD: I feel like plugins that are like all in one, something or other, they kind of scare me a little bit because it’s like, okay, but, well, do I need all that stuff? And how much stuff are you running that I don’t need? And, you know, that kind of thing.
PIPPIN: Sure, totally. I love lightweight plugins, and I think this would be a great example if you wanted to — if you were utilizing a CDN such as Amazon S3 for your stuff, but you didn’t want to use something like W3 Total Cache that has all of that extra stuff in it. Let’s say you only wanted to use it for the CDN aspect, this would be a great alternative.
BRAD: Yeah.
PIPPIN: For some of the stuff. Like if you’re only doing it for media like files. Obviously that doesn’t take care of your CSS and your JavaScript. But for your media files, that could be huge.
BRAD: Yeah, exactly. So what’s your plugin?
PIPPIN: I chose bbPress Custom Reply Topic Notifications. This is one of my plugins, and it’s one of the ones that I actually updated this morning. And I chose it for a couple reasons. One, I really love bbPress. bbPress is a plugin that I really like working with. I’ve done quite a bit of contribution to the core plugin as well. So bbPress 2.5 just came out, as we mentioned earlier, with the new forum subscriptions.
And so this plugin, bbPress Custom Reply and Topic Notifications, is one that I wrote about a year ago, I think. And it allows you to customize the email that gets sent when a reply is posted to a topic you’re subscribed to. So if you have a topic in a forum, and you subscribe to it, somebody else comes and posts a reply to it, you’ll get an email that says, “Hey, Brad Touesnard just posted a reply to this topic. Clear here to read it.” Well, since bbPress 2.5 introduced forum subscriptions as well, this plugin has now been extended to allow you to customize the email that gets sent out when a new topic gets posted to a forum that you’re subscribed to.
The reason I wanted to mention this in our noteworthy plugin section this morning is not just because I like the plugin, but because a cool thing happened yesterday. So Stephen Edgar, who is one of the core committers to bbPress, he’s done a lot of bbPress plugins, he does a lot of bbPress support, and he does a lot of core bbPress development. He sent me a big pull request yesterday that actually added complete support for the new topic notifications. So this, I had not really had any plans to update the plugin to support topic notifications as well, but then Stephen just sent me this pull request that did all of it, and that was really, really cool. And so I wanted to feature it because it brings up the idea, the topic of community driven development.
Just because you have written a plugin does not mean that you are the only person that can contribute to that plugin. If you put your plugin up on GitHub or put it up somewhere where it’s easy for other people to contribute to, there’s no guarantee that somebody is going to, but it makes it a lot easier for that person that does decide to do it. And so this was a good example where Stephen, who is another bbPress developer, he uses the plugin, and he wanted the feature, so he just went ahead and added it and sent it as a pull request. So I pushed up an update this morning that had that. So it’s really a thanks to Stephen for doing that.
And I think it’s just — I love the idea of community driven development. Even for small plugins. I work on Easy Digital Downloads every day, which has about 80 contributors to it now, maybe a few more than that. But it’s a huge plugin, and a lot of people use it, and a lot of people are making a living off of it or contributing to their living in some way, so it’s a little easier for people to justify contributing. This is a little, tiny plugin that’s been downloaded a total of, I think, 700 times. But that doesn’t mean that other people can’t contribute to it.
BRAD: Yeah. I mean, if someone else is finding it useful and they need, you know, something to be changed in it, the best way for them to, you know, take part and contribute to it and then, in the future, you know, you add something to it so then they get the benefit of that.
PIPPIN: Absolutely.
BRAD: I mean, one of the things I do is I put a link on the .org page for my plugins to GitHub saying, you know, request features, report bugs, do all that in there.
PIPPIN: I do the exact same thing.
BRAD: And I think a lot of plugin developers would probably benefit from that as well. So if you don’t have that link to your GitHub page on your .org —
PIPPIN: Ironically, I don’t have it on this plugin.
BRAD: That’s funny. So maybe it’s having the reverse effect.
PIPPIN: Yeah. So in order words, I need to take your advice and go put a link to GitHub on this plugin.
BRAD: Yeah.
PIPPIN: But I think you do bring up — seriously, you do bring up a good point though that if you have a plugin on .org, and you have that plugin on GitHub as well, put a link to it that says it’s on GitHub because I think you might be surprised at how often people are actually open and interested in contributing to a plugin, whether it’s a bug fix or a feature addition. But I think the biggest reason that people don’t is because it’s difficult. But if you make it easy by making it very apparent where they can send these submissions, and sometimes those submissions are just like language translations, which are awesome too. But making it easy is huge.
BRAD: Yeah. I completely agree.
PIPPIN: Cool.
BRAD: I think you need to close that loop. That’s why, you know, you link to GitHub. And then on GitHub, link to .org, you know.
PIPPIN: Yeah, certainly.
BRAD: And you make this kind of circular reference. The way I run the Open Source projects on .org and GitHub is that I use the issue tracker on GitHub as kind of like the central issue tracker. So any support requests that end up on .org in the forums, I reply to them there and everything. But if it’s an issue that is going to be addressed in the plugin, I’ll kind of move it there.
PIPPIN: Go to GitHub.
BRAD: I’ll go to GitHub.
PIPPIN: Yeah, I do it the exact same way.
BRAD: Yeah.
PIPPIN: I think of it as, like, GitHub is support for developers. .org is support for users.
BRAD: Yeah.
PIPPIN: And there’s some overlap for sure. But like let’s say a user reports a problem. If it’s simply not sure how to use the plugin and not sure where a setting is, I help them on .org. Now if I find out that what they reported actually is a bug, I will go log that on GitHub and then take care of it there.
BRAD: Yeah, exactly. And I manage releases, like release milestones, on GitHub as well.
PIPPIN: Yeah.
BRAD: You know, the tools are just not there.
PIPPIN: I don’t do anything on .org aside from a little bit of user support and hosting the plugin.
BRAD: Yeah, exactly, the same here. I actually use Scribus scripts to —
PIPPIN: Deploy.
BRAD: — deploy to .org. Do you use those?
PIPPIN: I use one from Brainstorm Media from Paul Clark, which I think he actually forked from someone else. But it’s all — and they’re all basically the same concept. You just run a script, and it takes your GitHub version and pushes it to .org for you.
BRAD: Yeah. Yeah, so —
PIPPIN: Super handy.
BRAD: Or my SVN history on .org is God awful though.
PIPPIN: Actually, no, that’s not true. If you ever talk to Otto, he will yell at you if you try and use SVN on .org as an actual version control system.
BRAD: Oh.
PIPPIN: He will tell you that they actually only want people to have one commit for versions.
BRAD: Really?
PIPPIN: Uploading version 1.7. Yep.
BRAD: Oh, wow. That is very — that is the —
PIPPIN: That’s their preferred method.
BRAD: That’s the opposite of what I would have guessed.
PIPPIN: Yep.
BRAD: Why is that? Do you know?
PIPPIN: I think it’s just because it’s not designed to be your repository for your versions.
BRAD: Oh, okay.
PIPPIN: I mean, it’s simply the distribution. Now obviously they have some version control in there because you can go back and download past versions. I suspect a lot of it has to do with the size. I mean, there’s 28,000 plugins on .org. It’s a little large.
BRAD: Yeah. Yeah.
PIPPIN: And that doesn’t count the themes as well.
BRAD: Yeah.
PIPPIN: Though technically they’re in a different kind of system. But still.
BRAD: Right, so the —
PIPPIN: Yeah, no, so you’re actually doing it the way that they prefer.
BRAD: That’s — well, I learn something new every day right there.
BRAD: Well, before we run out of time, why don’t we go ahead and jump onto our next topic because it’s a good one, and we could probably talk about it for a long time.
BRAD: Sure.
PIPPIN: Unit testing: so this is actually one of our listeners requested this, and I apologize ahead of time if I pronounce your name wrong, but it was submitted by Ante Sepic. And he basically wanted to know about unit test, and he asked a couple things. How important are they? How important are they for plugins? Should you use them — should you write unit test for your plugins? And how do you write; how do you make use of unit test?
This is a really large topic, so obviously we’re not going to be able to hit everything on it, but we’ll talk a little bit. And I think it’ll work well because Brad and I come from kind of two, not really two different backgrounds here, but like I am actively using unit test for a couple of my plugins, and Brad, if I remember right, you’re not yet. Correct?
BRAD: No. No, I’m not. I’ve done all the research.
PIPPIN: Cool.
BRAD: And just never took the plunge.
PIPPIN: Cool. So for anybody who doesn’t know, a unit test is basically an automated test on your code base, breaking the code base up unto tiny, tiny chunks. So you basically will have a test that will check each of your functions. So let’s say that you have a function that determines if some user can view a particular page. Let’s assume that you have a plugin that restricts content or something like that.
So you have a function that says: can user view this page? And so you will have a test, like an automated test that runs, and it will determine if that function is running correctly, is functioning correctly. And then you’ll have a unit that will, for example, test that your functions are returning appropriate values.
So in EDD, for example, we have a function that calculates tax. And this function will take the tax rate set in the store settings. It’ll take the current location of the customer we’re calculating tax for, so let’s say they’re in the United States in the state of Alabama. So we go look up the Alabama state sales tax rate, et cetera, and then calculate it.
So we will have a unit test that will actually use that function and pass at arbitrary amounts, so such as $54, $523, $1,200.23, et cetera. And we’ll have this unit test that will pass all of these values through the function and make sure it always returns the expected value. And if the function doesn’t, doesn’t return the expected value, our test fails.
BRAD: Right. And it shows up in your unit test report as a big red thing, right, doesn’t it?
PIPPIN: Right. It says, hey, we had a failure over here. We expected 3.74, but we got 5.2.
BRAD: Yeah.
PIPPIN: And so it basically gives you an indication there’s a bug somewhere.
BRAD: And the reason this is important is because maybe, you know, you guys were working on something completely unrelated to this, but the code changed just enough that it disrupted that function, you know, or maybe it disrupted the input into that function. And so that’s why — and so you weren’t even testing that function necessarily. You were testing something else.
PIPPIN: Absolutely.
BRAD: And so this is where, you know, unit tests are super important because they pick up these bugs in the things that you haven’t really tested in your development testing.
PIPPIN: Well, let’s say that your — unit tests are really, really important for really big plugins. They’re important for all plugins, but not nearly as important for small plugins just because it’s much easier to test them thoroughly.
But let’s say that your plugin has 30 files and 500 — 20,000 lines of code, for example, and you change something. And like what Brad was saying, you might change something somewhere and not realize that it’s going to have a consequence somewhere else. So your unit tests help catch those edge cases.
BRAD: Right.
PIPPIN: We actually had a perfect example of this in EDD recently. I was working on the tax system in the plugin. I was actually rewriting it. And so we have this function that calculates the tax amount. And we used to, when we store a payment, we would — the way that we calculated the tax for that payment and then stored it in the payment meta was kind of funky, but I didn’t realize this. But my unit tests were failing.
So I was creating a purchase, and I stored the tax for it, and then I was using — I was running a function to retrieve the tax amount for that payment. And I was doing this through my unit test, and my unit test was failing every time, and I couldn’t figure out why. Well, what I realized was that the function, the code that actually stored the tax in the payment originally was failing due to a change that I had made elsewhere in the tax system. But it didn’t appear to fail, except for in the unit test. And it’s something that I would have never caught if it wasn’t for those unit tests.
BRAD: Huh. Interesting.
PIPPIN: Just because the value was different.
BRAD: So is this function, so like say this calculate tax function, what are the parameters for that function?
PIPPIN: So in this case it has three parameters. It has the amount, so the amount that you’re calculating tax on. Let’s say $50. Followed by a country and a state or province. So you could use those to go look up the tax rates that are needed for this particular calculation.
BRAD: Right. And see, this is the big thing I feel with being aware of how unit testing works because sometimes you will write that function, and you’ll just have one parameter, the amount. And then in the function, you’ll figure out the country from, you know, the database, from the settings in the database and stuff. But then if you do it that way, it makes it very difficult to unit test that function because the database —
PIPPIN: Right.
BRAD: — is an unknown value. It could change. And so your unit test —
PIPPIN: Right. Let’s say it might work correctly when you’re calculating based off of the state of Alabama in the U.S., but then fail when you’re working in Ontario, Canada.
BRAD: Right, right.
PIPPIN: And so having — number one, writing a function that is easily unit testable is really important, and there’s a whole bunch of different things that go into that. But then also just having the test that will actually go through and run multiple tests. So when we test our calculate tax function, we actually do what are called assertions. Basically, we assert that some value is what we expect it to be.
We will actually run an assertion on like ten different countries/states and make sure that every single one of them comes back as we expect it to be. So that way, even if regardless of what our database tells us, if we pass this value, this is what we want to get. And we want to make sure that we get that.
BRAD: Right. I think one of the big criticisms of unit testing, although it seems that anyone that does test, that has moved to test driven development, never comes back. But the people that criticize it are usually on the basis that, well, it’s going to add like, you know, double the time to develop because these tests take like, you know, as much time to write as the code itself. What do you say to that?
PIPPIN: I say that the first time that a unit tests help you track down a bug that you wouldn’t have caught, it was worth it.
BRAD: Yeah.
PIPPIN: That, but it goes further than that too. It’s a lot easier to track down a bug, I think, when a unit test fails than it is just to track down a bug when you get a report from odd behavior. Let’s say, sticking with taxes for a moment. Let’s say that a user reports that for some reason a customer was charged the wrong tax rate, and so you start thinking, hmm, how the heck do I test this.
Okay, well, let’s see if I can replicate it by, I’ll go through the checkout process. I’ll see what tax I’m charged. Maybe I’ll change my country to something else. I’ll set my tax rates up the same way the user had them. And maybe you’re able to replicate it.
Well, if you have really a really good unit test, you should have a much better idea because, if one of those fails, it’s going to tell you exactly where it failed and maybe — it’ll give you a better idea of why. For example, when a unit test fails, let’s say it’s my calculate tax test, there’s ten assertions in that test, maybe more, so when that test fails, it’s going to tell me exactly which assertion failed as well. And that immediately gives me a better idea of where the bug is.
BRAD: Yeah.
PIPPIN: The other thing, this one is huge for us. Unit testing is awesome; automated unit testing, even cooler. So like for EDD, we have it set up with a system called Travis-CI. And what it does is it runs our entire suite of unit test every single time we push to the GitHub repository.
So every single time we push, it triggers and automatic run of the unit test. So we will actually get a report any time a unit test fails. So if we make a commit and it causes some test to fail, we will get a notice about it, and it will say this commit made this particular test on this line number fail.
BRAD: Mm-hmm, and —
PIPPIN: And so it’s a really nice peace of mind.
BRAD: Does it — I’ve heard that you can actually reject the push, so you can run it actually prior.
PIPPIN: Yes, you can.
BRAD: Yeah, that would be kind of cool.
PIPPIN: Which would be huge. I think it’s really important, like if you had a production code base that you were pushing to, and so you will have unit tests running on your production code base, or maybe it’d be on your staging code base. I’ve never actually done this. But so you would have these tests run. And if it detected a test failed, it would reject it before the commit is actually made live, before it’s actually put in.
BRAD: Right.
PIPPIN: Which is pretty cool.
BRAD: Yeah. Yeah, it’s really good.
PIPPIN: So, I mean, unit tests, I think we could go on forever about them. I think I just want to — this has been really barely touching the surface of what unit tests are. So we might even — maybe we’ll have an entire episode one day that just talks about unit tests. It would be great if we got someone, another person on that had done a lot of unit testing.
BRAD: Pippin, if there’s one little boy or girl out there that we’ve changed to a unit tester, I think we’ve done our job.
PIPPIN: But, yes, I mean, like we’re barely scratching the surface here of what unit testing are, but it’s something, if you have a large plugin, absolutely go look at it. I mean, like the EDD code base is enormous now, and I’m so glad that we have unit tests on it.
We’re sitting on only 33% code coverage though, so there’s a lot of code that does not have a unit test written for it. So start early.
BRAD: I think it’s — we should mention also that WordPress Core has a full unit testing suite that you can set up.
PIPPIN: Oh, yeah, they do.
BRAD: And run all the tests that the core developers do, so that’s another place that you can….
PIPPIN: Which is really cool. I think there’s a post on make.wordpress.org that actually shows how you can go and get that and how you can run the test. Don’t be intimidated with unit tests because they can be kind of hard to set up the first time mostly just because, if you don’t fully understand and are not fully familiar with how the system works, it can be a little overwhelming just because it’s kind of convoluted at times. Power through it because once you have them set up, they are invaluable.
BRAD: I agree. Well —
PIPPIN: All right. Should we wrap it up?
BRAD: Let’s do it.
PIPPIN: All right. Thanks, everybody, for listening. This is Episode 8 of Apply Filters, the podcast all about WordPress development. We will be back in two weeks with Episode 9. Thanks, everyone.
BRAD: Thanks, everybody.
Thanks for the podcast, this episode was a good intro to unit testing, even if only the last 10 minutes was spent on the subject. 😉
I know you ran out of time, but I was expecting to hear a lot more on the “how” part, which you didn’t get into at all really, so I thought I might chime in here to add to it.
I know there’s two different approaches to setting up unit tests for plugins right now, and the first is what eventually made it into WP-CLI, which downloads WordPress and checks out the WordPress unit testing framework files, and just the framework itself, not the core tests. This will run your plugin unit tests only.
Then there’s my own version that I’ve given a presentation on before that expects you checkout the entire WordPress repository including the tests, then requires that you copy your plugin with the template files into the copy of WordPress, and auto-activates your plugin while running your tests. This also allows you to even run all of the core unit tests with your plugin activated, something the first approach doesn’t allow. Current downside is that I haven’t had the chance to update my template files to use the new develop.svn.wordpress.org repository yet, it still uses the old unit tests (I’ll be updating that soon though).
Either approach works fine with Travis CI too.
Some extra links that might be helpful:
1. WP-CLI – https://wp-cli.org/ (for using “wp-cli scaffold plugin-tests”)
2. My own plugin tests template: https://github.com/tierra/wordpress-plugin-tests
3. My WordCamp presentation slides: https://speakerdeck.com/tierra/unit-testing-wordpress-plugins
Thanks for the great comment and links!
You’ve done your job – I am now looking in to unit testing and plan to set up a better process for myself in the future 🙂
Great to hear!