Tag Archives: testing

Testability with System.Web.Abstractions and no mock framework

As a follow-up to my previous post ASP.NET 3.5: improving testability with System.Web.Abstractions, I would like to show how the same testability can be achieved without using any mock framework like Rhino.Mocks. The C# 3.0 featuires ‘object initializers’ and ‘automatic properties’ makes our code sufficiently non-verbose to make it easy and readable.

So, given the same examples as in my previous post, here is what the test code will look like:

Example #1: Testing a page codebehind file

[TestMethod]
public void ShouldSetNoCacheabilityOnDefaultPage()
{
    _Default page = new _Default();
    HttpCachePolicyMock httpCachePolicyMock = new HttpCachePolicyMock();
    page.SetCacheablityOfResponse(new HttpResponseStub
    {
        TheCache = httpCachePolicyMock
    });
    httpCachePolicyMock.ShouldHaveSetCacheabilityTo(HttpCacheability.NoCache);
}
class HttpResponseStub : HttpResponseBase
{
    public override HttpCachePolicyBase Cache { get { return TheCache; } }
    public HttpCachePolicyBase TheCache { get; set; }
}
class HttpCachePolicyMock : HttpCachePolicyBase
{
    private HttpCacheability _cacheability;
    public override void SetCacheability(HttpCacheability cacheability)
    {
        _cacheability = cacheability;
    }
    public void ShouldHaveSetCacheabilityTo(HttpCacheability expectedCacheability)
    {
        Assert.AreEqual(expectedCacheability, _cacheability);
    }
}

I have created two helper classes, one with the suffix -Stub and one with the suffix -Mock. The convention here is that a stub is a type of class used to provide a context to the class under test. Mocks also do that, but additionally a mock can make expectation about what should happen to it during the test.

Example #2: Testing an HTTP handler

[TestMethod]
public void ShouldRedirectAuthenticatedUser()
{
    HttpServerUtilityMock httpServerUtilityMock = new HttpServerUtilityMock();
    HttpContextStub httpContextStub = new HttpContextStub
    {
        TheRequest = new HttpRequestStub { IsItAuthenticated = true },
        TheServer = httpServerUtilityMock
    };
    new RedirectAuthenticatedUsersHandler().TransferUserIfAuthenticated(httpContextStub);
    httpServerUtilityMock.ShouldHaveTransferredTo("/farfaraway");
}
class HttpContextStub : HttpContextBase
{
    public override HttpRequestBase Request { get { return TheRequest; } }
    public override HttpServerUtilityBase Server { get { return TheServer; } }
    public HttpRequestBase TheRequest { get; set; }
    public HttpServerUtilityBase TheServer { get; set; }
}
class HttpRequestStub : HttpRequestBase
{
    public override bool IsAuthenticated { get { return IsItAuthenticated; } }
    public bool IsItAuthenticated { get; set; }
}
class HttpServerUtilityMock : HttpServerUtilityBase
{
    private string _path;
    public override void TransferRequest(string path)
    {
        _path = path;
    }
    public void ShouldHaveTransferredTo(string expectedPath)
    {
        Assert.AreEqual(expectedPath, _path);
    }
}

ASP.NET 3.5: improving testability with System.Web.Abstractions

The testability of ASP.NET code has long been a challenge; creating unit tests for your ASP.NET code has been difficult. One of the main points of the new ASP.NET MVC framework has been to make code written for it easily testable. However, not many people know that in ASP.NET 3.5, Microsoft has added a few features to make any ASP.NET applications, not only ASP.NET MVC applications, more easy to test. The System.Web.Abstractions assembly adds a few classes to the System.Web namespace that will help the situation. For instance, looking at the documentation for System.Web.HttpRequestBase, it states that

The HttpRequestBase class is an abstract class that contains the same members as the HttpRequest class. The HttpRequestBase class enables you to create derived classes that are like the HttpRequest class, but that you can customize and that work outside the ASP.NET pipeline. When you perform unit testing, you typically use a derived class to implement members that have customized behavior that fulfills the scenario that you are testing.

