Welcome to Manicprogrammer Sign in | Join | Help

JsUnit + Accuracy

After I got my tests passing in JsUnit, I decided I needed to automate the execution of the JavaScript Unit Tests for Fjords(more on that in a later post). So, the only way I could think of doing that was to drive the browser to the JsUnit Test Runner page and type the correct parameters. Thank god I have an amazing Browser Driver called Stormwind.Accuracy.

Introduction

You can check how the JsUnit test runner looks here. But in the local version you get to choose the path to the test (in a textbox). "So", I thought, "It's pretty easy to automate that. I just write the test path in the textbox and click on run. Then I check that there were zero failures. How hard can that be?".

Whenever you finish a sentence with "How hard can that be?" you know that you are in for a world of pain. First thing that I noticed is that the JsUnit test runner uses a FrameSet, but not only that, it uses a FrameSet inside a FrameSet. That tends to be hard for Accuracy, since you need to specify the frame you want to find the control in. The thing here is I had never done any code with frames inside frames.

I was thrilled to see that the code in Accuracy is so simple that I managed to change the code to use hierarchical frames in no time. Now you can just say I.AmIn("some frame name").Frame or I.AmIn("Some Frame>Some Sub Frame>Some Inner Frame").Frame and it will put you inside the correct frame. This way I got to automate JsUnit properly.

The Test Fixture

Let's check what the JsUnitTestFixture looks like:

   1:      public abstract class JsUnitTestFixture : AcceptanceTestFixture
   2:      {
   3:          [Test]
   4:          public void ShouldRunTests()
   5:          {
   6:              //Context.Current.DebugMode = true;
   7:              Context.Current.ElementNamingStrategy = new CustomNamingStrategy();
   8:              var story = Story
   9:                  .AsA("Web Site User")
  10:                  .IWantTo("Unit test JavaScript using the " + TestPageUrl + " Page")
  11:                  .SoThat("I can verify that my JavaScript code is correct");
  12:   
  13:              var url = Path.Combine(Context.Current.RootUrl, "UnitTests/" + TestPageUrl);
  14:   
  15:              story.WithScenario("The tests run")
  16:                  .Given(I.GoTo("Js Unit Test Runner Page"))
  17:                  .And(I.AmIn("Main Frame>Main Data").Frame)
  18:                  .When(I.Fill.TextBox("Test File Name").With(url))
  19:                  .And(I.Click("Run Button").Button)
  20:                  .Then(I.AmIn("Main Frame>Main Status").Frame)
  21:                  .And(I.WaitFor("Status: Done").Message)
  22:                  .And(I.AmIn("Main Frame>Main Counts>Main Counts Errors").Frame)
  23:                  .And(I.See("Errors: 0").Message)
  24:                  .And(I.AmIn("Main Frame>Main Counts>Main Counts Failures").Frame)
  25:                  .And(I.See("Failures: 0").Message);
  26:          }
  27:   
  28:          public abstract string TestPageUrl { get;}
  29:      }
  30:   
  31:      internal class CustomNamingStrategy : INamingStrategy
  32:      {
  33:          public string Resolve(ElementType type, string key)
  34:          {
  35:              return string.Join(string.Empty, key.Split(' '));
  36:          }
  37:      }

Oh, that's right, Accuracy allows you to specify the naming strategy you want. In this case, none!

So we have one abstract property saying what Test Url is your test case in, and one Test which just runs the tests in that page. I think the code is pretty self-explanatory (one of the main advantages of using Accuracy).

Now let's check one of my test classes:

   1:      [TestFixture]
   2:      public class StormwindFjordsBusTest : JsUnitTestFixture
   3:      {
   4:          public override string TestPageUrl
   5:          {
   6:              get { return "StormwindFjordsBusTests.html"; }
   7:          }
   8:      }

Woot?! That's it? How come? This test doesn't have any assertions!!!

Calm down my hasty friend. Remember that your test is written in the html form. This is just a way to automate the run of those tests.

I could run all of them in the same Unit Test, but if I did that, I'd never know which ones are broken. So, that's why I have one JsUnitTestFixture for each of my Test Pages. There's just one last thing missing, the JsUnitTestRunnerPage, which is shown here and must be initialized in Accuracy.

   1:      public class JsUnitTestRunnerPage : Page
   2:      {
   3:          public JsUnitTestRunnerPage()
   4:              : base("/UnitTests/jsUnit/TestRunner.html")
   5:          {
   6:              Register.Textbox("Test File Name");
   7:          }
   8:      }

Conclusion

That's all you need my friend to have your JsUnit tests being run together with all your other unit tests.

Now I can really write as many JsUnit tests as I want to.

Hope that helps!

#146

Published Saturday, May 10, 2008 2:15 PM by heynemann
Filed under , , , , ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: JsUnit + Accuracy

Sunday, June 22, 2008 12:48 PM by Peter Mounce

Have you come across jQuery's QUnit (http://docs.jquery.com/QUnit) for JavaScript unit testing?  Even if it were horrible (it's not ;-)  ), it has the major advantage of not using frames.

It also comes with a jquery.simulate plugin which can be used to simulate actual browser events.

You can find out about both in the jQuery UI 1.5 release-notes blog post at http://jquery.com/blog/2008/06/09/jquery-ui-v15-released-focus-on-consistent-api-and-effects/

# re: JsUnit + Accuracy

Sunday, June 22, 2008 2:05 PM by heynemann

Thank you very much,

I'll definitely check it out!

Have you tried Accuracy?

I'm really looking forward someone who has checked it out.

# re: JsUnit + Accuracy

Sunday, June 22, 2008 5:28 PM by Peter Mounce

Not yet; I'm currently suffering from new-shiny-thing overload as I get to grips with Monorail and IoC, mocking and now user-acceptance tests all at the same time.  I landed here from your comment on Ayende's recent post on page models for tests, and am probably going to adopt that at least for the time being; given that WatiN uses interfaces for its DOM elements, I imagine it should be straight-forward to evolve that to something like Accuracy?

I'm also fighting the urge to see how hard it would be to extend WatiN's Find implementations with a jQuery-like selection engine - I really hate being forced to give everything IDs just to keep the server-side happy :/

# re: JsUnit + Accuracy

Monday, June 23, 2008 4:02 AM by heynemann

You don't need to "evolve it". You can use Accuracy to whatever tests you like. The nice thing is that it already provides a page model that you can create your page models against and a nice fluent interface to specify actions like: I.Click("Customer Name").Textbox.

I'd love to have our WatinBrowser extended to find elements using name instead of id, though.

Cheers,

Bernardo Heynemann


Enter the text you see in the image:

Leave a Comment

(required) 
required 
(required)