Characterization Tests

I got a question about TDD and Characterization Tests and wish the other day, and felt like the answer might be helpful to others. Characterization Tests are useful when you have untested code.

Hey [Redacted],

Basically, you can just write a test and see what the output value is, and then just fill in the blank with that value. So if you had a function like this:

function adds(first, second){
  return (first+second);
};

Without knowing anything about the function other than it takes two parameters, you can write this:

console.log(adds(3, 4));

And then you know that actually equals 7, because you get the output. So then you can write the assertion:

assert(adds(3, 4)==7);

You can use this (yellow highlighted) method freely. You don't have to be in a test framework. Just make sure to assert = require('assert') at the beginning of your program if you need to.

Some test frameworks come with more specific assertions that tell you what something was supposed to be, but only if you use the special syntax. Usually, it's something like expect(adds(3, 4)).to_equal(7) or something. So the green option is to just assert in that syntax, a value that you don't actually expect. Something like expect(adds(3, 4)).to_equal(nil). Then the test reporter will tell you the actual value, and you can just replace nil with whatever value you got back (should be 7 in this case).

So back to your original question a bit, you can't really use assert to get the value. It will just raise an error if the code inside of it is falsey. It won't tell you the value that the method gave (which is what you want, because with characterization tests, you're just looking for an easy way to write a working assertion to increase your test coverage/confidence in the code). When I don't have wish available, I go for the yellow highlighted method (console, then assert). I rarely do the green highlighted way, but if you prefer that way, it's the same exact principle.

As for TDD, I'd recommend going through the card game examples in the book until it becomes intuitive. Write a lot of simple tests for simple functions. Using a big test framework or big app framework take you away from more flexible and direct methods (this might make more sense if you're into functional programming, which is also in the book). It's extremely useful to have a bit of practice with. The best thing you could do is write your own small functions test first. And you can do them as assert statements.

For example, you could write this program and run it (you'll see errors):

assert(add(1, 1) === 2)
assert(add(2, 3) === 5)

Then write the code to satisfy the test:
function add(first, second){
return first + second;
};

or this:

assert(justTheParam('x') === 'x');
assert(justTheParam(9) === 9);

justTheParam(param){
  return param;
};

These are really trivial functions to write. The process is what's important. Write the test (a simple assert statement will do fine). Then run it. Then write the code to make it pass. When you're comfortable with that, move on to more complex functions and tying it together with a test framework (like mocha) and using watchers ("mocha -w" does this I think. It's in the book).

Use assertion tests when the code is untested. Write tests first if you can.

I recommend all of these things as experiences to become options for you. Confidence in the code, rather than methodology, is a better candidate as your guiding principle. But confidence is contextual, informed by experience, and hard to instruct on directly.

Anyways, glad you're enjoying the book. Let me know if anything else is troubling you.

Cheers,
-Evan