Unit Testing Javascript

Recently the project I’ve been working on has been moving more and more towards client side javascript, especially using jQuery. We have been pretty consistent on the server side, especially in our business logic, in creating unit tests. We have over 1,000 unit tests in our business tier leveraging nUnit and Rhino Mocks, that are run every time a check in is done using Cruise Control for continuous integration. Pretty standard stuff for server side logic.

Since we are using more and more javascript why not reap the quality benefits of good unit test coverage here as well?  Considering javascript is non-typed and allows the running of strings as code through the ‘eval’ function it would seem even more important to have good unit test coverage of our javascript.  Up to now we’ve ignored it since it’s been considered UI and not really logic.  With more and more ajax integration this no longer seems like a good practice.

For jQuery driven functionality we have been using the jQuery $.ajax method to call down to asp.net pagemethods located  in web forms we created to support the jQuery functionality.   ASP.net pagemethods are essentially webservice calls located in a webform.  The calls have to be static and must be decorated with the [Webmethod] attribute.   Here is a great blog post going into great detail about exactly how to call an ASP.net pagemethod from jQuery.  We essentially are doing the same thing.  We’ve actually wrapped our $.ajax call so we can centralize error handling and abstract away the ‘.d’ return value you get when the pagemethod does it’s json serialization.

This post is about testing, however, so enough with how we’re using jQuery ajax.   From a testing perspetive what we wanted to be able to do was achieve the same test coverage in our jQuery and javascript as we have on our server side logic.   A little googling and what did I find, but qUnit!  The motif is almost the same as writing tests for nUnit, and when you run your tests qUnit provides default css so test results are shown in a html page in a very similar manner to how the nUnit client shows it’s test results.

The great thing is how easy this is to accomplish.  All you need to do is write tests in a .js file that exercise the code you wish to test using the qUnit syntax.  Then in a html page include jQuery, qUnit, the code you are testing and your test code.  In the html provide the nodes that qUnit will want to write to and, you’re done.   Here’s a very simple html example:

<html xmlns="http://www.w3.org/1999/xhtml" >
   <head>
      <title>QUnit Test Example</title>
        <!-- css from qUnit to make output look good -->
          <link rel="stylesheet" href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css" media="screen">
     <!-- jQuery and qUnit include -->
       <script type="text/javascript" src="/scripts/jquery-1.4.1.js" ></script>
       <script type="text/javascript" src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js"></script>
        <!-- javascript you are testing include -->
       <script type="text/javascript" src="/scripts/ControlScript.js"></script>
        <!-- tests you wrote include -->
       <script type="text/javascript" src="/scripts/ControlScriptTests.js"></script>
   </head>
  <!-- nodes qUnit will write to -->
   <body>
       <h1 id="qunit-header">QUnit Test Suite</h1>
       <h2 id="qunit-banner"></h2>
       <div id="qunit-testrunner-toolbar"></div>
       <h2 id="qunit-userAgent"></h2>
       <ol id="qunit-tests"></ol>
   </body>
   </html>

Very code I’m testing:

[javascript]
function SetupButton(buttonID, txtBoxID, displayText)
{
$("#" + buttonID).click(function() {
$("#" + txtBoxID).attr("value", $("#" + txtBoxID).attr("value") + ‘ ‘ + displayText);

});
}
[/javascript]

And here are the tests I’m running:

[javascript]
test("SetupButtonTest()", function() {

var btn = document.createElement("input");
btn.id = "btn";

btn.type = "button";
document.appendChild(btn);

var txt = document.createElement("input");
txt.id = "txt";
txt.type = "text";
document.appendChild(txt);

SetupButton("btn", "txt", "disp");
$("#btn").click();
equals($("#txt").attr("value"), " disp", "text box has display value: " + $("#txt").attr("value"));

})

test("SetupButtonTest2()", function() {

var btn = document.createElement("input");
btn.id = "btn";

btn.type = "button";
document.appendChild(btn);

var txt = document.createElement("input");
txt.id = "txt";
txt.type = "text";
document.appendChild(txt);

SetupButton("btn", "txt", "disp");
$("#btn").click();
equals($("#txt").attr("value"), "disp", "text box has display value: " + $("#txt").attr("value"));

})
[/javascript]

