← Back

Testing thoughts

While I've been playing around with mocha and chai for a about a year now, I admit to being a less than great tester. It's one thing to know how to use a testing library. It's another thing to know WHAT to test in your code, and another-nother thing to know how to write a test BEFORE you've written code. It's something I'm still getting the hang of for sure. Though the more I push through it, the better I get, and the more I can see why I absolutely need it.

In any case here are some things that I've been thinking about:

Testing by state not by feature.

At work, I was recently testing a tricky bit of ui. It was the kind of code that has way too many ternary operators for its own good. A sure sign that it needs to be rewritten probably. My first stab at writing the tests was to focus on features (this circle should be red under these conditions but yellow under these other conditions). This led to some painfully un-dry code in which I was describe the potential states for every ui component over and over again and not relying on the power of a before each. In a rewrite of the tests we instead focused on states (ex: under this particular set of circumstances the circle will be red, the user will see this message, this button will be disabled, etc.).

If it's hard to mock, you might want to refactor.

In general I think part of why I was having a hard time writing tests before, was because my code just wasn't very good. What I mean by this is that my modules were relying on too many inputs for me to easily mock, and were responsible for accomplishing too many tasks. I recently started reading this book by Sandi Metz and have really been appreciating her thoughts on always trying to do the "smallest possible thing", and break out my functions and components. I used to be impressed by a complicated looking code file that took up 800 lines. Less so these days. Well written small bits of code is easy (or at least easier) to write tests for. And of course writing tests, makes it easier to write small bits of code. In short if you can't figure out how to mock the inputs your code is relying on to write some tests, you might want to do yourself a favor and try moving back a step in the chain.

Async error testing

I had some difficulty recently trying to figure out how to test if some functionality I had in a catch. My catch was supposed to in addition to catching an error from the server, then throw a new error to the user and then setting a property somewhere so as to ensure we knew we were in an errored state. I had some trouble figuring out how to run this async code without my tests actually erroring out themselves. Eventually I came up with a solution where I wrapped the original code in a promise to test with:

beforeEach(() => {  
  this.promisedDownload = Q.when(erroredDownload());
});
it("throws foo", () => {  
  this.promisedDownload.catch((err) => {
    err.message.should.equal("foo");
  }
});
it("sets some other property elsewhere", () => {  
  this.promisedDownload.catch((err) => {
    someProperty.should.equal("bar");
  }
});

But now I'm realizing that of course cool libraries already exist to solve these problems like chai as promised If I were to do it again I might play around with things like this (examples borrowed from chai as promised's docs):

return promise.should.be.rejectedWith(Error)  

and

it("should change the state", function (done) {  
    otherState.should.equal("before");
    promise.should.be.fulfilled.then(function () {
        otherState.should.equal("after");
    }).should.notify(done);
});

Neat right? Wish I had just sat for a minute and really read the docs, rather than banged my head on this one. It's all pretty much there

TDD4Lyfe

On a more personal note, after getting kind of overly enthusiastic about testing, I decided that instead of new years resolutions I would try to create tests for myself (in the form of a google form sent to myself once a week) this year that I would initially fail but strive to pass each week/month. Some are health related or career related. One of them is of course blogging as I've really dropped the ball on that one. And of course the big take away is not on any particular implementation but on the results. I don't care if I blog a little each day or have a marathon writing session once a month. My goal is to post once a month and I'll play around to see what works. I'll keep you going on this experiment of mine but so far so good!


← Back home