# Thursday, January 03, 2008
« ReSharper 3.1 | Main | Mmmm Podcasts »

I needed to make a change to some existing legacy* JavaScript that validates credit card numbers in the browser.  For the most part the project was green field except for a few services, so overall test coverage was very good - except for the JavaScript code.  The lack of test coverage in the increasingly growing JavaScript libraries was starting to really bother me, so I set out to find a way to create "unit" tests for my JavaScript code that didn't require any setup or any extra steps for another developer to run.  What I really was wanting, was for my JS tests to be integrated and run along side my NUnit tests.

After some searching it appeared that JsUnit looked to be the most widely used and supported JavaScript testing facility available.  The one problem with this is that it requires you run the tests through a frame in a browser, which is a whole lot slower and less integrated with our NUnit tests that I wanted.

To get faster feedback on my JS tests I immediately thought of using WatiN to drive the JsUnit tests.  After a quick Google search I found that Adam Esterline had already done something very similar.  The main difference between what he's done and what I wanted was that I wanted JsUnit errors results right there in my ReSharper test runner window and I wanted my test scripts to be pure JavaScript rather than HTML files that JsUnit uses (because I wanted to keep the SOC high, and be able to dynamically change the location of JsUnit relative to my test scripts).  Like Adam, I'm auto generating a test HTML page for JsUnit and using WatiN to drive IE (although since I get my results outside of IE, I'm thinking I can drop using WatiN altogether for this and make it browser independent).

The workflow for using the JsUnit utility library is as follows:

  1. In your test project include a reference to JsUnit.Utils.dll
  2. Create a folder (or two) to contain your JavaScript JsUnit test fixtures.
  3. Create your JsUnit test fixtures as separate .js files.
  4. Create a .NET NUnit test fixture with a test that runs the JsUnitTestRunner from JsUnit.Utils.

Here's my solution explorer window with the JsUnit.Utils reference and the c# and the JavaScript fixtures.

JsUnitSlnExplorer

Once that is setup you create a single NUnit test that kicks off all the JsUnit tests.

/// <summary>
/// This runs all JsUnit tests found in the JavaScript folder and makes
/// their results available through NUnit (if any fail).
/// </summary>
[TestFixture]
public class JavaScriptFixture
{
    #region Setup/Teardown
 
    [SetUp]
    public void SetUp()
    {
        jScriptTestDir = AppDomain.CurrentDomain.BaseDirectory + "\\..\\..\\JavaScript\\";
        jsUnitDir = ConfigurationManager.AppSettings["JsUnitDir"];
    }
 
    #endregion
 
    private string jScriptTestDir;
    private string jsUnitDir;
 
    [Test]
    public void RunAllJSUnitTests()
    {
        Assert.IsTrue(Directory.Exists(jScriptTestDir),
                      string.Format("Could not find the JsUnit tests directory: '{0}'", jScriptTestDir));
 
        Assert.IsTrue(Directory.Exists(jsUnitDir),
                      string.Format("Could not find the JsUnit directory: '{0}'", jsUnitDir));
 
        ITestFileReader reader = new SuffixTestFileReader(".js", new TestFileReader(jScriptTestDir));
        new JsUnitTestRunner(reader, jsUnitDir).Run();
    }
}

 

Running this test through the ReSharper Test Runner runs all my JsUnit tests, so when I choose "Run All Tests from Solution," it really means "run all tests".  More importantly, if any JsUnit tests fail during execution the JsUnit error is displayed in the output window.  Here's my "testShouldValidateCreditCard" test that is failing which shows the JsUnit error text:

JsUnitInsideNunit

If you've ever used JsUnit before I bet you're wonder how I'm getting the result back, since JsUnit is entirely web based and only supports posting results to a URL (generally for use with the JsUnitServer).  What I'm doing is unpacking an ashx file that is an embedded resource, copying the current running DLL (JsUnit.Utils.dll) to the bin directory under the current running directory, and then starting the .NET 2 webserver.webdev.exe to listen for results using the unpacked ashx file.  The results are then saved out to a predetermined text file which JsUnitTestRunner is looking for and then parses out any errors.  I could use .NET remoting or something fancier, but this works well enough for now.

There's still a lot that could be done to clean this up, like removing the WatiN dependency, adding new features and so on.  There are also a few bugs I need to work out, but so far so good.

*legacy in the sense that there were no unit tests, even though the code is only a month old.

Comments are closed.