As you can see qUnit provides a pretty straightforward way to unit test the now more complex javascript we’re writing in our project (the above is just an example, not actual code from our project). The next step is to integrate qUnit into our continuous integration. We would like to have our javascript tests run with every check in, just like our server side tests do. Here is a post on how to do it, it’s seems a little complicated. I will give it a try and put up a post as to the results.

Hopefully we will be able to bring the benefites of good unit testing coverage out from just our server code and now apply it to the more and more complex client side code we’re creating.  After all why would it not be good practice to test code just because it’s javascript?  It seems even more important to test in a language that is non-typed and allows run-time execution of strings as code.

CodeMash 2010 Wrap UP

I attended CodeMash at Kalahri in Sandusky, Ohio last Wednesday and Thursday.  I skipped out on the last day to catch up on some work.  All in all it was a great experience.  I learned quite a bit and also felt validated in many of the approaches we’ve been taking at work.

Below are my notes from the sessions I attended.  I also have to note my favorite quote from CodeMash.  Barry Hawkins was giving a presentation on Domain Driven Design.  When trying to describe the experience of talking to Doman Driven Design people about Domain Driven Design, (apparently they can be long winded in their explanations)  he said something like, “it’s like talking to Ents with crack pipes”.  I liked that description a lot!

Session Notes:

Engineering Vs Design

Domain Driven Design

Software Design and Testablity

User Stories Closing The Agile Loop

Keynote – Lean Methodology

Agile – Iteration Zero

Practical B/TDD

Fundamentals Of Software Engineering

CodeMash – Engineering Vs Design

It’s my last session today and forever at CodeMash this year.  I’m not able to show tomorrow.  Currently sitting in on Engineering Vs Design, given by Joe Nuxoll.

Reviewing Web 2.0 and RIA‘s, things like Google Maps, could they have been envisioned by a designer with no software knowledge or vice versa?  Probably not.  Must have design and engineering mixed together in ways not previously needed.  UI Engineering is design and design is UI Engineering.

Traditional Roles in product development: Designers, UI Developers, and web UI developers.  More and more you are seeing people who can do all of these tasks as need to understand them all.  New breed of tools to simplify this sort of work, RIA Design tools:  Adobe Catalyst, JavaFX Production Suite.

Important to cross train engineers and designers as they function with very different processes.  Important to educate engineers on the design process and designers on the engineering process to encourage mutual skill appreciation.  To this end co-location is very helpful.  Much easier for designers and engineers to understand and support each others processes if they are situated together.

Important to understand the difference between prototype and production.  Build many prototypes and be willing to throw them away.  Joe likes to use a separate folder in subversion for design, partly because subversion is good at handling design type resources and partly to separate highly iterative resources.   The design folder is prototype work, not production.  Also brings benefit of version control to design, where it is not traditionally used.

Build detailed facades.  These are generally not going to be production code, be ready to throw much of it away.  Really iterate to get it right.  Stub out back end calls and keep back end people in the loop.  Make sure the UI team has regular check ins with the back end team.

Once you’ve iterated to the point where can start work on production code can lift much of the final iteratino prototype code to start production work.  Keep prototypes clean by doing production work in separate source control folder.

Joe seems to be wrapping up although still 20 minutes left in the session.  I think we’re going to Question and Answer now.  Question came up as to how to get end users to not focus on color and such when reviewing a functional wire frame?  Joe’s answer, keep all design detail out of functional wireframe so nothing for end user to get distracted by.

Wire frame prototyping should happen before visual design.  Designers need app functionality to be fairly solid before they can effectively begin their work.  Interaction and functionality should be defined thoroughly before visual design.

Well that’s a wrap.  Another good session, not very technical but very relevant to our current work.

CodeMash – Domain Driven Design

Time for the second afternoon session here at CodeMash.  This session is called Domain Driven Design and is being given by a gentleman by the name of Barry Hawkins.  This is the second presentation I’ve seen Barry give today, he’s a very dynamica and entertaining speaker, but still is very on point.

