Test Driven Development Part 2: Writing Mocha Tests (almost)

Remember Why Writing Tests is a Good Idea?

In short:

  1. It’s extremely useful for debugging to have tests
  2. It forces you to reason through things and think in terms of small, manageable bits of code
  3. It will help with division of responsibilities
  4. It will make you more impressive when you try to get a job if you have TDD skills
  5. Everyone keeps telling me it’s fun? The Mocha tag line is actually “simple, flexible, fun.” (I am not sure about this YET, but I think at least in Mocha, the nyan cat will help me feel more motivated.)
Also, RuPaul, in his infinite wisdom, claims, “Fulfillment isn’t found over the rainbow-it’s found in the here and now.” Hopefully I will find fulfillment en route to the nyan cat rainbow.

Getting Started

So, how should I start writing mocha tests, and build a small application to see if I can actually do TDD? Even with my capybara testing, I only got the red, I didn’t get the green or the refactor. So, I’d like to try to get an entire set of tests written and passing!

Install

First, I visited the Mocha site for some insight into where to start.

Install Mocha by running the following code in your terminal

$ npm install --global mocha

Start your project

First, I started with a basic directory structure:

$ npm install mocha 
$ mkdir mocha_test_app
$ cd mocha_test_app
$ touch test.js
$ touch package.json
$ atom .

I followed the following example from Mocha to ensure that everything was set up and communicating correctly:

var assert = require('assert');
describe('Array', function() {
describe('#indexOf()', function() {
it('should return -1 when the value is not present', function() {
assert.equal(-1, [1,2,3].indexOf(4));
});
});
});

Then, I set up a small snippet of JSON that allows you to run “test” in the terminal to execute the Mocha test:

{"scripts": {
"test": "mocha --reporter=nyan test.js"
}
}

Make sure you are actually using JSON and the brackets around the entire piece of code, otherwise the test will not pass!

Now, you can test the code using “npm test” in the terminal:

Got the first test, and it’s passing! Now that I’m sure that everything is set up correctly, I’m going to get rid of this test (it’s not really related to what I want to do), and start thinking through the code challenge I’m going to work on.

The Code Challenge

For this test, I’m going to try working on a common code challenge that’s presented during Junior Developer job interviews (because, why not?).

This one is, according to the internet, reportedly used during interviews at Microsoft.

Write a function in your favorite programming language that will accept any two strings as parameters and return “1" if they are anagrams and "0" if they are not.

Logic

First of all, what are we testing here? Really, at a very basic level, we are looking at the characters in two strings, and seeing if those match up exactly.

A common example is “silent” and “listen.”

Made with Wordsmith anagram animator

If I were just looking at two words, such as the words above, and I were doing this without a program, I would probably write both of the words out, and go through each letter of the first word, cross it out, and cross out the same letter (if it exists) in the second word. This seems like it would be very easy to do with paper, but might be a bit complicated with code.

Another way to do it would be to put both words in alphabetical order, and see if they are exactly the same. This is something I would NOT be able to do easily on paper, because I have to recite the entire alphabet each time I try to figure out where a letter goes, but it is probably something a computer could do very easily!

So, most simplistically, I am expecting my code to:

  1. Have a function called anagramDetector
  2. This function should take two arguments, both of which should be strings
  3. The function should split each string into it’s characters and put them in alphabetical order
  4. Then, it should compare those two arrays. If they are equal, return 1. If they are not, return 0.

Figuring out how to write tests

There are several libraries you can use when deciding how to write your test assertions, or essentially the structure and syntax of your tests. Chai is particularly popular, but since the program I am working on is a small code challenge which does not need a lot of test cases, I’ve decided to go with expect.js, which is even simpler and very straight forward. The API is also simple to understand and implement.

Here is an example below:

math.js
function add (a, b) { return a + b; };
test.js
describe('test suite', function () {
it('should expose a function', function () {
expect(add).to.be.a('function');
});

it('should do math', function () {
expect(add(1, 3)).to.equal(4);
});
});

Following this template, I wrote my first test as follows…

var expect = require('expect.js');
describe('test suite', function () {
it('should expose a function', function () {
expect(anagramDetector).to.be.a('function');
});

…and got my first test to fail!

HOORAY FAILING TEST!

The Catch (or: my blog posts are frequently a bit too ambitious)

The problem I encountered here was, after

  • reading about a dozen different blog posts
  • reading all the documentation on Mocha, and
  • studying a github repo made by MIT which was specifically an anagram detector using JavaScript and Mocha tests
  • cloning the aforementioned repo and trying to not change any of the file structure and just change the code and my write my own tests

I still could not get my files to communicate correctly with each other and my test to find my index.js file. I wrote out some code with an anagram detector function (first just with a console log to see if I could get it to define, for the purposes of red-green-refactor) and then something closer to how I would actually solve this code challenge. No dice. This is basically as successful as my Capybara testing.

So, as of right now, no passing tests, and no rainbow, no fulfillment in the here and now…sorry, Ru.

Another possibility…

While I’m pretty sure that my first test was a fairly straight forward fix, I’m not sure if I’m really going about writing my tests in the best possible way. If the issues lie there, I could write the most beautiful anagram detector function in the world, and I would probably still have problems because my tests might be buggy.

So, what’s next?

I don’t know what the problem is just yet, and I’m not really sure how to go about solving it, but I’m going to try to walk through a few more examples without trying to do my own thing. Then, once the concepts have really sunken in (hopefully!), I’m going to try this again. If it works, I’m going to try to do one TDD + Code Challenge per week (stay tuned!).

Resources