Very well. Looking at the documentation for HttpRequest, we see that HttpRequest is not a decendent of HttpRequestBase as one might expect from the name. The reason for this is probably that that would break backwards compatability with older versions of ASP.NET. So, how can we exploit the HttpRequestBase then? The answer is the HttpRequestWrapper class which is a decendant of HttpRequestBase and has a constructor that takes an HttpRequest object as a parameter. Then, we can take the HttpRequest object passed to our code from the framework, wrap it inside an HttpRequestWrapper object and pass it on to our code as a HttpRequestBase object. As I will show you in the examples below, this will enable us to create unit tests of our code by creating fake implementations of ASP.NET framework clases (using Rhino.Mocks).

Example #1: Testing a page codebehind file

Take, for instance, this simple page codebehind code that we would like to test:

using System;
using System.Web;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}

The first step to take here, is to extract a method which take the request object as a parameter instead of fetching it from a method in a superclass. In general, this is a variation of the dependency injection pattern which in many situations will help us make our code testable (also, see my earlier related post). Like so:

using System.Web;
using System;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        SetCacheablityOfResponse(Response);
    }

    public void SetCacheablityOfResponse(HttpResponse response)
    {
        response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}

So, then having extracted our code in a separate method, the next step is to change the parameter type of this method from HttpRequest to HttpRequestBase. Furthermore, when calling this method, we need to wrap the HttpRequest object by creating an instance of HttpRequestWrapper. The code, then, looks like this:

<

pre class=”c-sharp” name=”code””>using System.Web;
using System;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
SetCacheablityOfResponse(new HttpResponseWrapper(Response));
}

public void SetCacheablityOfResponse(HttpResponseBase response)
{
    response.Cache.SetCacheability(HttpCacheability.NoCache);
}

}
Having now prepared our code for testing, we can create a unit test where we test the SetCacheabilityOfResponse method:

[TestMethod]
public void ShouldSetNoCacheabilityOnDefaultPage()
{
    _Default page = new _Default();
    MockRepository mocks = new MockRepository();
    HttpResponseBase responseStub = mocks.Stub<HttpResponseBase>();
    HttpCachePolicyBase cachePolicyMock = mocks.CreateMock<HttpCachePolicyBase>();
    With.Mocks(mocks).Expecting(delegate
    {
        SetupResult.For(responseStub.Cache).Return(cachePolicyMock);
        cachePolicyMock.SetCacheability(HttpCacheability.NoCache);
        LastCall.On(cachePolicyMock).Repeat.AtLeastOnce();
    }).Verify(delegate
    {
        page.SetCacheablityOfResponse(responseStub);
    });
}

If you are not familiar with Rhino.Mocks or any other mocking framework, there appears to be a lot going on in that test. The basic idea is that we create derivatives of the -Base classes and pass these to the code that we are going to test, mimicking the behavior of the “real” objects that the framework would pass our code at runtime. Also note that in this particular test we test the side effect of our code, namely that the code should call a the SetCacheability method with a specific parameter. This is achieved using a mock object.

Example #2: Testing an HTTP Handler

Given the following HTTP handler code:

using System;
using System.Web;

public class RedirectAuthenticatedUsersHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        if (context.Request.IsAuthenticated)
        {
            context.Server.TransferRequest("/farfaraway");
        }
    }
}

Again, we extract the code we want to test into a separate method, passing it a -Base object and wrap the object passed to us from the framework in a -Wrapper object:

using System;
using System.Web;

public class RedirectAuthenticatedUsersHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        TransferUserIfAuthenticated(new HttpContextWrapper(context));
    }

    public void TransferUserIfAuthenticated(HttpContextBase context)
    {
        if (context.Request.IsAuthenticated)
        {
            context.Server.TransferRequest("/farfaraway");
        }
    }
}

This allows us to create unit tests for the TransferUserIfAuthenticated method, for instance:

