Sunday, December 4, 2011

Another abstraction layer on top of PageObjects with Selenium

Hi everyone,

As I mentioned before, on this project our Selenium 2 tests are extremely important. We've tried to keep the test code on the level of the production code, so it naturally has its own object model. We already use PageObjects extensively in the project.

Recently a few bugs popped up that we reproduced with Selenium tests that were pretty similar and required similar actions. Here's an example of some duplicated code:

// first step: log in as a temp to accept a need
LogOn login = new LogOn(WebDriver);
login.Go();
login.Login("Temp", "temporary");

TempNeeds need = new TempNeeds(WebDriver);
need.ViewFirst();
need.Accept();

login.Logout();
login.Go();
login.Login("Chris", "foo");

Billing billing = new Billing(WebDriver);
billing.Go();
billing.CreateNewInvoices();
billing.UpdateAndReview();
billing.FinishCreate();

Turns out this bit of logic is common in our tests, so it gets duplicated everywhere. So in the interest if minimizing the amount of code, I modified it to look more like this:

Temp temp = new Temp(WebDriver, "Temp", "temporary");
temp.AcceptFirstAvailableNeed();

Admin admin = new Admin(WebDriver, "Chris", "foo");
admin.CreateInvoices();

This code does the same thing, it's just been hidden by another abstract layer that represents the different users of the site and what they would do. Usually, each method off of a user would interact with many different PageObjects. The idea is to make the code reveal its purpose more by telling you what the user is trying to do, not the different PageObjects that need to be used.

Anyway, we're trying this approach out now for newer tests so we'll see how it goes. Hopefully the more tests we write and the more objects we build up, the less new Selenium code we'll have to write.

No comments:

Post a Comment