Thursday 6 December 2012

Page objects....why not Email Objects????

I have been working on the Selenium Webdriver automation of a website which requires all new users  to confirm via an email as part of the registration flow.

This presents a challenge to test automation as we obviously want to verify the registration process post email confirmation and if we do not have a suitable API to create test users, this may be a key process for all tests to use; fortunately in my case there was an API to create users but I was still keen to prove the entire registration flow.

Once we have cracked the problem of generating new accessible email addresses for each tests such as adding "+" to the end of Gmail addresses or using a temporary provider such as Dispotable, there are a few options open to us;

Don't automate

"Hey, we have to accept that not everything can be automated, we still need  manual testers, let them do it"

I just can't let that happen! I want to automate everything ;-)

Automate an email client

"Gmail is a webpage, we can automate a web page, therefore we can automate Gmail"

Well, yes you can BUT you have even less control over this GUI then the one you are testing. How often are you going to have to maintain tests because Google decide to change the layout? Do you really want to test someone elses website? Your tests are going to be flakey enough without adding a 3rd party GUI into the mix!

So..

Having chosen Gmail as my email provider (I just added a GUID to the end of a base email address), I then decided to use the Gmail IMAP API to access.  It was then easy to call a method in my test which polled Gmail API until an email arrived addressed to my new email address.  Once I had this email, I could extract the HTML of the email, but what to do with this HTML????

Initially I did what I subsequently found others had done; extract the URL of the required link using somekind of HTML parser of XPATH engine, then use the Navigate method in Selenium to navigate the browser to this address (see http://www.seleniumtests.com/2011/08/verify-email-confirmation-using.html ).

While this works, it still doesn't quite feel right. What if the link is hidden? What if we want to validate other aspects of the email?

I then stumbled upon something which should have been obvious; I was using Saucelabs and had a couple of problems;

1. Tests would time out if no command was received within 90 seconds

2. The video of the test would look very slow as we would be stuck on one page without any obvious processing going on, and everybody hates slow tests!

To fix this I decided to use Selenium to inject simple HTML (I only know simple HTML!!!) displaying a message on a blank browser so any viewer of the video would know what was going on.  This would then be injected every 30 seconds to keep Saucelabs happy as well.

Then it was either a "DOH!" or 'Eureka" moment; if I can inject my HTML, then I can inject the email's HTML as well.

So that's it, the idea of Email objects was born. Emails are not different from web pages. They are HTML, they have a DOM, they can be processed, they can navigate to other pages. They can have links, they can have buttons, they are just HTML pages.

I had to escape some offending characters which resulted in java script errors, but apart from that it was surprisingly easy and appears to work across platforms and browsers. I created a base email object which had very similar methods and properties to a base page object such as Load(), IsOnEmail(), ClickLink(int idx), WaitForLoad(), etc.  The base email object can then wrap a lot of the boilerplate code as well, so adding a new type of email is very easy

I've only be using Email Object this for a week, so I am not sure of the best approach yet, and would love to hear from others, and if interested I can share code examples.

Here's an example of what a test using email objects looks like;



     .......

     registrationPage.ClickSendEmail();

     var confirmationEmail = new ConfirmationEmail(_driver, "test+hgjhgjgj@gmail.com";

     confirmartionEmail.WaitForEmail();
     
     Assert.IsTrue(confirmationEmail.IsOnEmail());
     
     var registrationFinalPage = confirmationEmail.ClickConfLink();


     ........







6 comments:

  1. Though idea seems interesting, the code example does not really manifest it clearly. b/w I suppose you meant to use word "Disposable" and not "Dispotable" :)

    ReplyDelete
  2. Actually I meant Dispostable (http://www.dispostable.com/)

    ReplyDelete
  3. Sending time does matter too. Find your best sending time experimentally. Split your email list into 3-5 smaller groups and send the same email copy to each group at a different time and day. Monitor open rate for each group. You will clearly see which copy and at which time and day performed better. Plan your future email campaigns with regards to your tracking results.



    email testing

    ReplyDelete
  4. Would be interesting to see an email object implementation example. The example of how to use the object isn't of much use since it's just another page object...

    Would also like to see how you inject the email HTML into the page and what page in particular as well.

    ReplyDelete
  5. That is the point; an email object is just a page object. Both email and web pages are HTML.

    With regards to injecting the email HTML, it is just simple JavaScript executed via WebDriver

    ReplyDelete