Automated Web Testing (1) Using WatiN
WatiN (what-in), stands for Web Application Testing In .NET, is a very easy automated web application testing framework. WatiN is developed in C# for web testing with Internet Explorer and FireFox. According to Scott Guthrie:
… it will give you exactly the experience that you'll have when a customer hits the site, which ends up being a far more accurate assessment of the application quality.
This tutorial shows how to use WatiN in Visual Studio 2008, while it can also work with other popular test frameworks like NUnit.
Preparation
The current RTM version of WatiN is 1.3, supporting only IE. The latest 2.0 CTP2 supports both IE and Firefox. Let’s go through 1.3 with IE first.
After the installing, a couple of libraries should be found in the installation folder. Typically, it is C:\Program Files\WatiN\1.3.0-net-2.0\bin. In most of the scenarios we work with WatiN.Core.dll.
Getting started with a console application
Create a console application project in Visual Studio, and add a reference to WatiN.Core.dll. Then copy and paste the following code and press F5. It should work immediately.
using System; using WatiN.Core; internal class Program { [STAThread] private static void Main() { // Opens an new Internet Explorer window and goto the Google website. IE ie = new IE("http://www.google.com"); // Finds the search text field and type "WatiN" in it. ie.TextField(Find.ByName("q")).TypeText("Dixin"); // Clicks the Google search button. ie.Button(Find.ByValue("Google Search")).Click(); // Finds the <p> which shows the search result statistics. Div div = ie.Div(Find.ById("ssb")); Para p = div.Paras[0]; string result = p.Text; // Closes Internet Explorer. ie.Close(); // Writes the statistics text to the console window. Console.WriteLine(result); Console.Read(); } }
You can watch from your screen how the IE works. The related elements will be highlighted when being operated.
Pay attention to the STAThread attribute for the Main method. It is requried because the Thread.Apartmentstate should be set to STA when using WatiN.
Working in a Visual Studio test project
Now let’s write some real test code. Create a unit test project in Visual Studio; add a new test class "WatiNTest.cs".
In this test class, write a test method like this:
using Microsoft.VisualStudio.TestTools.UnitTesting; using WatiN.Core; [TestClass] public class WatiNTest { [TestMethod] public void GoogleTest() { bool hasText; using (IE ie = new IE()) { ie.GoTo("http://www.google.com"); ie.TextField(Find.ByName("q")).TypeText("Dixin"); ie.Button(Find.ByName("btnG")).Click(); hasText = ie.ContainsText("Dixin"); } Assert.IsTrue(hasText, @"The search result does not contain text ""Dixin""."); } }
In this scenario, the STAThread attribute is not required for the test methods.
Run this unit test, and here is the result in my machine.
Now we know how to write automated web testing code against web products, no matter the product is built with of ASP.NET Web Form, or it is a rich Ajax application.
WatiN with Firefox
The 2.0 CTP2 supports Firefox, with a lot of problems of course.
First of all, download the 2.0 CTP2 package from here, and extract the WatiN-2.0.1.754-net-2.0 folder to somewhere, like C:\Program Files\WatiN.
Then, pay attention to the path of Firefox.exe. WatiN uses Firefox.GetExecutablePath() method to find Firefox.exe. For example, I am using a green version of Firefox, so I have to modify the source code to make it return "E:\Software\Firefox\FireFox.exe", which is the path of my Firefox 3.0.6. If you installed your Firefox normally, you can just ignore this step.
And an Firefox add-on, jssh, need to be installed. It can be found in the WatiN-2.0.1.754-net-2.0\Mozilla folder. For example, if using Firefox 3.0, I should install jssh-WINNT-3.x.xpi.
The last step is to close all instances of Firefox, or WatiN cannot start it.
Now create a new console application project, and add a reference to the new WatiN.Core.dll. Then run this test:
using System; using WatiN.Core; using WatiN.Core.Mozilla; internal class Program { [STAThread] private static void Main() { // Opens an new Firefox window and goto the Google website. FireFox firefox = new FireFox("http://www.google.com"); // Finds the search text field and type "WatiN" in it. firefox.TextField(Find.ByName("q")).Value = "Dixin"; // Clicks the Google search button. firefox.Button(Find.ByValue("Google Search")).Click(); // Finds the <p> which shows the search result statistics. string result = string.Empty; WatiN.Core.Mozilla.Element div = firefox.Element(Find.ById("ssb")) as WatiN.Core.Mozilla.Element; if (div != null) { result = div.ChildNodes[1].Text; } // Closes Firefox immediately. firefox.Dispose(); // Writes the statistics text to the console window. Console.WriteLine(result); Console.Read(); } }
There is a sample folder in the WatiN-2.0.1.754-net-2.0. When trying, exceptions are thrown from CrossBrowserTest.ExecuteTest(). So a Thread.Sleep(5000) has to be added between two Firefox test cases, so that WatiN works.
// Simple method program.SearchForWatiNOnGoogleVerbose(); Thread.Sleep(5000); // Generic method program.ExecuteTest(program.SearchForWatiNOnGoogleUsingBaseTest);
Tools for WatiN
IE Developer Toolbar should be very helpful to inspect the DOM and find the elements / attributes, like id, which makes coding easier.
WatiN Test Recorder is another powerful tool. It runs an IE instance, records the actions, and generates C# test codes.
WatiN best practices
This article, "WATiN/R Testing Design Pattern", described some patterns and practices of WatiN. Another one "WatiN Testing Pattern" is simpler. Its basic idea is to encapsulate for each page like this:
public class SomePage : IE { // Uri of the page private const string Uri = "http://localhost"; public SomePage() : base(Uri) { } // Elements of the page public TextField UserNameTextField { get { return this.TextField(Find.ByName("Username")); } } public TextField PasswordTextField { get { return this.TextField(Find.ByName("Password")); } } public Button LogOnButton { get { return this.Button(Find.ByName("LogOn")); } } // Action of the page public void LogOn(string userName, string password) { this.UserNameTextField.TypeText(userName); this.PasswordTextField.TypeText(password); this.LogOnButton.Click(); } }
Then testing code can be easy and clear:
[TestMethod] public void SomePageTest() { bool hasText; using (SomePage somePage = new SomePage()) { somePage.LogOn("Dixin", "Password"); hasText = somePage.ContainsText("Dixin"); } Assert.IsTrue(hasText, "Message"); }
The future of WatiN
WatiN is one of the easiest web testing frameworks for .NET developers / testers. According to the official blog, hopefully after finishing Firefox support, Chrome support will be there very quickly. But I am a little confused with the design of WatiN 2.0.