Today some code! That's better than rhetoric innit? I'm sure it won't be as popular though.
OK, so I have been too busy recently with ColdFusion 11 and various other odds 'n' sods to either continue writing about unit testing, and also I have been neglecting the CFLib.org submission queue. So today I am remedying both of those in one fell swoop.
This article is not really "TDD" or "BDD" as the code I am testing is a fait accompli, so the tests are not driving the development. However this is perhaps a good lesson in how to retrofit tests into functionality, and what sort of things to test for. There's a bit of TDD I suppose, because I end up completely refactoring the function, but first create a test bed so that that is a safe thing to do without regressions.
On CFLib there is already a function
firstDayOfWeek()
, but someone has just submitted a tweak to it so that it defaults to using today's date if no date is passed into it. Fair enough. Here's the updated code:function firstDayOfWeek() {
var dow = "";
var dowMod = "";
var dowMult = "";
var firstDayOfWeek = "";
if(arrayLen(arguments) is 0) arguments.date = now();
date = trim(arguments.date);
dow = dayOfWeek(date);
dowMod = decrementValue(dow);
dowMult = dowMod * -1;
firstDayOfWeek = dateAdd("d", dowMult, date);
return firstDayOfWeek;
}
Nothing earthshattering there, and I basically scanned down it going, "yep... uh-huh... oh, OK, yeah... cool... yeah that seems OK". And I was about to just approve it. Then I felt guilty and thought "ah... I really should test this. And I'll use TestBox and its BDD-style syntax to do so, and I can get a blog article out of this too.
It's just as well I did test it, because it has a bug. Can you see it?
I sat down and looked at the code, and went "right... what do I need to test?". I came up with this lot:
- if I don't pass in a date, it returns the first day of the current week;
- if I do pass in a date, it returns the first day of that week;
- if I pass in the date that is the first day of the week already, it passes back that same date;
- if I pass it "not a date", it errors predictably.
// TestFirstDayOfWeek.cfc
component extends="testbox.system.testing.BaseSpec" {
function beforeAll(){
include "udfs/firstDayOfWeek.cfm";
variables.testDate = now();
variables.testFirstDayOfWeek = dateAdd("d", -(dayOfWeek(variables.testDate)-1), variables.testDate);
}
function run(){
describe("Tests for firstDayOfWeek()", function(){
it("returns most recent sunday for default date", function(){
expect(
dateCompare(variables.testFirstDayOfWeek, firstDayOfWeek(), "d")
).toBe(0);
});
it("returns most recent sunday for current date", function(){
expect(
dateCompare(variables.testFirstDayOfWeek, firstDayOfWeek(variables.testDate), "d")
).toBe(0);
});
});
}
}
Notes:
- I've got the UDF saved in a separate file, so just include it at the beginning of the tests;
- I set some helper variables for using in the tests;
- I'll get to this.