Sunday, July 6, 2014

Web UI Testing Part 3: The Page Object Model

Whether you end up WatiN or Selenium for automating the browser actually doesn't matter that much.  Whichever mechanism you use should be hidden behind a Page Object Model.  This actually took me a while to discover because it wasn't really in your face on the WatiN and Selenium forums.  In fact even once I knew about the pattern I didn't feel the need for it at first.  It was similar to having a domain controller for a couple of computers.  However, as the sites I was writing and testing got more complicated, I needed a way of organizing the methods to manipulate the pages into a logical grouping.  It makes sense to make an object model that encapsulates the ID, classes, tags, etc. inside a page so that they can be reused easily.  Let's look at a simple example in WatiN, prior to putting in the Page Object Model.

[Given(@"I am on an item details page")]
public void GivenIAmOnAnItemDetailsPage()
{
browser = new IE("http://localhost:12345/items/details/1?test=true");
}

[When(@"I update the item information")]
public void WhenIUpdateTheItemInformation()
{
browser.TextField(Find.ByName("Name")).TypeTextQuickly("New item name");
browser.TextField(Find.ByName("Description")).TypeTextQuickly("This is the new item description");
var fileUpload = browser.FileUpload(Find.ByName("pictureFile"));
string codebase = new Uri(GetType().Assembly.CodeBase).AbsolutePath;
string baseDir = Path.GetDirectoryName(codebase);
string path = Path.Combine(baseDir, @"..\..\DM.png");
fileUpload.Set(Path.GetFullPath(path));

The ?test=true in the first method is interesting, but the subject of another blog post.  Instead Notice the Find.ByName("Name") in the second method.  Now what if there is another method where I need to check the name to see what is there.  And yet another where I need to both check it *and* update it.  So I would have three places and four lines where that Find.ByName("Name") would be used.

What happens when I change the element to have a different name?  Every test where I have used Find.ByName("Name") breaks.  I have to go through and find them all and update them. 

Let's look at the same two methods, but this time with a PageObject model.

[Given(@"I am on an item details page")]
public void GivenIAmOnAnItemDetailsPage()
{
browser = new IE(Pages.ItemDetails.Url);
}

[When(@"I update the item information")]
public void WhenIUpdateTheItemInformation()
{
Pages.ItemDetails.SetName("New item name");
Pages.ItemDetails.SetDetails("This is the new item description");
Pages.ItemDetails.SetPictureFile("DM.png");

A couple of interesting things happened.  The first is that the test is a lot more readable.  The second is that I now have a central place to change when something from the page changes.  I fix one line, and now all of the tests are running again.


So to recap, Page Object Models are great when either the pages are volatile or the same pages are being used for lots of different tests.

Tuesday, June 24, 2014

Xamarin Forms changes the game

Although Xamarin has been around for a while now, there were cross platform mobile projects where I did not recommend its use.  These were generally projects that had a large number of screens.  In such cases the process of creating multiple versions of every screen could make the project too difficult and time consuming to write.  In these cases I might recommend going with PhoneGap if the shop has web development experience.  Now that Xamarin Forms has released (at the end of May), all of the UI can go into a common layer, written in a single paradigm.  This allows the vast majority of the assets to be reused across platforms.  Of course it still doesn't mean that *all* of the code will go into a common layer, just that *most* of it will.

One a personal note it is interesting that the Xamarin Forms release happened while we were in the middle of the mobile development track for the San Diego TIG.  It is changing the industry, and it also changed our track.  We removed the PhoneGap meeting from the end of the track after a brief discussion of the technology.


[Update: September One thing I have noticed since I started using Xamarin regularly is the flakiness of the product.  When you pay this much for a product you expect a higher level of quality.  The start debugging, then restart debugging, then stop the simulator and restart debugging again is getting old]

Monday, June 2, 2014

New SQL Tip: SET XACT_ABORT ON

I have a new SQL Tip about SET XACT_ABORT.  If you're unfamiliar with this setting, you should definitely spend three minutes and watch this tip:



CREATE TABLE t1(

col1 INT PRIMARY KEY)

GO

INSERT INTO t1
VALUES
(1)
,(
2)
,(
3)
,(
4)-- Assuming SET IMPLICIT_TRANSACTIONS is OFF


INSERT INTO t1
VALUES(1)

INSERT INTO t1
VALUES(99)
-- Which rows get inserted?

SELECT * FROM t1-- Which rows get inserted for this explicit transaction?
BEGIN TRANSACTION;
  
INSERT INTO t1
  
VALUES
  
(1)

  
INSERT INTO t1
  
VALUES
  
(100)

COMMIT TRANSACTION;
GO-- Which rows get inserted?  Did 100 get inserted?
SELECT * FROM t1-- With SET XACT_ABORT?
SET XACT_ABORT ON;
BEGIN TRANSACTION;
  
INSERT INTO t1
  
VALUES
  
(1)

  
INSERT INTO t1
  
VALUES
  
(200)

COMMIT TRANSACTION;
GO
DROP TABLE t1

Sunday, June 1, 2014

Web UI Testing Part 2: Front-door testing tools

Because of the two problems I mentioned with back-door web testing (changes to layout and no Javascript testing), I was looking to pursue front-door web testing toward the end of 2012. 

My first thought was that whatever framework I chose should have a test recorder so that writing the tests would be much easier than having to code up every little click and wait.  The problem with this philosophy is that most of these test recorders generate code.  It turns out that generating code in a maintainable way is hard, and all code should be maintainable, even test code.  So although recorders can be useful in learning how to write tests I eventually scrapped that path, and started looking at using a nice API to drive the browser.

I looked at two different frameworks in .NET for accomplishing this: WatiN and Selenium.  Both had great feature sets and either one would have been suitable.  At the time, Selenium's documentation was way too fragmented.  There were multiple versions: Selenium 1.0, Selenium RC, Selenium 2.0 , etc.  Because I was new I wasn't sure which one to use (e.g. was 2.0 stable?).  When I did a search I ended up on a blog posts using outdated methods, or the blog posts didn't indicate which version of the API was being used.  I found WatiN's documentation to be much clearer on the .NET side.  I went with that, although both tools offer an API which is easily to understand.  I later ended up regretting my choice.  WatiN only supported IE, and although the bulk of the bugs were in IE, I found a few bugs on the other browsers that I wished I had a way of automating.  WatiN later started supporting Firefox after I finished the project.


[Update: Selenium has been on version 2.0 for a while, and the older documentation is becoming less relevant in search engines, so I would probably go with Selenium today]