TestDriven.Me

I hope to spend some time discussing testing with VB.NET. I don't think of myself as an expert, but I have had some experience and certainly some opinions. I will try to share some of those opinions along with some information and hopefully generate some discussion so that we all can improve our skills a bit.

April 2008 - Posts

Testing Web Pages - Things to Consider

Connecting to Internet Explorer

Before issuing any commands to Internet Explorer, you must first create an instance of it. 

Acceptable Method

The basic method for doing so is shown next:

        Dim ie As IE = New IE(http://localhost:3587/default.aspx)

It is easy to see that the only parameter provided to the IE function is the URL that should be navigated to once the instance is created.  Once this command has been executed, the IE instance is now available to issue commands to Internet Explorer.

 

In this case the localhost on port 3587 was used as the domain name.  This will start the local ASP.NET Development Server (the port number may be different on your machine).  It is equally possible to visit any web page on any web server, such as a corporate intranet development server or the Internet.  The only requirement for creating the new IE instance is that you must pass in a valid URL.

 

Sometimes, the creation of the IE instance will be placed in the setup function for the text fixture (class) because the same URL will be used for all tests within the fixture and the creation of the IE instance is frequently the slowest part of the tests.  Care should be taken that each tests starts with a stable session which is not corrupted by changes made in other tests within the class.  Internet Explorer has some aggravating habits of holding on to the objects created during prior visits to a URL (caching) and will try to use the internal copy of the object rather than creating it again.  I have seen examples using the Setup function where the author suggests ensuring the use of ie.Refresh() to get around the cache problem, but I still do not trust it. The safest method of ensuring that this is not a problem is to create and close the IE during each test.  As will be seen at the end of this section, there is yet one more reason not to Dim the IE instance in the setup.

 

When you open the IE instance with the Dim statement, you must be sure to dispose of it properly by using the following method to close the Internet Explorer instance:

 

        ie.close()

Simple and to the point, no parameters required.  This command will close the web browser.  There may be times that you wish for the browser to stay open after a test, especially if you are running only one test and want to see the state of the browser at the end of the test.  It is safe to omit this command.  You will then have to close the browser manually after you are done reviewing it.  For test runs with many individual tests, it is generally better to insert the close command at the end of the test, or you may find yourself closing 20 or 100 browser windows at the end of the run!

Recommended Method

An even better way to connect to a new instance of Internet Explorer is with the Using statement provided in .Net 2.0.  The following line takes the place of the DIM statement shown earlier.  An additional benefit is that the ie.Close is now no longer needed.  For the information of those that do not already use the Using statement, it combines the benefits of Dim with the assurance that resources will be closed and released when the End Using is processed, even in the event of a bug which transfers control out of the block.  So the recommended and best way to conduct your tests is to use the following construct:

 

        Using ie As IE = New IE("http://localhost:3587/default.aspx")
           ' Test code here
        End Using

It would not be possible to combine the Using statement with the use of Setup methods, which is probably the single biggest reason not to open the IE instance in a setup method.  The safety net supplied by the Using command trumps the speed increase of opening IE only once.

Identifying Elements on the Web Page

In order to automate actions within the browser, WatiN must be able to uniquely identify the various elements and controls on the web page to be tested.  Elements can be found by a wide range of attributes.  The Find.By construct used by WatiN includes:

 
  • Alt – Search the Alt text of controls for one matching supplied text.
  • Custom – Specify any attribute name and the text to match by.
  • For – Search for a label element by the ID of the element it is linked with.
  • ID – Search for an element by its ID.  The most basic search.
  • Index – Search for an element by its index within the DOM tree.
  • Name – Search for an element by its name attribute.
  • Source – Used with images to search by their src attribute.
  • Style – Search for an element using a particular style attribute.
  • Text – Search for an element with specific text identifying it.
  • URL – Find an element, frame, IE instance or dialog by its URL.
  • Value   - Search for an element with a specific value.
 

With one of these methods, it should be possible to identify the exact element on the page to interact with.  As you will see in the following sections, Find.By is used in conjunction with other methods and never alone.

Identifying Controls

The astute reader will have gotten the feeling that the earlier simple examples cheated somewhat on one minor detail, the ID if the controls accessed.  We all know that real web pages have master pages, usercontrols, naming containers and such that ASP.NET uses to mangle a simple name like OKButton into a much more verbose unique ID like ctl00_ContentPlaceHolder_UserControl1_OKButton.  Simply looking for OKButton with a call like the following will fail because OKButton is only part of the ID and WatiN requires the entire ID in the exact case used when the control was created to find the control.

Incorrect Method

 

  ' Bad example: This will not find ' ctl00_ContentPlaceHolder_UserControl1_OKButton

 ie.Button(Find.ById("OKButton")).Click()

Fortunately, there are several good ways around this problem.  Before they are discussed, however, the bad way will be presented along with why it is bad so the reader will not be tempted to use it.

 

 

ie.Button(Find.ById("ctl00_ContentPlaceHolder_UserControl1_OKButton")).Click()

True, this example will indeed find the proper button and click it.  The problem is in the maintainability of the tests.  Consider for a moment that you have created 50 tests for this web page and all of the calls to the controls use a similar construct with the ID specifically spelled out.  Next consider that during code review, the reviewer correctly mentions that UserControl1 is not very self documenting and requests that you change the name of the control to SomeActivityUserControl, where “someactivity” relates to what the control is doing.  ASP.NET will not have a problem with this and will happily change the ID of the OKButton and all the other controls inside the user control to be ctl00_ContentPlaceHolder_SomeActivityUserControl_OKButton.  So all those IDs that were working so well for WatiN are now incorrect and every test you have ceases to work until you go through and change all the hard-coded IDs.

A Better Method

A better way that also makes the tests more readable and saves work is to define constants at the top of the class to hold the control names.  Then whenever a change to the control names occur, you have only one place to change and all the tests still work.  Look at the example which follows:

 

Imports NUnit.Framework
Imports WatiN.Core
 
<TestFixture()> _
Public Class DefaultTests
 
Private Const currentURL As String = "http://localhost:3587/Default.aspx"
 
    Private Const OKButton As String = "ctl00_ContentPlaceHolder_UserControl1_OKButton"
    Private Const CancelButton As String = " ctl00_ContentPlaceHolder_UserControl1_CancelButton"
    Private Const MessageTextBox As String = " ctl00_ContentPlaceHolder_UserControl1_MessageTextBox"
 
    ''' <summary>
    ''' Ensure that on clicking the OK Button
    ''' that OK is added to the textbox properly.
    ''' </summary>
    ''' <remarks></remarks>
    <Test()> _
        Public Sub TestButtons()
        Using ie As IE = New IE(currentURL)
 
            ie.Button(Find.ById(OKButton)).Click()
            Assert.IsTrue(ie.TextField(Find.ById(
            MessageTextBox)).Text.Equals("OK"),
"TestButtons did not find OK in the textbox
after OK button clicked.")
 
        End Using
    End Sub
 

End Class


Now we have placed the IDs of the controls into constants which make reading the test easier.  If OKButton becomes ctl00_ContentPlaceHolder_SomeActivityUserControl_OKButton then the one change is made in the assignment of the value of the constant and this test and all the rest using the OKButton will continue to work without any change.  Not very much overhead for ease of maintenance later, and we also increased readability.

Recommended Method

There is another finesse which makes things even better.  Examine the following code which is almost the same:

 

Imports NUnit.Framework
Imports WatiN.Core
Imports System.Text.RegularExpressions
 
<TestFixture()> _
Public Class DefaultTests
 
    Private Const OKButton As String = "OKButton"
    Private Const CancelButton As String = "CancelButton"
    Private Const MessageTextBox As String = "MessageTextBox"
 
    ''' <summary>
    ''' Ensure that an clicking the OK Button
    ''' add OK to the textbox properly.
    ''' </summary>
    ''' <remarks>
    ''' currentURL is a Private Const =
    ''' "http://localhost:3587/Default.aspx"
    ''' OKButton is a Private Const = "OKButton"
    ''' MessageTextBox is a Private Const = "MessageTextBox"
    ''' </remarks>
    <Test()> _
        Public Sub TestButtons()
        Using ie As IE = New IE(currentURL)
 
            ie.Button(Find.ById(New Regex(OKButton))).Click()
            Assert.IsTrue(ie.TextField(Find.ById(New
            Regex(MessageTextBox))).Text.Equals("OK"),
"TestButtons did not find OK in the textbox
after OK button clicked.")
 
        End Using
    End Sub
End Class

The import for System.Text.RegularExpressions was added and the Find function calls now have been modified to use a new Regex pattern.  This small change has tremendous importance however.  Now if the change is made to the ID of OKButton as discussed in the last example, no change is needed to the unit tests.  None, zip, nada.  The regex commands will find the unique IDs that you as a developer already chose for your controls even with the wrapper of all that verbosity that ASP.NET puts on them to ensure uniqueness.

Using the WatiNTestRecorder

Another way to identify controls and also to get help with the syntax required by WatiN is to use the WatiN Test Recorder tool created by Daaron Dwyer.  It is still in its infancy at the time of the writing, but is expected to flourish into a marvelous tool to assist with WatiN.  Look at the following screenshot:

 

By placing the URL for the test web site into the address bar of the recorder, it has opened our page to be tested.  Now, if we enter a name for the test, such as “Test1” and click the Record button, the recorder will write part of the WatiN test for us as we click and interact with the web page.

 

After starting the recording and clicking the OK button the recorder has created the following test:

 

This is very similar to what we came up with on our own.  The recorder chose Find.ByName rather than Find.ByID and does not know about using Regex but will gladly put the specific long unique ID into the tests it writes, so we will have to modify the tests that the recorder creates a bit to make them all they can be.  The WatiN Test Recorder at this time implements Asserts and provides extensibility with its functions, which can be viewed by right clicking on a control within the browser. 

 

Even though the recorder has some quirks, such as it does not capture which item is selected in a drop down list properly, it still is very helpful in writing tests for complicated pages.  Its greatest value at this time is that once you are done recording, just click the Stop button and copy and paste the test code into your class, modify it a bit, and you are essentially done.

 

The recorder also has several other handy features.  Click on the HTML Source button.  There is the complete source for the web page in case you need to look for something specific that does not have a proper name or ID.

Starting the ASP.NET Development Server

Visual Studio 2005 introduced the ASP.NET Development Server, also known as the Cassini server, as a way to run web pages on computers that did not have IIS installed.   It is very useful for running WatiN unit tests, but requires a small amount of setup.  There are basically two things that need to be done:

 
  • Ensure that the web project is designated to run under the Development Server
  • Ensure that the Development Server is running
 

Both of these requirements are easily met.  The designate the project to use the Development Server, right click on the project name in the Solution Explorer and select Properties.  Click on the Web tab on the left side of the properties window.  You will be provided a window like this:

 

In the middle of the screen you will likely find that the “Use Visual Studio Development Server” selection is made by default.  If it has defaulted to “Use IIS Web Server” then you can change it here.

 

The second requirement is slightly more work, but not much.  Create a TestFixtureSetupMethod that you will place at the top of each class that you create for testing web pages with WatiN like the one shown next.  You will have to add Private Const variables as shown in the remarks and a class variable to hold the process information to the beginning of your class.

 

    Private Const baseSourcePath As String =
      "C:\Doug\WatiNTest\WatiNTest\"
    Private Const baseServerPort As String = "3587"
    Private Const currentURL As String = "http://localhost:" &
baseServerPort & "/Default.aspx"
    Private p As Process
 
 
    ''' <summary>
    ''' If the ASP.NET Development Server is not currently running
    ''' then start it in a new process.
    ''' </summary>
    ''' <remarks>
    ''' baseSourcePath is the path to the web page source files
    ''' baseServerPort is the port number to start the
    '''     Cassini server on
    ''' The path to the WebDev.WebServer.EXE
    '''     will be different with others versions
    '''     of Visual Studio.
    ''' </remarks>
    <TestFixtureSetUpAttribute()> _
    Public Sub SetUp()
 
        If Process.GetProcessesByName("WebDev.WebServer").Length = 0
Then
            ' create a new process to start the Development Server
            p = New Process()
 
            ' set the initial properties
            p.StartInfo.FileName =
"c:\Windows\Microsoft.NET\Framework\v2.0.50727\WebDev.
WebServer.EXE"
            p.StartInfo.Arguments = "/path:" & baseSourcePath &
" /port:" & baseServerPort
            p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized
 
            p.Start()
            'Give it a chance to start
            System.Threading.Thread.Sleep(1000)
        End If
 
    End Sub

 


This method will run at the beginning of the first test in the class.  You can also stop the process with the corresponding Teardown method, but it is not required.

 

    ''' <summary>
    ''' Close the ASP.NET Development Server
    ''' </summary>
    ''' <remarks></remarks>
    <TestFixtureTearDown()> _
    Public Sub TearDown()
        p.Kill()'It is best NOT to do this. See notes.
    End Sub

 


I personally omit this method, which keeps the Development Server open for the next test to be run.  Otherwise, if testing multiple classes, which is normal, then the system would have to start and stop the development server for each class.  You can close it later manually by right clicking on the icon in the system tray if you want to.  It does not use a lot of resources and seems to close on it’s own after a period of inactivity.

 

You can also start the Development Server manually by simply using F5 to start the project and display a web page.  This will start the Development Server and leave it running, but you do not have control of the port used and may have to edit your tests to set the port ASP.NET chose.

 

Contents: Table of Contents Previous Page: How to use WatiN to Test Web Pages - Part II Next Page: ;Testing Web Pages - Things To Consider/P>

Posted Wednesday, April 16, 2008 2:51 PM by ddodgen | with no comments

How to Use WatiN to Test Web Pages - Part II

Testing with the NUnit Framework

NUnit is free to download and use.  Better yet, it already comes with functionality built in that had to be created to be used by a console application, and even then the console application did not perform as seamlessly.

Create a new Solution

To begin, since we eventually will be using WatiN to test our web site, create a new project by selecting the type of web site you want to create.  (Note:  To test a legacy web site that has already been created, you would just create a class library project to hold your unit tests.)  We are going to use an Ajax Toolkit enabled site for our tests so we will choose the ASP.NET AJAX Control Project template.  You will need to select a name for the project and a place to create it as shown next:

This will create a new web site with a Default.aspx web page as shown next:

Next we need a class library for our business layer so we keep that project separate from the web site project.  Click on the File menu option, select Add and New Project, then add a Class Library which we will call BusinessLayer as shown next:

Once the project is added, delete Class1.vb.  Then add a folder for Utilities under the BusinessLayer project by right clicking BusinessLayer and selecting Add – New Folder.  Finally, we will right click the Utilities Folder and select Add – Class and give the new class the name MathFunctions.vb.

 

Now we need to add a class library for the NUnit tests.  Click on the File menu option, select Add and New Project, then add a Class Library which we will call UnitTests as shown next:

Rename the newly created Class1.vb in the UnitTests project to MathFunctionsTests.vb.  Now our Solution Explorer should look like this:

Yes, it is true that this is slightly more complicated that the console application structure.  That is because we are already creating the projects needed for the web site and its utilities which we did not bother with for the console application.

 

Add References

Right click on the UnitTests project name and select AddReference from the menu.  Add the NUnitFramework.DLL from the Bin folder that you installed NUnit into.  We also need a project reference to the BusinessLayer project.

 Edit the class for MathFunctionsTests and add the imports line for the BusinessLayer and the NUnit framework as shown next:

Imports BusinessLayer
Imports NUnit.Framework
 
Public Class MathFunctionsTests
 

End Class


 


Create Modules to be Tested

We will be using exactly the same basic definition for the GetPercentage function so you can either copy and paste the GetPercentage function from our prior console application and strip out the utility code added for logging, or type it in again into the MathFunctions.vb class under the Utilities folder in the BusinessLayer as follows:

Public Class MathFunctions
     Public Function GetPercentage(ByVal whatNumber As Double, _
ByVal whatDivisor As Double) As Decimal
        Dim answer As Decimal
 
        answer = (whatNumber / whatDivisor) * 100
 
        Return answer
    End Function
 End Class

Create Unit Tests

To create the unit test, add the <TestFixture()> _ attribute to the top of the MathFunctionsTests class, the create a public sub with the attribute <Test()> _ assigned to it.  The test itself is the same test we used for the console application with the logging and Try…Catch stripped out as shown next:

Imports BusinessLayer
Imports NUnit.Framework
 
<TestFixture()> _
Public Class MathFunctionsTests
 
    <Test()> _
    Public Sub TestGetPercentage()
        Dim answer As Decimal
        Dim numberOne As Double
        Dim numberTwo As Double
        Dim myMathFunctions As New MathFunctions
 
        numberOne = 2.0
        numberTwo = 4.0
        answer = myMathFunctions.GetPercentage(numberOne, numberTwo)
        Assert.IsTrue(answer = 50D, "GetPercentage returned " & _
            answer.ToString & " when provided " & _
            numberOne.ToString & " and " & numberTwo.ToString & _
            " when expected 50")
 
    End Sub
 
End Class

To run the test with the NUnit Test Runner, you will need to modify the properties of the project on the Debug tab to start an external program.  Use the browse button (the one with the …) to navigate to the bin folder under the NUnit installation and point to the nunit.exe executable program as shown next:

Use the F5 key to run the program and you will see the NUnit Test Runner which should look something like the one shown next:

At this point, the test runner does not know about your new tests, because it is either pointing to the default location within its own installation folder, or it is pointing to the last set of tests it was used with.  Click on the File menu option and point to the UnitTests.DLL file inside the bin folder which is under the UnitTests project in your current solution.  The test runner will now recognize your unit tests and will look like the following:

Click the large Run button and the selected tests will be run.  You should be rewarded with the green bar as shown next:

The green check marks indicate that each test passed and the green bar indicates that everything passed.  Close the test runner to stop the debugging process in Visual Studio.

 

Time to add the Divide by Zero test that caused us so much trouble in the console application.  Place this test in the same MathFunctionsTest class that contains the other tests:

    <Test()> _
    Public Sub TestGetPercentageBadData()
        Dim answer As Decimal
        Dim numberOne As Double        Dim numberTwo As Double
        Dim myMathFunctions As New MathFunctions
 
        numberOne = 2.0
        numberTwo = 0.0
        answer = myMathFunctions.GetPercentage(numberOne, numberTwo)
        Assert.IsTrue(answer = 0D, "GetPercentage returned " & _
            answer.ToString & " when provided " & _
            numberOne.ToString & " and " & numberTwo.ToString & _
            " when expected 0")
 
    End Sub

Using F5 to run the solution again we see that the test runner automatically recognizes that we have added a new test as shown next.  No need to modify controlling methods!

Clicking the Run button dashes our hopes, however.  The program did not crash, but the test clearly failed as shown next:

Our new TestGetPercentageBadData test got a red X which percolated up the tree and resulted in a red bar indicating that not all tests passed.  You can see in the notes pane that we have the same divide by zero problem.  There is a bit of a difference in how we handle it, however.  We actually expected the divide by zero, since our requirements, as you will recall, stated that we should throw an error when attempting to divide by zero.  So, our test actually passed since the error was thrown.  Fortunately, NUnit has a way to tell the test that you expect an error to be thrown.

 

Examining the error message above we see that a System.OverflowException was generated.  We just need to decorate our test method with this information as shown next to show that we expect that an exception will be thrown:

    <Test()> _
    <ExpectedException("System.OverflowException")> _
    Public Sub TestGetPercentageBadData()
        Dim answer As Decimal
        Dim numberOne As Double
        Dim numberTwo As Double
        Dim myMathFunctions As New MathFunctions
 
        numberOne = 2.0
        numberTwo = 0.0
        answer = myMathFunctions.GetPercentage(numberOne, numberTwo)
        Assert.IsTrue(answer = 0D, "GetPercentage returned " & _
            answer.ToString & " when provided " & _
            numberOne.ToString & " and " & numberTwo.ToString & _
            " when expected 0")
 
    End Sub

Now when we run the tests, we get all green:

That was a great deal easier and more intuitive than what we had to do in the console application.

 

You may have been wondering how TestDriven.NET fits into all of this.  Now is the time for you to find out.  TestDriven.NETs primary purpose is to avoid having to fire up and display the NUnit Test Runner.  Staying in the Visual Studio IDE, you right click on any test or module or group of modules that you wish to test, and choose Run Tests.  TestDriven.NETs rocket fires off and the tests run within the IDE and the results are shown in the lower left corner and the Output Window.

 

For example, to run the same two tests in TestDriven.NET that we did with the Test Runner, right click on the MathFunctionsTest.vb file in the Solution Explorer and choose Run Tests.  The system will rebuild if necessary, and run the tests within the class one at a time.  The result is shown in the lower left corner as show in the following example:

The Output window will hold the explanation of any errors as shown next:

The real power of TestDriven.NET in my opinion is in the “Test With …” menu options.  Right click on the MathFunctionsTests.vb class again and then select Test With.  The menu which pops up includes the Debugger in case you need to step through the test and the underlying code line by line to see why a test is failing as well as NCover, which will provide a report of what percentage and exactly which lines of your code were executed in the prior test.

 

There is nothing like seeing that your tests are missing portions of the code, to help you come up with more unit tests to ensure more complete coverage.  For example, many developers forget to test the catch blocks in Try…Catch constructs.  Remember, NUnit will allow you to fall into the catch block and handle the exception gracefully, so be sure to create tests that pass parameters to will cause exceptions to ensure that the catch is working properly also.

 

So, now you have written a function, created some unit tests to ensure that it works correctly and you are ready for the next step.  Take a moment to think about what has happened up to this moment, however.  In the old days, you might have written the function, then added some fields on a form somewhere to pass parameters to your new function, then started the application and run it through several pairs of numbers to see if it did what it was supposed to.  Once you are done with those tests, you have nothing concrete to show for your efforts but the satisfaction that the function is working correctly for now. 

 

After writing these unit tests, which probably did not take any more time that modifying your front end to pass the parameters and running a few tests would have, you have left over the complete tests, ready and waiting to check over and over that the function is still working correctly.  You now have so much more for probably less work!

 

Now for the fun stuff.

First Test of a Web Page

WatiN’s purpose is to automate the testing of web pages.  So far we have just used the core technologies we will be using in conjunction with WatiN but not WatiN itself.

 

In order to test a page, we have to create one.  The default.aspx page is just a shell at this point with nothing on it.  Open default.aspx in design mode and drop two buttons and a textbox on the form.  We will name the buttons OKButton and CancelButton giving them the obvious text for those purposes and name the textbox MessageTextbox.

 

Now double click on the OK button to open the code behind for the click event and set the textbox to the value “OK” as shown below:

    Protected Sub OKButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles OKButton.Click
        MessageTextBox.Text = "OK"
    End Sub

Do the same thing with the Cancel button, setting the textbox to “Cancel”.  Then just to make things nice, set the textbox to empty in the page load as shown in the following code:

    Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
        If Not IsPostBack Then
            MessageTextBox.Text = ""
        End If
    End Sub
 
    Protected Sub CancelButton_Click(ByVal sender As System.Object,_
            ByVal e As System.EventArgs) Handles CancelButton.Click
        MessageTextBox.Text = "Cancel"
    End Sub

Now if you right click on the web project and set it as the startup program and press F5 to run the application, the web page comes up and clicking on the buttons fills the textbox as expected.  Pretty simple, but something to start with.

 

Now for the magic.  Click on the File menu option and select Add – New Project, giving the project the name of WebPageTests as shown next:

Rename the Class1.vb to DefaultTests.vb to show that it will contain tests for the Default page.  Right click on the new WebPageTests project and Add References to both NUnit and WatiN.  Add the imports at the top of the DefaultTests.vb for Nunit.Framework and WatiN.Core and add the <TestFixture()> attribute to DefaultTests.vb, so it now will appear as:

Imports NUnit.Framework
Imports WatiN.Core
 
<TestFixture()> _
Public Class DefaultTests
 
End Class

Now it is time to add the new test.  Copy the following into the DefaultTests class:  Note: the 3587 after the localhost is the port that the ASP.NET Development Server chose.  It may be a different port on your machine.  Run the web page again, examine the URL in the address bar and make a note of the number used.

    <Test()> _
    Public Sub TestButtons()
      Dim ie As IE = New IE("http://localhost:3587/default.aspx")
 
      ie.Button(Find.ById("OKButton")).Click()
                 Assert.IsTrue(ie.TextField(Find.ById("MessageTextBox")).Text.
Equals("OK"), "TestButtons did not find OK in the textbox after OK button clicked.")
 
    End Sub

WatiN is case sensitive, so you must use the exact capitalization that you used when naming the controls in the web page.  If you have TestDriven.NET installed, right click on the new test and select Run Test.  You should see the web page open, the OK button is clicked and OK appears in the textbox.  If you are not used to automating the Internet Explorer with a tool like WatiN, then that should be very exciting.  Yes, it means that you can now do all sorts of cool automation.

You should also have gotten confirmation in the lower left corner of the IDE that one test passed.

 

If you do not have TestDriven.NET installed, then you will have to prepare the NUnit Test Runner to control the tests.  The first step is to add an app.config file to your WebPageTests project, because NUnit requires some settings to work correctly.  Right click on the project and Add – New Item, selecting application configuration file.  Add the following to the beginning of the newly created file:

<configSections>
      <!--Tell configuration there will be information about NUnit-->
      <sectionGroup name="NUnit">
            <section name="TestRunner"
        type="System.Configuration.NameValueSectionHandler"/>
      </sectionGroup>
</configSections>
<NUnit>
      <TestRunner>
            <!-- Valid values are STA,MTA. WatiN requires STA. -->
            <add key="ApartmentState" value="STA" />
      </TestRunner>
</NUnit>

This is required because NUnit normally runs in multi-threaded mode but WatiN requires single-threaded mode.

 

Also, just as before, you will have to make the WebPageTests the startup project and modify its debug properties to start an external program, selecting the nunit.exe test runner program.  Once you press F5 to run the program the test runner will appear, but it probably will be pointing to the last set of tests you ran for the MathFunctions.  Click the File – Open Project option and navigate to the bin folder under the WebPageTests project and select the WebPageTests.DLL.  Your test should now appear in the test tree.

Clicking the Run button will open the browser, click the button and place OK in the textbox.  You get the green bar of success as your reward:

You may have a little difficulty viewing the results and closing things down however, which points out one of the shortfalls of our test.  We deliberately left the browser open so you could see that the textbox contained OK, but this is not good practice.  Each test needs to clean up after itself.  You probably had to close or hide the browser manually so you could see the test runner and look for the green bar.  You also had to close both the test runner and the browser to get the IDE to stop debugging.

 

Let’s add the following line at the end of our test:

         ie.Close() 

This will close the browser.  There is no need to keep it open now that the test is over and now that you have verified the magic with your own eyes.

 

Run the test again and you can see, if you watch carefully, the browser open, the button get clicked, the OK appear in the textbox, then the browser closes and the results are shown.

 

This concludes the introductory portion of our magic show.  By now you should be aware that WatiN gives you the tools to automate just about anything that a user can do with an Internet Explorer web browser.  As of the time this was written, the creators of WatiN have just released the CTP of the next version which will also allow testing with a FireFox browser.  The next section will provide more complicated examples and introduce some of the standards employed to make the process easier over the long term.

 

Contents: Table of Contents Previous Page: How to use WatiN to Test Web Pages - Part I Next Page: Testing Web Pages - Things To Consider

Posted Thursday, April 03, 2008 4:44 PM by ddodgen | with no comments