How to get started testing with Express, Jasmine, and Zombie
Okay, so I’m a little old fashioned. I’m also lazy and reluctant to learn new things. My buddy Dawson asked How do I get started with testing my web software? I said, start with node/express…
Express
Express is a web framework. You build server-side software with Express. Let’s bootstrap a project with express-generator:
|
|
This creates a skeleton application from which to launch development. The ejs
stands for Embedded Javascript. To install:
|
|
Execute the server:
|
|
Assuming all is well, you can navigate to http://localhost:3000 to see your new app in action. Halt server execution by pressing Ctrl-C.
That’s great and all, but let’s get to testing…
Jasmine
I’m not sure Jasmine is trendy, but I’ve been using it for years. It takes minimal setup and can be neatly structured. It’s a good tool and the tests you write are easily adapted for execution by other test frameworks (if you decide you don’t like jasmine
).
Add jasmine
to your web application:
|
|
jasmine
is now a development dependency. Execute cat package.json
to get a peak at how node
manages its dependencies.
Initialize jasmine
like this:
|
|
Most people like to script test execution with npm
. Open the package.json
file just mentioned. Configure "scripts": { "test": "jasmine" }
… that is, make package.json
look like this:
|
|
If you do this correctly, you can run the following:
|
|
And expect to see something like this:
|
|
jasmine
is telling us that the tests failed because we have yet to write any. Being as lazy as I am, I try to find opportunities to skip unit tests and go directly to testing user behaviour. For this, I use a headless browser called Zombie.
Zombie
Like jasmine
, I’m not sure zombie
is the trendiest option out there, but I’ve always managed to get the two to play nicely together and have yet to find any serious shortcoming. Add zombie
to your project like this:
|
|
Now we’re ready to write some tests…
Testing!
Oh wait, what’s this app supposed to do? Ummmmm…
For now, I’ll keep it really simple until my buddy Dawson comes up with tougher testing questions.
Purpose
I want to be able to load my app in a browser, enter my name in an input field, press Submit, and receive a friendly greeting in return.
When starting a new web application, the first test I write ensures my page actually loads in the zombie
browser. Create a spec file:
|
|
I use the word index in the sense that it’s the default first page you land on at any website. Test files end with the *Spec.js suffix by default. Execute cat spec/support/jasmine.json
to see how jasmine
decides which files to execute.
Open spec/indexSpec.js
in your favourite editor and paste this:
|
|
Simple enough. At this point you might be tempted to go make the test pass. Instead, execute the following to make sure it fails:
|
|
Whoa! What happened? You probably see something like this:
|
|
It’s good that it failed, because that’s an important step, but if you look closely at the error, connect ECONNREFUSED 127.0.0.1:3000
tells you your app isn’t even running. You’ll need to open another shell or process and execute:
|
|
Your app is now running and zombie
can now send a request and expect to receive your landing page. In another shell (so that your app can keep running), execute the tests again:
|
|
If it fails (as expected), you will see something like this:
|
|
That’s much better. Now, having ensured the test fails, make the test pass. Open routes/index.js
in your project folder and make it look like this:
|
|
Execute the tests again:
|
|
And you will see:
|
|
Oh no! Not again! Go back and check… yup, you definitely changed the name of the app. What could be wrong?
You need to restart your server in your other shell. Exit with Ctrl-C and restart with npm start
. (Yes, there is a much better way of doing this).
Having restarted your application, execute the tests again with npm test
. You will see this:
|
|
Awesome. Your first test passes. Recall the stated purpose of this app:
I want to be able to load my app in a browser, enter my name in an input field, press Submit, and receive a friendly greeting in return.
Using this user story as a guide, you can proceed writing your tests. So far, the first part of the story has been covered (i.e., I want to be able to load my app in a browser). Now to test the rest…
|
|
You can push this as far as you want. For example, you might want to ensure your audience doesn’t enter a number or special characters for a name. The ones above define the minimal test-coverage requirement in this case.
Make sure these new tests fail by executing npm test
. You won’t need to restart the server until you make changes to your app (yes, you should find a better way to manage this).
Make the tests pass
You should try doing this yourself before you skip ahead. I’ll give you a couple of clues and then provide the spoiler. In order to get these tests to pass, you’ll need to add a route to routes/index.js
and you’ll need to modify the document structure in views/index.ejs
.
Did you try it yourself?
Here’s one possible answer:
Make routes/index.js
look like this:
|
|
Make views/index.js
look like this:
|
|
Note the EJS alligator tags (<% %>
and <%= %>
).
When all expectations are satisfied, you will see something like this:
|
|
What’s next?
Got a test question? What kind of app should I build and test?
If you learned something, support my work through Wycliffe or Patreon.