11/12/2012

Building a Unit Test in Jasmine, Part 1

(Thanks to Dustin Butler for the inspiration that led me down this path.  His great and more in-depth article is at Unit Test JavaScript Applications with Jasmine)

Unit testing and I have had a tumultuous affair until now.  Every few months I would pick up a book, go on a blog reading binge, or try out a framework.  It would never work out.  I would get frustrated or work would intervene and off I went.  Unit testing and I were almost fated to always be apart... <cue the romantic music>
An opportunity came at work to create a new feature on our web platform.  I decided to take a chance and build it from unit tests.  It was a great opportunity to start clean with very few dependencies to worry about.  The lack of entanglements made it easier for me to understand how unit testing would work to describe this new piece.


After some web research, I decided on Jasmine.  I don't know enough about unit testing yet to speak about which platforms are best suited for what.  What I do know is that Jasmine was recommended in some trustworthy sources, and I could grasp it's syntax readily.  
My first hurdle was understanding how it worked.  Beginning can be the hardest part, so I started simple....2+2=4.

Getting Started 

The first step was to create a testing space and adding the necessary Jasmine files to it.  The latest zip can be downloaded at https://github.com/pivotal/jasmine/downloads.  The files that are necessary to get started are:
  • SpecRunner.html
  • jasmine.css
  • jasmine.js
  • jasmine-html.js
I put everything in one folder when I first started with Jasmine.  Later, I created an appropriate folder structure to host my tests.   There are three parts to any test:
  • HTML - The tests are started by loading an html page that builds the Jasmine environment and executes the tests
  • Spec - describes the tests and how they should run
  • Source - The code being tested
First, I created a new JavaScript file for my first Spec.  Then, I went to add it to the Jasmine test environment on the HTML page.  The HTML page will need to access the new Spec file and the Source to test.  This is accomplished through simple script tags.  The sample HTML file,  SpecRunner.html included in the download, has 2 comment lines that call out a place to put those tags.


<!-- include source files here... -->
<script src="Insert path to the code you are testing"  type="text/javascript"></script>

<!-- include spec files here... -->
<script src="Insert path to the file you will put your tests in"  type="text/javascript"></script>

With the reference created, I moved on to editing my Spec file.  The first function is describe.  Describes are headings you can use to organize multiple tests into logical groupings, or suites.  For example, I might have a describe for a simple object's "Attribute Tests" and another for "Function Tests".  I used "Simple Test" for this example.  The describe is a closure so the second parameter is a function.  


The "it" goes inside this closure.  "it" is the specific test(s) you are going to run.  "it" is also a function with a closure.  The first parameter is what will be returned to you on a successful test.  This example returns  "2+2=4" on a successful test. The second parameter is the function that does the work.


A lot of things can happen inside an "it".  Primarily, a thing is "expected" to have a predetermined result.  This is the purpose of the "expect" function.  The expect function captures the result of the process passed into it.  The expect then matches that actual result against the expected result.  If the result matches the expected result, then the test passes.  If not, the test fails.  The matchers I have used most often are toBe and toEqual.  The test can be read as "I expect the result to be" or "I expect the result to equal".  The difference between the two is type comparison.  toBe performs implicit type conversion (==), and toEqual performs no type conversion (===).


It helps me understand my tests by reading them in plain language.  One of the reasons I like Jasmine is how easy this is.  The simple test I put together for this post can be read as:

"I have a simple test running to check that 2 + 2 = 4, and I expect my inline function to return a 4 when run."



Next week, we will take this and start abstracting it out.