Imports BusinessLayerImports 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.