In my latest project I am utilising WatiN to perform my website testing. This is not the first time I have used it in a project but it is the largest test project I've had to create and I've come across a couple of challenges.
Early on I realised my code was becoming increasingly difficult to manage and well rather messy due to all the control find declarations that existed within my tests. So I decided to see if anyone had implemented a nice pattern for WatiN tests that they could recommend. And low and behold I came across a couple and I have included them as references as the bottom of this blog. There are slight variations for both and undoubtedly you will vary your own to suit the situation you are working with but the underlying principals are the same.
First of all we create a page class for every page of our website. This page class is going to contain all the controls that we need to access on our page. The page class is going to inherit from the IE object and instantiates itself using the correct url. Let's look at an
example
public class BaseModelPage : IE { public const string PreConfiguredModelURL = "/BaseModel.aspx";
public BaseModelPage() : base (SharePointSiteFixture.Site.Url + PreConfiguredModelURL){}
public Button AddToQuoteButton { get{ return Button(Find.ById(new Regex("AddToRequestButton"))); } }
public Button EditSpecButton { get{ return Button(Find.ById(new Regex("EditSpecButton"))); } } }
|
From here its a matter of removing all the control find code you had in your tests, reference the new page class and now our tests are clean, easy to read and is a true representation of what we're testing.
So here is what it looks like
after the cleanup [SetUp]] public void SetUp() { page = new BaseModelPage(); }
[Test] public void AddQuoteAndEditSpecButtonsAreHidden() { Assert.That(!page.AddToQuoteButton.Exists); Assert.That(!page.EditSpecButton.Exists); }
|
We can also abstract out common scenarios or workflows out to the classes also. For example if there are some textfields we need to fill out multiple times to cover off a couple of test scenarios then we'll pull this code into a method in our page class and simply reference it from our test. Again, our tests are becoming more clean and simple. Lets look at another test that calls one of these methods.
[Test] public void SubmittingValuesHidesConfigureFormShowsButtons() { page.SubmitValues();
Assert.That(!page.ConfigureForm.Exists); Assert.That(page.AddToQuoteButton.Exists); Assert.That(page.EditSpecButton.Exists); }
|
Another thing we can do is extend our page classes further to handle moving between pages. This is useful when you have a transactional website and you need to test page sequence. In this scenario we add another constructor which accepts an IE instance. Then we can call this constructor from another page class in order to return the new page.
public QuoteRequestPage(IE instance): base(instance.Uri){}
internal QuoteRequestPage GoToQuoteRequestPage() { RequestQuoteButton.Click(); return new QuoteRequestPage(this); }
|
So that pretty much sums it up. I certainly recommend following a pattern like this as the maintainability of your code is greatly increased and your tests become clean and readable.
Ref1 - James Avery
Ref2 - Richard Griffin
No comments:
Post a Comment