London Alt.Net beers night - 25th November 2008

The London Alt.Net community convened again this week at a beers night kindly hosted by Tequila.

Topics are suggested on a board as people arrive and mingle and when the night begins in earnest, votes are cast for the most popular topic that will be up for discussion in a park bench style - three people at any one time on four seats at the front can answer questions and discuss the topic of the day with anyone free to occupy the free seat should the want to contribute something substantial.

The format works for the most part and Seb Lambla and Zi Makki are very capable moderators of this good idea, but unfortunately the way the topic is talked about throughout the session dilutes the discussion somewhat. With strongly held opinions battling for prominence the topic quickly descends into a fight to justify or explain the topic that is up for discussion - the mere fact that the majority voted for it doesn't seem to mitigate this.

This is not to say that the current format is not producing worth - I certainly got something out of the night and the topic(s) at hand, but something about it leaves me feeling as though I was short-changed.

My suggestion would be to allocate a set time for describing the topic - 10 minutes devoted at the start of the session solely to defining what it is we are talking about, with three people volunteering to give their few minutes unbiased description of the subject. From then on, all discussions must be productive and not about justifying the term or why it should be used in a project in the first place.

Anyway onto the topic that was discussed, or rather two topics... AOP and Opinionated MVC.

Aspect Orientated Programming was the first topic of the night and we ultimately rounded the discussion off with four forms of AOP discussed:

  • Simple Decorator pattern AOP where the decorator class of the same type performs its aspect before calling into the containing type and these can be nested as much as required - Neil Robbins described this well as the Russian doll AOP (to paraphrase).
  • Attribute based where a framework inspects attributes at runtime - this has to be baked into the framework you are utilising
  • Proxy or interception code provided by libraries - usually introduced via a run-time configuration
  • IL weaving where the assembly is changed after compilation - for example with PostSharp.

All attempt to provide a way to move cross-cutting concerns out from the domain objects themselves, helping adhere to the single responsibility principle and provide cleaner code. As no-one could think of a concrete reason other than logging for its use (!) the session moved onto another topic:

Opinionated MVC was discussed and again, this is where I pitched for one of my first times at one point asking whether we were actually talking about Convention MVC as opposed to "Opinionated" and in doing so played the "describe the topic" game I criticised earlier! D'oh!

The topic was clearly a hot one though and we did get a few different opinions on the subject, the most interesting of which, I found, was one put forward by Alan Dean where he advocated building component parts of a page (again cross-cutting concerns) from client code via javascript to REST-like resources, thus fully utilising native http caching and reducing server load.
For example, the breadcrumbs are the same for every user on a "my profile" page - why produce it on the server with composite views each time if it can be cached for all users?

In my web experience, having the page degrade gracefully to non-javascript users has been paramount and all my hairs raised in automatic repulsion of the idea.
But I DO like it - it is a very interesting one as the caching ability he proposed would be truly useful as a website scales.

All in all a good and thought provoking night.

Posted at at 4:51 PM on Thursday, November 27, 2008 by Posted by Justin Davies | 0 comments Links to this post   | Filed under:

Using the classic ASP unit test framework

This is the fifth part of a series on unit testing classic ASP and in this we will start to use the framework to implement our example user stories we described earlier whilst attempting test-first development. The earlier parts of the series are available at:

Part one: how to unit test classic ASP
Part two: user stories for classic ASP unit testing example
Part three: beginnings of a classic ASP unit test framework
Part four: automating classic ASP unit tests with NUnit

We begin this part by revisiting our user story backlog and identifying the story that we will be working on - we choose one of the easiest:

As a user if I access the system between 13:00 and 14:00, I cannot place an order and the system will provide an appropriate message.

For this we anticipate having an "OrderSettings" VBScript class and properties that will indicate the cut off time and next order time and a function that will tell us whether a user can place an order. Therefore we can write our tests before we write the class itself.
We create a new folder in our Unit Test project called "Orders" and in here we place a new ASP file, "OrderSettings.Test.asp":

<!--#include virtual="Tests/UnitTester.asp"-->
<%
dim tester
Set tester = new UnitTester
tester.Init("Testing Order Settings")

Dim currentOrderSettings
Set currentOrderSettings = new OrderSettings

currentOrderSettings.CutOffTime = "01/01/1999 13:00:00"
currentOrderSettings.NextOrderTime = "01/01/1999 14:00:00"

Dim onePm
onePm = "10/10/2008 13:00:00"

tester.AssertIsFalse currentOrderSettings.CanOrderAt(onePm), "Can Not Order At 13:00"
%>

