In my first post about WatiN I introduced the open source API, and provided a simple demo to give a taste of what WatiN is capable off. I ended that post with a promise to write a follow up on some of the lessons I’ve learnt. Here they are:
- .NET control ids are not friendly
WatiN allows you to select any DOM element based on a specified id (or a myriad of other attributes) as follows:
Unfortunately, .NET control ids are rarely as friendly.You’ll quickly find your tests littered with control ids like ‘ctl00_ContentPlaceHolder_ControlId’ making the tests hard to read and overly verbose. The solution is to supply your own regular expression when selecting an element to match only the end of the control id as shown below.
public static Regex PartialClientId(string partialClientId)
return new Regex(".*_" + partialClientId + "$");
To use the regular expression you need to provide it as a parameter to the selector:
- Tests are linked to ids
Finding a control by id (or name, class, etc.) creates a dependency on that id not changing. Refactoring a control’s id will break all tests relying on it causing you to make sweeping changes which takes time. The solution I use is to create a static class for each web form in my website, under my test project. The class defines constants for all control ids (or names, classes, etc.) that could be referenced in the unit tests. The unit tests use the constants instead of the actual control ids meaning that any change in the web form only needs to be made in one place.
- Tests repeat
If you’re building a suite of tests for your website you’ll quickly see that you have to perform the same actions again and again. For example, if you’re testing your e-store you’ll have unit tests for searching for a product and adding products to the shopping cart. If you code these two tests from scratch, the second test would include searching for products. Again, this means if you make any changes to your search unit test you’ll need to make the same change somewhere else. A simple solution is to think of code re-use. Create helper methods for each action like searching, and then call it where appropriate. For example, my helper method would accept a search string and return the results grid.
That’s all I’ve got so far. Hope it helps.