[TestMethod]
public void ShouldRedirectAuthenticatedUser()
{
    RedirectAuthenticatedUsersHandler handler = new RedirectAuthenticatedUsersHandler();
    MockRepository mocks = new MockRepository();
    HttpContextBase httpContextStub = mocks.Stub<HttpContextBase>();
    HttpRequestBase httpRequestBaseStub = mocks.Stub<HttpRequestBase>();
    HttpServerUtilityBase httpServerUtilityMock = mocks.CreateMock<HttpServerUtilityBase>();
    With.Mocks(mocks).Expecting(delegate
    {
        SetupResult.For(httpContextStub.Request).Return(httpRequestBaseStub);
        SetupResult.For(httpContextStub.Server).Return(httpServerUtilityMock);
        SetupResult.For(httpRequestBaseStub.IsAuthenticated).Return(true);
        httpServerUtilityMock.TransferRequest("/farfaraway");
        LastCall.On(httpServerUtilityMock).Repeat.AtLeastOnce();
    }).Verify(delegate
    {
        handler.TransferUserIfAuthenticated(httpContextStub);
    });
}

Summary

I have shown two very simple examples on how some of the classes in the System.Web.Abstractions assembly can help us test our ASP.NET code. I have used HttpResponseBase, HttpServerUtilityBase, HttpContextBase, HttpRequestBase, and HttpCachePolicyBase. Note that there are a number of classes available, so if you are faced with not being able to test your ASP.NET code because of dependencies to classes in the framework, take a look in the System.Web namespace and see if there are -Base classes that can help you out.

Testability is a large topic, and there is much to be said about it. I have shown a couple of very simple examples on how to improve testability. Testability has a lot to do with code design as well; in a real world I would write the test before writing the code and I would move my code out of codebehinds. Those topics are discussed a lot elsewere, hopefully this post will bring you a small step further in writing testable code.

Avoiding brittle Selenium tests

When automating tests, avoiding creating brittle tests are very important. In my experience, this something that can easily happen when using Selenium if you don’t take special care.

For instance, when locating elements on the page, you typically would like to refer to them using IDs. However, can you be sure that the IDs stay the same at all times? No. This problem becomes appearent when creating ASP.NET applications in Visual Studio. Visual Studio automatically generates what is called the Client ID for a control, based on its location in the control hierarchy. This id is rendered as both the id attribute and name attribute of an HTML element. For example, an ID might look like this:

ctl00_MainArea_MainPageControl_MainPageSection2_ClearRepeater_ctl01_HyperLink1

As a consequence, if you move a control to another place in the control hierarchy, the ID will be different. If you have referred to this ID in your Selenium test, it will break! Not good.

In order to fix this situation, I created a locator that does a partial match on the element id attribute.

HttpOnly broke my Selenium tests

On my current project (running .NET 2.0), I have been using Selenium to test various security related aspects of the application. (Could Selenium be used for security testing?, Selenium with support for cookie-management) I have been happily using Firefox for running my tests, but today I tried to run the tests in Internet Explorer 7. Without success.

The thing is that I have been using Selenium to verify login related functionality, so for instance a test could be something like these:

  • Test that a user can successfully log in by providing correct username and password
  • Test that a user’s cookie session is ended when logging out

In order to successfully run these tests, I had to manipulate cookies in my tests:

  • To prevent tests from interfering with each other, I had to remove any session cookies in between tests
  • Test for existence of session cookies

When running my tests in Firefox, this worked well. I could perform operations on the .ASPXAUTH cookie, which is the cookie that .NET uses to identify an authenticated session. When running IE 7 it breaks. The reason for this, is that Microsoft has created a new attribute on cookies called ‘HttpOnly’ that .NET uses, and the Set-cookie HTTP header looks for instance like this:

Set-Cookie: .ASPXAUTH=bisxfb45rbiclmjmqu4aa345893763387328743238736; path=/; HttpOnly

IE 6 SP1 (and apparently also IE 7) makes such cookies inaccessible by JavaScript, as explained here: Mitigating Cross-site Scripting With HTTP-only Cookies.
Hence, my Selenium tests were unable to test for and to manipulate these cookies.

I have a mixed feeling about this. Everything that helps security makes me happy. However, everything that makes my application hard to test is baaaaaad. And I mean really bad. I think that the technical solution that Microsoft has come up with here is good – it really makes sense. Why should JavaScript be able to manipulate session cookies like these anyway? I cannot think of any good use case for that. However, this is proprietary stuff that Microsoft has come up with and is not an agreed standard. Makes my life as a developer harder. Not good.