The presentation focused on the importance of modeling.  To distill this greatly models are a representation of the domain, the domain is the subject matter itself.  It is important to use ubiquitous language across a team made up of all people necessary to move project from conception to completion.  This means that subject matter experts and scenarios they provide feed the domain vocabulary, not pattern and practice leanings.

Domain models should start small and be validated by detailed reference scenarios.  Barry’s team uses nNuit or jUnit to create tests to in effect ‘model’ the reference scenarios so they can validate the model accurately reflects them.  The reference scenarios get increasingly complicated and are provided by domain subject matter experts.  Barry used an example from the shipping industry as an example.

Another importance concept was to entertain different models, don’t settle on the first solution you think of.  Use natural language to pseudo code out multiple modeling options to decide which is best for the context you’re in.  Don’t be afraid to throw out models if they don’t work, the first thing isn’t the best thing necessarily.

Barry works with Eric Evans who authored a book, Domain Driven Design, which the talk was based on.  Great overview of a very deep topic.  I’m looking forward to picking up the book and learning more.

CodeMash – Software Design and Testablity

It’s Thursday afternoon here now at CodeMash.  Had a nice lunch while listening to a presentation on Microsoft’s open source efforts given by Hank Janssen. Now I’m sitting in on my first afternoon session, Software Design and Testability, the presentation is being given by Jeremy Miller, a gentleman from Dovetail Software in Austin Texas.

Testability and Design …is about finding, removing and preventing defects….is about assiging and partitioning responsibilities in an application…corresponds well to traditionally good design ideas…..is facilitated by patterns.

Need to shift mindset, I don’t write code, I ship software….people should see their efforts in the context of the whole, testability promotes this.  Software isn’t designed for the efficiency and optimzation of the code itself, but for the software as a whole.   Good code is only important in that it enables us to delivery what the customer wants, where it does not do that it doesn’t really matter.  That being said it is really important since good code allows software to be changed and worked on by other developers more easily, allowing us to better deliver wanted features to our customers.

First Causes Of Good Design: Fast feedback, short iterations are important to good design (agile)……Orthogonality, good separation of concerns (persistence, ui) so changes can be kept to small parts of the system when made.  Changes will be needed when made only want to change one area of system to accommodate.  This allows you to change things more easily when you know more later in your project.   You will be wrong at times, this helps make things easier to change to accommodate this…………Reversibility, give customers the ability to change their mind………….Understandability, although smaller classes for testing that interact more may make things less understandable.

Writing Automated Tests:  Known Inputs and Measurable Outcomes.  State Based tests versus Interaction Based tests, state based tests check to see if state changes occurred appropriately, testing to see if something else was called appropriately are interaction based tests (mock objects).

What makes a good test?  Repeatable…..Run Fast…..Easy To Write….Easy To Understand, a good test tells you where and why it failed, not just that it failed.

Jeremy is pulling up an example of something he did early on that was not testable.  Showing us the actual code.  Example code is doing many things at once, hitting database and doing processing.  Code is impossible to test without setting up entire application.

You should isolate the ugly stuff, isolate external dependencies ie the database, active directory, remoting, chatty api’s, etc…..etc……  Jeremy gave an example from Jay Flowers, Expand The Creamy Center.   Jeremy is now walking through how to do this with the sample bad code he has up on the screen.   Refactoring code into state machine that is heart of the workflow, ugly stuff is pulled out and state machine is tested using mocks for the ugly stuff.

Coding from the bottom up is good idea.  Test small to begin with, then test big.  Don’t try and put everything together and then test, hard to find problems you find.  Build little things at a time and assemble them.  Jeremy is a big fan of Object Role Stereotypes and responsiblity driven design, this is in the context of introducing a controller into his refactoring of his example code.

Inversion of control discussion.  Should push not pull, if your class is directly accessing a config file or database it is very tightly coupled to these things and hard to test.  Push externally needed things into your classes so they aren’t coupled to these items.  Push don’t pull!  This also causes you to keep a short tail, can resuse code without needing a whole lot of other code to come with it.

The hour is up, a very good presentation I thought.  The push versus pull analogy really made a lot of sense a clarified why we’re doing a lot of the things we’re doing.