Welcome to Manicprogrammer Sign in | Join | Help

Stormwind.Accuracy - Part 3

Introduction

One thing that has been hard to achieve in our acceptance tests is a natural way (fluent) of specifying what data our tables should contain. Usually our scenario is like this:

  1. We have some table that contains some list of entities rendered.
  2. We need to make sure the table has the correct header.
  3. We need to make sure that these entities were correctly rendered.

This has become a large task when it should be quite simple. So, while thinking about it, I talked to my friend Sadek Drobi and he had wonderful ideas on the subject. After a very nice discussion on it, I settled for the following constructs.

Checking Tables Entity-Based

Let's say you have an entity that looks like this:

   1:  public class TestEntity
   2:  {
   3:      private readonly string propertyA;
   4:      private readonly int propertyB;
   5:      private readonly string propertyC;
   6:   
   7:      private TestEntity(string propertyA, int propertyB, string propertyC)
   8:      {
   9:          this.propertyA = propertyA;
  10:          this.propertyB = propertyB;
  11:          this.propertyC = propertyC;
  12:      }
  13:   
  14:      public string PropertyA
  15:      {
  16:          get { return propertyA; }
  17:      }
  18:   
  19:      public int PropertyB
  20:      {
  21:          get { return propertyB; }
  22:      }
  23:   
  24:      public string PropertyC
  25:      {
  26:          get { return propertyC; }
  27:      }
  28:   
  29:      public static IList<TestEntity> GetTestData()
  30:      {
  31:          IList<TestEntity> entities = new List<TestEntity>();
  32:          entities.Add(new TestEntity("a", 1, "d"));
  33:          entities.Add(new TestEntity("b", 2, "e"));
  34:          entities.Add(new TestEntity("c", 3, "f"));
  35:   
  36:          return entities;
  37:      }
  38:  }

Then you have a GridView (I hate them, but I wanted to make sure my approach work with anything that renders a table) like this:

<asp:GridView runat="server" ID="tblTest" AutoGenerateColumns="False">
    <Columns>
        <asp:BoundField DataField="PropertyA" HeaderText="Test table header 1" />
        <asp:BoundField DataField="PropertyB" HeaderText="Test table header 2" />
        <asp:BoundField DataField="PropertyC" HeaderText="Test table header 3" />
    </Columns>
</asp:GridView>

Then in your code-behind file you do this:

   1:  protected void Page_Load(object sender, EventArgs e)
   2:  {
   3:      tblTest.DataSource = TestEntity.GetTestData();
   4:      tblTest.DataBind();
   5:  }

So, by now your GridView has rendered a table with all the entities in your list. Now, let's head back to our Acceptance Test. How can I make sure that this page is showing correct data, with minor effort and in a non-fragile way (if I hard-code data here and the data change, I'm in trouble)? Well, that's where Accuracy comes to the rescue! Let's check what that Acceptance Test would look like:

   1:  [Test]
   2:  public void ShouldTestSeeActionInShowEntitiesInTablePage()
   3:  {
   4:      IList<TestEntity> entities = TestEntity.GetTestData();
   5:   
   6:      Story story = Story
   7:                      .AsA("Regular User")
   8:                      .IWantTo("See Action tests")
   9:                      .SoThat("I can test the See action and its sub actions are working");
  10:   
  11:      story.WithScenario("User should see elements in table")
  12:          .Given(I.GoTo("Show Entities In Table Page"))
  13:          .When("The page finishes loading")
  14:          .Then(I.See("Test").Table)
  15:          .And(I.See("Test").Table.WithData(entities));
  16:  }

Hmmm... We're missing something here. How can he know about this table's details? Well, because we told Accuracy that by registering our table like this:

   1:  public class ShowEntitiesInTablePage : Page
   2:  {
   3:      public ShowEntitiesInTablePage()
   4:          : base("/ShowEntitiesInTable.aspx")
   5:      {
   6:          Register.Table("Test")
   7:              .WithHeader("Test table header 1", "Test table header 2", "Test table header 3")
   8:              .WithMapping("PropertyA", "PropertyB", "PropertyC")
   9:              .WithDataStartingInRow(2);
  10:      }
  11:  }

Well, that's pretty much all you need to do to make this work.

Checking a Table Custom-Value Based

Now, let's say you need to check the same table, but you want to check every row yourself, instead of relying in the entity-based mechanism. That's ok, there are cases where you have static tables, and such.

You would just do it like this:

   1:  story.WithScenario("User should see elements in table")
   2:      .Given(I.GoTo("Show Entities In Table Page"))
   3:      .When("The page finishes loading")
   4:      .Then(I.See("Test").Table)
   5:      .And(I.See("Test").Table.As(
   6:          "a", 1, "d",
   7:          "b", 2, "e",
   8:          "c", 3, "f"
   9:      ));

As long as your values in the As() method match the number of columns that you specified in the header when you registered your table, you'll be fine.

Conclusion

If you are feeling adventurous, check the code out. It's commited in Stormwind SVN Trunk at Accuracy Trunk.

There's only one bug yet. The header is not working because Watin does not recognize TH's as TableCells. I'll try to contribute to it, since I found the line of code that should be changed.

If you feel like contributing to Accuracy, just let me know and we can talk it out. Stormwind Project is also in need of new members to the other projects, as well as to help with documentation and portal maintenance. Just check Stormwind Project and see if you feel like helping us out!

#138

Published Sunday, March 23, 2008 10:42 AM by heynemann

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

No Comments


Enter the text you see in the image:

Leave a Comment

(required) 
required 
(required)