And we’re back. In part 1 we installed everything we needed for Tower and generated our app. In part 2 we learned how to run tests, and got our very first pre-generated tests to go from red to green. Now we need to write some tests of our own, then maybe we can go about actually writing some application code.
Tests of Our Own
If you’re returning to this project after taking a break, remember that your going to want to open a couple tabs in the terminal. In the first one, type:
git checkout -b ircbot
This tells git to create a new branch called “ircbot” and switch us into it. When we add a new feature to a project, this is a good idea because if we screw up something badly, we can save all our changes to that branch and then simple delete it, or just leave it there for reference, but switch back to the master branch. We won’t go deeply into that, but again, I recommend checking out the Pro Git book to learn all about using git in your workflow.
Now that we are safely in a new branch run:
This watches for changes to the coffeescript files and compiles them. Then open a second terminal to run your tests with
mocha test/*/*Test.coffee -w
Now let’s get started. Open up the file test/models/ircBotTest.coffee and change “describe ‘relationships’” to “describe ‘methods’”, then add everything I have beneath that here:
The “describe” lines tell mocha that we are creating a new group of tests. “beforeEach” tells mocha, this is code we want you to run before each of these tests. Pretty simple, right? Your tests should still be passing. If something fails, make sure you typed everything correctly. Be careful of identation.
Now for the first test. Add the following beneath the “beforeEach” block, and make sure the identation is even with it.
As soon as you save the file you should get a failing test. What this block of code does is tells sinon-chai to wrap the ircbot (from the beforeEach block )’s ‘init’ method in a special object called a spy. This spy can then return all kinds of useful information to us, like when, how and how many times the method was called during the execution of the code. Very useful for testing. You can read all about sinon’s abilities here. Then, the test saves the ircbot. What we want is for that bot to call an init method as soon as its saved. It doesn’t, yet, but we’ll fix that soon by writing application code. Finally, after checking that, we call “done()” to tell mocha that everything in the test is finished and it can move on. This is very useful, due to the asynchronous nature of coffeescript and node.
Now open up app/models/ircBot.coffee and add the two extra lines you see here:
“@after” is a special command in a tower model that tells Tower to run a method on an instance of that model, after a certain action is taken. Here we tell it that after creating an instance of an ircBot, it should run the init method. Then we write the “init” method. We could have gone ahead and written the init method’s code, but one guideline of BDD is to only write enough code to pass the test. In this case, simply having the init method there is enough. So now what? Well, now we need to write another test telling us what the init method actually needs to do.
How to Train Your Robot (and by “Train” I mean, “Test”)
So, first we need to go into test/server.coffee and add this line right beneath where we required Faker.
This gives us access to node’s “net” module, which we’ll need for testing some basic functionality in our ircBot. Then it’s back to ircBotTest.coffee, and beneath our last test we now should add:
This code create’s a server on our localhost, using port 6667, the port irc server’s generally connect on, and tells it to listen for a connection. When something connects we assume it’s our ircbot, and we disconnect, close everything out, and pass the test. If you look back to the beforeEach method, you will see that “localhost” is the server we used when we set up our bot. For now, your test should timeout and fail.
When I first wrote this test, I really had no idea how to go about it. I had created an empty channel on an irc server I often frequent and my plan was to create a testBot to join the channel and wait there for the real bot, and test it that way. What I never imagined was that my tests would trigger the irc server’s flooding defenses and get me banned. Fortunately, a message explaining the situation got me back on the server, but, it meant I needed a better way to test the bot.
By setting up a simple server using the “net” module, we can test basic things like connection without actually joining any irc servers or wasting anyone’s bandwidth.
Let’s get this test to pass now. Go back into app/models/ircBot.coffee and fill in the init method with this code:
This sets some variables based on the ircbot’s attributes, and then uses those to create a connection to the server and channel given. But wait, our test continues to fail with:
TypeError: Cannot read property 'Client' of undefined
Right. We need to install the irc module, and require it. First, in the terminal, find or open a tab not already running something, make sure you are in your app’s directory, and type or copy:
npm install irc --save
Watch to see that it installs without error, and check your package.json to make sure that it properly saved the module to your “Dependencies”. Even though we installed the module, our tests will continue to fail because we haven’t yet told our app about the module. In the folder app/config/server/initializers, create a file irc.coffee, and add to it:
Now, as of now, Tower sometimes doesn’t catch when we add new files to it, so we’ll need to return to the terminal and restart both:
Now our test should definitely pass. Alright, that was a lot of work. Remember how we wanted our bot to give a helpful message when someone joined the channel? I’m gonna give that functionality to you for free, then we’re gonna call it a day. In the init method, in app/models/ircBot.coffee, just add this:
We tell the bot that when the irc server emits the join event, it needs to respond with a message. Testing this proved to be a lot of work, and you are here to learn about Tower.js not the ins-and-outs of creating irc servers with node, so I decided to skip that for brevity’s sake. We can verify it works later, by actually making a bot and joining a channel that its in.
For now, let’s save our changes, then commit those to git and merge them back into master, with these commands:
This shows us all the changes which haven’t yet been committed. Before adding or commiting anything, it’s a very good practice to always check this and make sure everything looks right. Next:
git add .
This adds the changes we’ve made, along with new files, etc. Then:
git commit -m "Adds tests and functionality for our ircbot"
It’s the convention of the community to write commit messages in the present tense. I’m not entirely clear on why (maybe someone could explain in the comments), but in general, unless you have a very good reason, it’s best to follow the communities conventions. Finally:
git checkout master
git merge ircbot
If git doesn’t want to merge the changes, just re-run “cake watch” and try again. Once our changes are safely merged in, we can stop for now.
Come back for part 4, where we begin saving messages and turning those into github gists (a lot like the gists I’m currently using to display code in these posts.)