Welcome to Manicprogrammer Sign in | Join | Help

Stormwind Accuracy

What? Another Stormwind project?! Are you crazy? Are you trying to set some sort of record? Don't you want to finish the ones there first?

I just quoted those imaginary sentences to scare that thought away from me. I like to think that I am an individual with good ideas. So as the ideas come in I try to work them out.

Today I just finished a proof-of-concept of what I think will be a very cool project in the Stormwind umbrella. Stormwind.Accuracy is the name of this new endeavour. I chose this name since I think I missed some targets in the past by not having appropriate acceptance criteria and testing.

I need to give credit where it's due, since a lot of the ideas for Accuracy came from the project I'm currently working in Thoughtworks. I'll disclose the name of the team members if they allow me.

Anyway, on with the show!

Introduction

Are you as tired as me of having to write weird acceptance tests that feel like writing a browser API from scratch in every test? Well, the team I'm currently in was tired as well, so we came up with a way to use NBehave and Watin in order to achieve a sort of BDD Acceptance Testing. It's working so great we have automated acceptance tests for all our stories, even for security (it was hard to do since security is windows integrated, but we got it).

So, as usual, I kept thinking about refactoring that into something easier to write, and above all, semantically readable. After three cycles of writing code, throwing all away and rewriting it, I got to something I really like.

I'll first show what two of my acceptance tests look like, then how I modeled my Pages (more on that in the Pages section) and then discuss some interesting bits of the Accuracy framework.

Acceptance Test Syntax

A sample of an acceptance test syntax:

   1:  [Test]
   2:  public void ShouldTestSeeAction()
   3:  {
   4:      Story story = Story
   5:                      .AsA("Regular User")
   6:                      .IWantTo("See Action tests")
   7:                      .SoThat("I can test the See action and its sub actions are working");
   8:   
   9:      story.WithScenario("User should see textbox")
  10:          .Given(I.GoTo("Default Page"))
  11:          .And(I.SeeDefaultControls)
  12:          .When("The page finishes loading.")
  13:          .Then(I.See("My Test").Message);
  14:  }

The test output for that test is:

Story:
  As a Regular User
  I want to See Action tests
  so that I can test the See action and its sub actions are working

  Scenario 1: User should see textbox
  Narrative:
    Given That
      I navigate to Default Page at /default.aspx
      and that I see the default controls for the Default Page
    When
      The page finishes loading.
    Then
      I see the "My Test" message.

Another sample:

   1:  [Test]
   2:  public void ShouldTestFillAction()
   3:  {
   4:      string testTextBox1Text = "My Custom Special Text";
   5:   
   6:      Story story = Story
   7:                      .AsA("Regular User")
   8:                      .IWantTo("Fill Action tests")
   9:                      .SoThat("I can test the Fill action and its sub actions are working");
  10:   
  11:      story.WithScenario("User should fill textbox with text")
  12:          .Given(I.GoTo("Default Page"))
  13:          .When(I.Fill.TextBox("Test Textbox 1").With(testTextBox1Text))
  14:          .Then(I.See("Test Textbox 1").TextBox.ContainsText(testTextBox1Text));
  15:  }

The test output for this test is:

Story:
  As a Regular User
  I want to Fill Action tests
  so that I can test the Fill action and its sub actions are working

  Scenario 1: User should fill textbox with text
  Narrative:
    Given That
      I navigate to Default Page at /default.aspx
    When
      I fill the Test Textbox 1 with "My Custom Special Text".
    Then
      I see that the Test Textbox 1 textbox contains the "My Custom Special Text" text

Page Modeling

The page model is how you abstract pages for your tests. The current way of implementing that page model is to create classes that inherit from Page (a class in Accuracy) and initializing them in Accuracy (more on that in another post).

A page class looks like this:

   1:  public class DefaultPage : Page
   2:  {
   3:      public DefaultPage() : base("Default Page", "/default.aspx")
   4:      {
   5:      }
   6:      protected override void RegisterPageComponents()
   7:      {
   8:          Register.Label("My Test").WithText("My Test");
   9:          Register.TextBox("Test Textbox 1").WithId("txtTest1");
  10:      }
  11:  }

As you can see, we register components for this page with keys, which are in turn used in our tests for easy reference of page components. The page also passes an URL and a Key for itself as a way of automating navigation.

Interesting Bits of the Framework so far...

Well, so far I really like the clear style of writing acceptance tests. I also am very fond of the output I get from the tests. Even so, there are three parts of the framework right now that go unnoticed in the above code.

The first one is the concept of a Context in the acceptance tests. So you get a singleton with some nice information on the current run, like current page, if the framework is initialized, a list of available pages and stuff like that. It's really helpful when you need to extract information on the currently running test.

The second one is the security part of the framework. If you were really paying attention to the code above you have seen this code: .AsA("Regular User"). Whenever you execute a .AsA directive in Accuracy, an event is raised in the Current Context (see above paragraph) with this security information. You would ask me why is that, right? What do you care about this stuff? Well, you would usually need to se some security information for each of your acceptance tests, providing you have authentication in place and some sort of role-based authorization. So, Accuracy allows you to implement your own security handler, and as long as you subscribe to the correct event, whenever an .AsA directive is executed your code will be executed, so you get to take direct action (change a config file, update the database, or whatever you have to do).

The third one is the Action model currently in place in Accuracy. It's really easy to implement new actions like TextBoxExistsAction or ClickLinkAction, for instance. Hopefully I'll get to implement a lot of that till the first release of Accuracy.

As a last interesting thing of the framework is that we're not coupled with Watin. We currently use it to drive our tests, but we use it through an IBrowserDriver interface. This way, we can implement other Browser Drivers later if need be.

Feedback?

I know that you can't really test drive the code right now, but I hope that all of that gave a feel of what it looks like. I really want feedback on the syntax of stuff, because that's the thing I am most concerned about right now. Acceptance tests should convey the criteria in a meaningful way, and they really should be easy to read.

If you want to help me out here, please DO! Just add your comment here!

#136

Published Friday, March 14, 2008 11:40 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

# Stormwind.Accuracy - Part 2

Friday, March 21, 2008 8:05 AM by while(availableTime>0) {

Introduction I've been toying around with the syntax for writing more natural acceptance tests as you

# Resumo da semana - 24/03/2008

Monday, March 24, 2008 7:40 PM by Console.Write(this.Opinion)

Resumo da semana - 24/03/2008


Enter the text you see in the image:

Leave a Comment

(required) 
required 
(required)