Selenium with support for cookie-management

I blogged earlier about using Selenium for security testing. One of the shortcomings that I pointed out, was that session handling (i.e. cookie handling) was needed. I went ahead and created extensions for this. As of version 0.8.0, Selenium now supports this out of the box. This means that Selenium now is able to test scenarios such as logging in and logging out from web applications, in additional to other cookie-based functionality. Great!

Using Selenium to test input validation

When testing for security, it is important to test that the application under test (AUT) handles unexpected input properly, i.e. does not enter an unsecure state. A typical example of an unsecure response to an unexpected input is to display an exception that reveals information about the system configuration that can help a malicious user breaking in to a system.

As I blogged about earlier, I am trying to use Selenium to do security testing. In order to be able to test how the AUT handles being passed a value that is not present in an HTML dropdown list, I created a Selenium extension that adds a new option to a dropdown list and selects it. This way, the test may add a new value before submitting the form to the application.

Here is the code for the Selenium action.

Could Selenium be used for security testing?

My current project uses an agile project methodology. As such, we use Selenium to create automated acceptance tests for the project. Focusing on the security aspects of the application we are developing, I had an idea about using Selenium for security testing. Basically, there are a few points that led me to this idea:

  • Using Selenium we would perhaps not need to introduce yet another tool into the process, lowering the project’s effort to handle security.
  • Using Selenium, security testing could get attention equal to the acceptance tests.
  • Selenium tests could perhaps be created to simulate Black Hat activity.

Being a Selenium newbie, I started looking at Selenium to see of it could be used for this purpose. I quickly realised that Selenium out of the box does not have the functionality that is needed. It is, however, easily extensible.

I have found some areas where Selenium has shortcomings when it comes to security testing:

  1. Session handling: Proper session handling is important when it comes to security, for instance vulnerabilities like session fixture and rights elevation. To enable testing of session handling, Selenium needs functions for inspecting and deleting cookies. Furthermore, if one where to run test suites with tests which involves sessions, these would have to be deleted in between tests to avoid the tests interfering with each other.
  2. HTTP protocol: Testing which involves inspecting and setting HTTP headers would be an integral part of a security test suite.
  3. Input validation: Testing that the AUT does proper input validation and/or can handle input out of range would be important. For example, one test that comes to mind is whether the AUT can handle being sent a value that is not a part of an HTML drop down list.

Even though Selenium has shortcomings, I am fairly optimistic that these can be overcome, and I would like to investigate this further. For instance, I have created basic cookie handling routines for Selenium which seems to do the job. (Item 1 above) I will post them on my homepage later (www.kongsli.net). For item 3 above, I have created a method that will dynamically add options to dropdown lists on a page before the page is submitted, making it possible to send parameters out of range to the server. Furthermore, I will look into AJAX related techniques to handle item 2 above, possibly using the Dojo framework.

Quantum mechanics in software testing

The other day, a colleague of mine and I discussed our test environment. We concluded that neither
of us had used it for a while and were hence uncertain of its state. Then, I came to think of Schrödinger’s cat, the thought experiment introduced by physicist Erwin Schrödinger in which a cat is placed in a sealed box together with a container of poison and a radioactive substance. A radioactive decay would make the poison escape from the container and kill the cat. However, exactly when the decay will occur is not predicable by quantum physics, only a probability of the occurence may be given. So, given that the state of the cat, dead or alive, cannot be observed without opening the box, its state is uncertain.

According to quantum mechanics, an unobserved nucleus is said to be in a superpositioned state,
both decayed and undecayed. Only when it is observed it seizes to be superpositioned.

Now, it is quite funny to make an analogy to this regarding software development. Unless you test
(observe) your system, it is in a superpositioned state: it both works and doesn’t work. The only
way to make it work, is to test it.

Using this analogy we will arrive at the agile software development mantra of test early, test often.
For instance, using continuous integration with unit testing and automatic acceptance testing, your
system will be in a well-defined state at (almost) all times.