Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript Unit Testing integrated with CruiseControl.NET

I'm looking for framework which provides unit tests for JS. Later, I'll have to integrate it with CruiseControl.NET. I have a lot of asp websites using JS and I need to automate testing for them. For example I used local JSUnit (may be other framework), which was quite easy for me, but I have no idea how to integrate it with CC.NET. Maybe you can show me how to start with ?

NOTE: it must be CC.NET, framework for unit test not specified

like image 417
deha Avatar asked Oct 25 '22 11:10

deha


1 Answers

I realize this is a rather old question, but I have had similar interests so I figure I would post an answer regardless. I am assuming you are writting OO style JavaScript and wanting to test those objects.

A common solution recommended by people is to run JsTestDriver and this is definitely a great tool; that being said, it requires the JVM to be installed on your machine as well as the build server. In addition to requiring the JVM, JsTestDriver is still dependant on running one or more 'Slave' browsers. Personally, I believe that should not be a concern when unit testing JavaScript objects. If the focus is UI testing, then using a tool such as WatiN and is a different type of test in my opinion. The browser should be mock out like you would mock out any other view using JSMock or JsMockito (which I like best).

To that end, I have used Windows Script Host to run my JavaScript unit tests for years. This has several advantages:

  1. No Browser Required (to me that is a good thing).
  2. CScript is already on every Windows machine since XP; so nothing to install.
  3. Runs in background process and does not require an interactive UI when running tests.
  4. Since running inside MSTest, NUnit or xUnit etc, integrating with CC.NET, Hudson, or TeamCity is as easy as running your unit tests as a part of the build.
  5. Full debug support simply by running your unit test inside the debugger.

There are a couple of disadvantages of course:

  1. The machine running the unit tests has to have the ability to spawn off new processes (CSCript) to actually run the tests (has yet to be an issue).
  2. Slower that running regular unit tests (A little over 1,000/minute on an older dual core if run individually - i.e., not bundled together in a single CSCript process).

Using JSTest.NET (approach I have used for years but just posted online), you end up with a test fixture that may look similar to the following:

using JSTest;
using JSTest.ScriptLibraries;
using Xunit;

namespace JSTest.Sample
{
  public class EventDispatcherTests
  {
    private readonly TestScript _testScript = new TestScript();

    public EventDispatcherTests()
    {
      //Append File(s) Under Test.
      _testScript.AppendFile(@"..\..\..\Web\Scripts\eventDispatcher.js");

      //Append Mock/Assertion libraries.
      _testScript.AppendBlock(new JsHamcrestLibrary());
      _testScript.AppendBlock(new JsMockitoLibrary());

      //Append Common "Setup" Scripts.
      _testScript.AppendBlock(@"var dispatcher = new EventDispatcher();
                                var mockHandler = JsMockito.mockFunction();
                                var mockPredicate = JsMockito.mockFunction();
                                var fakeEvent = { eventType: 'CommentAdded', data: 'Sample Comment' };
                              ");
    }

    [Fact]
    public void ProcessEventInvokesAttachedHandler()
    {
      ...
    }

    [Fact]
    public void ProcessEventGracefullyHandlesPredicateException()
    {
      _testScript.RunTest(@"var mockPredicateAlternate = JsMockito.mockFunction();

                            JsMockito.when(mockPredicateAlternate)(fakeEvent).thenThrow('MyException');

                            dispatcher.attachListener(mockHandler, mockPredicateAlternate);
                            dispatcher.processEvent(fakeEvent);

                            JsMockito.verify(mockPredicateAlternate)(fakeEvent);
                            JsMockito.verifyZeroInteractions(mockHandler);
                          ");
    }
  }
}

This approach works well for me, and is very simple to setup. Basically, it is like writing regular unit tests, but with JavaScript.

like image 185
Chris Baxter Avatar answered Nov 15 '22 13:11

Chris Baxter