Unit Testing ASP.NET Pages Using WatiN
By AzamSharp
Views: 7639

Introduction:

Unit testing is an integral part of the application design. Unit testing is applied at different levels of the application. In this article we will focus on the User Interface level unit testing. We will use WatiN to test our ASP.NET application.

What is WatiN?

WatiN is a tool inspired from Watir (Don't worry I will write an article on Watir  very soon) to test web pages. WatiN stands for Web Application Testing in .NET.

What are we testing?

In this article we will be testing a simple ASP.NET page. The page will demonstrate an agreement acceptance scenario. The user will type his name in the TextBox, click the “I agree” checkbox and then press the submit button. This is a very simple page to test but after you are familiar with the workings of the WatiN framework you can apply the same concepts for testing large pages.

Here is the screen shot of our page:

 Testing the Agreement Page:

Add a class library project to your solution and make references to the testing tool (I am using MbUnit but you can use NUnit or VS Team Suite Test Project) and the WatiN library. You can download the WatiN library from the here.  

Here is the simple test which makes sure that the user has agreed the agreement.

[TestFixture(ApartmentState = ApartmentState.STA)]
    public class TestAgreementPage
    {
        [Test]
        public void test_can_accept_the_user_agreement()
        {             
            IE ie = new IE(ConfigurationManager.AppSettings["DefaultPageUrl"] as String);

            ie.TextField("txtName").TypeText("Mohammad Azam");

            ie.CheckBox("chkAgree").Checked = true;
           
            ie.Button("Btn_Agree").Click();

            Assert.AreEqual("Valid",ie.Span("lblMessage").Text);           
        }       
       
    }

The class is decorated with the TestFixture attribute which also makes sure that the tests are run in a Single Threaded Apartment state. This is because the test will launch the Internet Explorer.

The IE class contained in the WatiN library does the main work. IE class opens the Internet Explorer and refers to the HTML controls using their name or ID. The line ie.TextField(“txtName”).TypeText(“Mohammad Azam”) refers to the TextBox with the ID “txtName”. When the browser is launched WatiN will write the text “Mohammad Azam” inside the TextBox named “txtName”. This will be done right before our eyes and you would be able to see WatiN typing text into the TextBox. Then the CheckBox with the ID “chkAgree” will be checked. Finally, WatiN will press the submit button and the form is submitted.

If you run this test it will fail. This is because the Label named “lblMessage” is never set to “Valid”. Let’s do that in the page code behind.

 protected void Btn_Agree_Click(object sender, EventArgs e)
        {
                lblMessage.Text = "Valid";
        }

Now, if you run the test it will pass. But, something does not seem right. Let’s remove the following line from our test.

ie.CheckBox(“chkAgree”).Checked = true;

This means we are not going to mark the CheckBox as checked. If you run the test again it will pass. This is not right! The test should only pass when the CheckBox is checked. Let’s make a change to the code behind of the page.

protected void Btn_Agree_Click(object sender, EventArgs e)
        {
            if (chkAgree.Checked)
            {
                lblMessage.Text = "Valid";
            }
        }

Now, the test will only pass when the CheckBox is checked.

Programmatically Running the Web Server:

In the above example you will need to start your WebServer by either manually running the command line tool or by running the Web Application Project. But, sometimes you will want the unit test project to dynamically start a web server. Let’s check it out how this can be done.

First, if you want to start the ASP.NET internal server (WebDev.WebServer) then you can use command line to start it. The syntax is shown below:

WebDev.WebServer.exe /port:1950 /path: “C:\Projects\MyWebApplication”

You will need to be in the same directory where the WebDev.WebServer exists. By default it is located at:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\WebDev.WebServer.exe

Now, let’s use this information to start the server using unit tests. First, here is the required configuration saved in the configuration file (App.config).

<configuration>

  <appSettings>
    <add key="WebServerExePath" value="C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\WebDev.WebServer.exe"/>
    <add key="Port" value="1950"/>
    <add key="WebApplicationPath" value="c:\projects\demowatiN\demowatiN"/>
    <add key="DefaultPageUrl" value="
http://localhost:1950/Default.aspx"/>  
  </appSettings>
 
</configuration>

The BaseTestPage class will use this information to start the server and all the test classes will derive from the BaseTestPage class to use this functionality. 

Here is the complete code for the BaseTestPage class:

public class BaseTestPage
    {
        static Process server = null;

        static BaseTestPage()
        {
            if (Process.GetProcessesByName("WebDev.WebServer").Count() == 0)
            {
                string webServerExePath = (string)ConfigurationManager.AppSettings["WebServerExePath"];
                server = new Process();
                Process.Start(webServerExePath, GetWebServerArguments());
            }
        }

        public static string GetWebServerArguments()
        {
            string args = String.Format("/port:{0} /path:\"{1}\"",GetPort(),GetWebApplicationPath());
            if (String.IsNullOrEmpty(args)) throw new ArgumentNullException("Arguments is not defined");
            return args;
        }

        public static string GetPort()
        {
            string port = ConfigurationManager.AppSettings["Port"] as String;
            if (String.IsNullOrEmpty(port)) throw new ArgumentNullException("Port is null or empty");

            return port;
        }

        public static string GetWebApplicationPath()
        {
            string webApplicationPath = ConfigurationManager.AppSettings["WebApplicationPath"] as String;
            if (String.IsNullOrEmpty(webApplicationPath)) throw new ArgumentNullException("WebApplicationPath is null or empty");

            return webApplicationPath;
        }

      
    }

We used a static constructor to make sure that the process is not running. If it is not running we make a new process and start it else we use the old process. The GetWebServerArguments(), GetPort() and GetWebApplicationPath() are just helper methods to improve the readability.

Finally, you will derive all your unit test classes from the BaseTestPage class as shown below:

public class TestAgreementPage : BaseTestPage

Now, if you run your unit test project will start the WebServer and then run all the tests.

Conclusion:

In this article we learned how to unit test our user interface layer. Unit testing the user interface helps us to understand the requirements of the interface and quickly see the expected result based on the user input. If this testing is done manually then it might take a lot of time.

By AzamSharp


Enter Comment/Feedback
  •  
  •  
  •  
  •  
  •  

Comments/Feedbacks
Subject: Alternative to WatiN
Name: ftorres
Date: 1/27/2008 12:40:07 PM
Comment:
I just rewrote your test using the InCisif.net api.



[InCisif.net.Library.Test("WaitUntilRemoved Unit Test",1,TestPriority.High)]
public void WaitUntilRemovedWithFrameUnitTest(){

using ( InCisif.net.Library.Test t = new InCisif.net.Library.Test(Language.CSharp, this) ) {

Page.URL = ConfigurationManager.AppSettings["DefaultPageUrl"] as String;
Page.WaitUntilIdle();

Page.Control("txtName").Text = "Mohammad Azam";
Page.Control("chkAgree").Checked = true;
Page.Control("Btn_Agree").Click();

Assert.AreEqual("Valid",Page.Control("lblMessage").Text);

t.Passed = true;
}
}
Subject: RE: Alternative to WatiN
Name: AzamSharp
Date: 1/28/2008 10:42:37 AM
Comment:
Hi ftorres,

Thanks for this information. I was not aware of this tool.

Thanks,
Subject: InCisif.net and WatiN
Name: ftorres
Date: 1/30/2008 6:58:42 PM
Comment:
I rewrote your test using the InCisif.net api:

[InCisif.net.Library.Test("My comment",1,TestPriority.High)]
public void test_can_accept_the_user_agreement(){

using ( InCisif.net.Library.Test t = new InCisif.net.Library.Test(Language.CSharp, this) ) {

Page.URL = ConfigurationManager.AppSettings["DefaultPageUrl"] as String;
Page.WaitUntilIdle();

Page.Control("txtName").Text = "Mohammad Azam";
Page.Control("chkAgree").Checked = true;

Page.Control("Btn_Agree").Click();
Assert.AreEqual("Valid",Page.Control("lblMessage").Text);

t.Passed = true;
}
}


We also integrated cassini in our api.

Subject: Javascript and Ajax
Name: Carlos Veber
Date: 3/26/2008 10:29:57 AM
Comment:
How does WatiN and/or InCisif interact with ajax (update panels, render controls in runtime, etc) and javascript (alerts, validations, etc) ?
Subject: Integrate with Ajax technology
Name: Thomas Hansen
Date: 5/13/2008 11:45:14 PM
Comment:
Watin integrates perfectly with Ajax technology, we're using it to debug our Ajax library; http://ajaxwidgets.com I wrote a video blog about it some few months ago in fact. How we're using it to unit test our Ajax library :)
Subject: Another Web Testing Tool For The .NET Platform
Name: ftorres
Date: 5/20/2008 5:49:47 PM
Comment:
InCisif.net is an automation tool designed to implement functional web testing
under Internet Explorer, using languages VB.Net, C# within Visual Studio 2005, 2008 or Express.
Subject: Feedback
Name: Marina
Date: 6/22/2008 3:59:22 PM
Comment:
Hi Azam,

Would be great if you provided more details about Watin configuration.
For example about such important parts as SetUp and TearDown.
If a beginner reads your article, he/she might be frustrated for hours trying to figure out why app doesn't compile.

Other than that the article is great.
Subject: RE: WatiN Feedback
Name: AzamSharp
Date: 6/27/2008 11:27:12 AM
Comment:
Hi Marina,

There is really no configuration you need to perform in web.config to make WatiN work. You only need to add the required DLL and that's it. Please visit www.azamsharp.com and check out the Unit Testing Articles.




Join WebHost4Life.com






Copyright GridViewGuy 2007-2008