Here, we are expecting a new OrderSettings class to have a function called CanOrderAt - we pass the date/time in and it returns true or false.
Note that we are using dates here for our time functionality and not strings... we made this choice so that we can use the date types and functions to assist us and this can also be stored reliably in the database.

We now wrap this in a NUnit test fixture by creating a new file called "OrderSettingsFixture.cs" and place this alongside our test file:

namespace ASPTesting.Tests.UnitTests.Orders
{
    [TestFixture]
    public class OrderSettingsFixture : AspFixture
    {
        [Test]
        public void OrderSettingsTest()
        {
            RunAspTest("UnitTests/Orders/OrderSettingsTest.asp");
        }
    }
}

When we run this unit test via a test runner it fails due to the 500 server error produced by the missing OrderSettings class:

Now, we go to our main ASP website and insert a new ASP file "OrderSettings.asp" in a folder called "Orders" - in here we place our initial code for this class:

<%
Class OrderSettings

    Public Property Let CutOffTime(value)
    
    End Property
    
    Public Property Let NextOrderTime(value)
    
    End Property
    
    Public Function CanOrderAt(dateTime)
        CanOrderAt = true
    End Function
End Class
%>

We also have to reference this new location within our unit test ASP file "OrderSettingsTest.asp" with a new include at the top:

<!--#include virtual="Orders/OrderSettings.asp"-->

Now, when we run our unit tests, it still fails, but this time as a result of an assertion and not an exception - we now have somewhere to start with our Red, Green, Refactor TDD process.

First, to get our tests to pass we change the implementation of the CanOrderAt function:

    
    Public Function CanOrderAt(dateTime)
        CanOrderAt = false
    End Function

When we run our unit tests, they pass and we have our first fully functioning unit test on a requirement.

Time for some refactoring and more assertions (from hereon we shall not look to screenshots and take it at face value when a test is described to pass or fail).
We add new assertion code into our unit test ASP file "OrderSettingsTest.asp":

Dim onePm, twoPm
onePm = "10/10/2008 13:00:00"
twoPm = "10/10/2008 14:00:00"

tester.AssertIsFalse currentOrderSettings.CanOrderAt(onePm), "Can Not Order At 13:00"
tester.AssertIsTrue currentOrderSettings.CanOrderAt(twoPm), "Can Order At 14:00"

Our unit tests now fail because we are returning only false from this function, so we change the implementation in our OrderSettings class to account for this:

    Public Function CanOrderAt(dateTime)
        
        dateTime = CDate(dateTime)
        
        Dim twoPm
        twoPm = CDate("10/10/2008 14:00:00")
        
        If dateTime = twoPM Then
            CanOrderAt = true
        Else
            CanOrderAt = false
        End If
    End Function

With this change, our unit tests pass, but we obviously need some refactoring to get this code into a correct state and we logically turn to the properties and want write the code to store those values - we can then use them in our CanOrderAt function. We insert some more assertions, this time for the properties (we might do this one at a time in true TDD, but for brevity we shall do them together here).
The unit test ASP file "OrderSettingsTest.asp" is changed to the following:

<%
dim tester
Set tester = new UnitTester
tester.Init("Testing Order Settings")

Dim currentOrderSettings
Set currentOrderSettings = new OrderSettings

dim cutTime, nextTime
cutTime = "01/01/1999 13:00:00"
nextTime = "01/01/1999 14:00:00"

currentOrderSettings.CutOffTime = cutTime
currentOrderSettings.NextOrderTime = nextTime

tester.AssertAreEqual currentOrderSettings.CutOffTime, CDate(cutTime)
tester.AssertAreEqual currentOrderSettings.NextOrderTime, CDate(nextTime)

Dim onePm, twoPm
onePm = "10/10/2008 13:00:00"
twoPm = "10/10/2008 14:00:00"

tester.AssertIsFalse currentOrderSettings.CanOrderAt(onePm), "Can Not Order At 13:00"
tester.AssertIsTrue currentOrderSettings.CanOrderAt(twoPm), "Can Order At 14:00"
%>

If we run our unit tests again, they blow up with a server error as the properties do not have Get implementations. We add the get code into the file but initially as empty placeholders, then watch our unit tests fail on an assertion exception instead.
We can now proceed with the implementation in our "OrderSettings" class and our unit tests now pass when we run them once again:

Class OrderSettings

    Private m_cutOffTime
    Private m_nextOrderTime

    Public Property Get CutOffTime()
        CutOffTime = m_cutOffTime
    End Property
    Public Property Let CutOffTime(value)
        m_cutOffTime = CDate(value)
    End Property
    
    Public Property Get NextOrderTime()
        NextOrderTime = m_nextOrderTime
    End Property
    Public Property Let NextOrderTime(value)
        m_nextOrderTime = CDate(value)
    End Property

We will take a break here so that this post doesn't become too long - in the next part of this series we will continue to refactor this class and further illustrate test-first development in action using classic ASP.

Posted at at 8:50 PM on Friday, November 21, 2008 by Posted by Justin Davies | 0 comments Links to this post   | Filed under: ,

Automating classic ASP unit tests with NUnit and C#

In this fourth part of a series on classic ASP unit testing we will explore how we can automate our unit tests using the 2.0 .Net framework, C# and NUnit so that we need not call our test ASP pages directly.

Parts one, two and three walked us through the reasons for our framework and introduced the core UnitTester VBScript class that emits HTML for our assertions when we call a test ASP page that uses the class and asserts.
Rather than manually call this test ASP page (and any further ones that we develop) it would help us greatly if we could automate this using a common test framework and runner.

We start this automation with a C# class that will serve as a base NUnit test fixture - we will call it AspFixture and store it in the root of our test project (see illustration).
Note that we have a "lib" folder with the nunit.framework.dll file and this is referenced by the project.

The initial code for the AspFixture class is as follows:

namespace ASPTesting.Tests
{
    public abstract class AspFixture
    {
        private const string BASE_URI = "http://localhost:990/UnitTests/ASPTesting.Tests/";

        public void RunAspTest(string uri)
        {
            var request = WebRequest.Create(BASE_URI + uri);

            ICredentials requestCredentials = CredentialCache.DefaultCredentials;
            request.Credentials = requestCredentials;

            using (var response = request.GetResponse())
            {
                using (var stream = new StreamReader(response.GetResponseStream()))
                {
                    string html = stream.ReadToEnd();

                    Assert.IsFalse(html.Contains("Failed"));
                }
            }
        }
    }
}

This class serves as an abstract base class for any fixtures that we write and encapsulates the automation of our ASP test run. First it creates a WebRequest instance from the uri provided and supplies default credentials. Then a WebResponse instance is obtained via request.GetResponse().

We then obtain a StreamReader instance and read the HTML into a string. Finally we make a simple assertion that this HTML does not contain the word "Failed". Through using statements we ensure Dispose() is called to free all resources.

This forms the beginnings of a base class and is pretty primitive (hard coded constant uri path for instance) -  later in the series we will improve upon this but for now it enables us to automatically check whether any assertions we are calling emit "Failed" in the HTML.

To see this in action we now create a new C# class called "TestFixture.cs" within our UnitTest folder (alongside its Test.asp counterpart):

namespace ASPTesting.Tests.UnitTests
{
    [TestFixture]
    public class TestFixture : AspFixture
    {
        [Test]
        public void Test()
        {
            RunAspTest("UnitTests/Test.asp");
        }
    }
}

This class is decorated with the NUnit TestFixtureAttribute indicating it is a unit test and inhertis from the base abstract class we just set up - it makes just one call to the RunAspTest() method with the location of our "Test.asp" file.

We can now run this TestFixture and it will call out to our ASP page, parse the HTML and assert whether any have failed - in our previous example (part three) we have an assertion that fails, so we expect our first test run to fail.

Using Resharper as our test runner in this example (obviously any NUnit test runner will suffice), we right click on the file in the solution and choose "Run Unit Tests":

We receive an NUnit AssertionException because the HTML does indeed contain the word "Failed" and our test run fails.
We now have automated classic ASP unit tests!

We finish up this part of the series by fixing our assertion problem and illustrating automation in action.
Let us go back to the Test.asp file and amend our assertion:

<!--#include virtual="Tests/UnitTester.asp"-->
<%
Dim tester
Set tester = new UnitTester
tester.Init("Testing our unit tester class")
tester.Given("that we are testing our new framework")
tester.AssertAreEqual 1, 1
tester.AssertAreEqual "this", "this"
tester.AssertAreEqual "yes", "yes"
%>

Now when we run our unit tests we get a green bar indicating our assertions all pass:

In the next part of this series we will start to implement our user stories showing the unit test framework in action and illustrating how we can use test-first development with classic ASP.

Posted at at 3:39 PM on Tuesday, November 11, 2008 by Posted by Justin Davies | 4 comments Links to this post   | Filed under: ,

The beginnings of a classic ASP Unit test framework

This is the third part of a series exploring how to unit test classic ASP code. In part one, we explored the motivations behind this series and in part two we examined a scenario that will give us context when discussing the framework we are building.

In this part we start building a classic ASP framework that will enable us to test new VBScript/ASP code that we are writing and to facilitate this we create two projects - a C# website project that represents our ASP site and a C# class library project for our unit tests. Note that the Unit test project needs to be nested within the ASP site so that ASP test pages we write can access the classes of main site in the same site and context.

The image shown here has the nested project location highlighted and we will therefore be accessing our testing pages with "(wesbite)/UnitTest/ASPTesting.Tests/".

Our first thing to address is how we will encapsulate the code that we are writing, enabling us to test code in isolation without unnecessary overhead. We will achieve this through VBScript classes and objects with one ASP file per class - these files will sit within the main ASP site and through server side includes we can use those classes / objects in both our main site ASP pages and in our test ASP pages. But how will we test these isolated classes?

Let us start with creating a UnitTester class that we can use as the base of our framework and we save this in the root of the ASPTesting.Tests project. We will want this class to emit HTML based on assertions that we make in ASP test pages that we will be calling manually; we therefore want to make this user friendly and able to provide context about the tests we are performing.

We create a file called "UnitTester.asp" to contain the class and introduce an initialisation sub-routine that will emit some test header HTML:

<%
Class UnitTester
   Public Sub Init(testMessage)

      Response.Write("<style type='text/css'> .unitTest {color: #CF118C;}")
      Response.Write(" .testMessage { padding-right:50px }")
      Response.Write(" .passed { color:green; font-weight:bold; }")
      Response.Write(" .failure { color:red; font-weight:bold; }")
      Response.Write(" .unitTest, .test, .given { font-family:Verdana; font-size:14px; }")
      Response.Write(" .given,  { font-weight:bold; }")
      Response.Write("</style>")

      Response.Write("<div class='unitTest'><h1>Unit testing for ASP</h1>")
      Response.Write("<h2>" + testMessage + "</h2></div>")

   End Sub
End Class
%>

We can now set up a test page that uses this class directly - we have a UnitTest folder in our ASPTesting.Tests project and we place our first ASP test file in there (Test.asp). Note that we have also set up a virtual directory called "Tests" that points to the root of the ASPTesting.Tests folder, enabling us to use a virtual include.

<!--#include virtual="Tests/UnitTester.asp"-->
<%
Dim tester
Set tester = new UnitTester
tester.Init("Testing our unit tester class")
%>

Here we are creating a new instance of the UnitTester class and writing some HTML via the Init() sub-routine. If we call this page directly in the browser we can view the result:

Now we can add some new behaviour to our UnitTester class:

Public Sub Given(message)
   Response.Write("<hr><div class='given'> Given " + message + "</div>")
End Sub

Private Sub WriteTest(passed, message)
   Response.Write("<br><div class='test'>Test: ")

   If passed Then
       Response.Write("<span class='passed'>Passed</span>")
   Else
       Response.Write("<span class='failure'>Failed</span>")
   End If

   Response.Write("<span class='testMessage'> - " + message + "</span></div>")   
End Sub

Public Function AssertAreEqual(actual, expected)
   Dim areEqual, sActual, sExpected
   areEqual = (actual=expected)

   dim sActual, sExpected
   If IsNull(actual) Then
       sActual = "NULL"
   Else
       sActual = CStr(actual)
   End If

   If IsNull(expected) Then
       sExpected = "NULL"
   Else
       sExpected = CStr(expected)
   End If

   WriteTest areEqual, ("Actual value of <b>" + sActual + "</b> is expected to be <b>"
                          + sExpected + "</b>")
   AssertAreEqual = areEqual
End Function

We have added a Given() sub-routine that will enable us to provide context to a series of assertions we are making and we have a new private sub-routine called WriteTest() that facilitates the writing of the test result - it will give us a "Passed" or "Failed" message each time it is called.

Finally we have our first assertion function that tests the equality of two values and calls the private Write Test routine to emit the HTML result.

Wrapping this all up we can now test this functionality with some more code in our Test.asp file:

<!--#include virtual="Tests/UnitTester.asp"-->
<%
Dim tester
Set tester = new UnitTester
tester.Init("Testing our unit tester class")
tester.Given("that we are testing our new framework")
tester.AssertAreEqual 1, 1
tester.AssertAreEqual "this", "this"
tester.AssertAreEqual "yes", "no"
%>

We make a number of assertions here and expect them to have the correct HTML output when we access the Test.asp file manually in a browser:

In the next part of this series we will examine how to automate this test using NUnit so that we need not manually call our ASP pages directly every time we write a test. We will then proceed with our example requirement and show the unit test framework in use whilst adding new assertion functions as we need them.

Posted at at 9:20 PM on Friday, November 7, 2008 by Posted by Justin Davies | 2 comments Links to this post   | Filed under: ,