Welcome to MSDN Blogs Sign in | Join | Help

Which Microsoft virtualization solution to use for software testing

I have to admit the title is a bit misleading this time since - if you ask me - there is only one answer: Hyper-V! It is the first Microsoft virtualization product to support 64-bit guest operating systems, SMP for some guests (see Supported Guest Operating Systems for a full list) and with Enlightened I/O it is incredibly fast. The only problem - and also the real reason for writing this post - is that you can only get Hyper-V as part of Windows Server 2008 or as the new Hyper-V Server 2008. So what if that is not an option?

The simplest alternative is good old Virtual PC. It certainly gets the job done but I really appreciate the option of being able to use Remote Desktop with all my machines no matter if they are physical or virtual. While nothing is preventing me from connecting to a VM running in Virtual PC through Remote Desktop, Virtual PC itself is "just" a regular application. Or rather, it is not a service, meaning that you cannot logout as long as you still need that VM running.

Fortunately, there is still Virtual Server which - like any well-behaved server - runs as a service. That addresses what I dislike about Virtual PC but now I got a different problem. The standard management solution for Virtual Server is web-based which of course means that you need at least one IIS instance in order to configure Virtual Server and manage your VMs. This is - for the purpose of testing applications in VMs - an unnecessary resource penalty. Even worse, if your host OS is Windows Vista setting IIS up so the Virtual Server management website will actually work is quite painful. Good thing no one - not even the installer - is forcing us to install the Virtual Server Web Application as the feature is officially called. So let's not.

Microsoft Virtual Server 2005 R2 SP1 Setup

So if you install with these options, how do you actually use your Virtual Server? This is where a little unsupported freeware tool comes in. Since it's unsupported it's not suitable for production (then again, so is running Virtual Server on Vista anyway) but it's perfect for testing. It's called VMRCplus (the full name is Virtual Machine Remote Control Client Plus... but let's be honest, that's simply too long), available for download from the Microsoft Download Center and while it does not cover the full functionality of the web application it most certainly includes everything you typically need (just remember to use Run as administrator on Vista).

VMRCplus 1.8


This posting is provided "AS IS" with no warranties, and confers no rights.

Posted by ddietric | 1 Comments
Filed under: ,

A poor man's approach to testing with databases

Say you are working on software that accesses a database server and you need to test it. To some extent you'll probably try to not actually hit the database with your tests by using a mock. However, this is not always possible, especially when we're dealing with integration/acceptance tests which need to verify the system as a whole. In case your software only reads from a database there isn't really an issue. You setup a database server, create the required test database, the actual tests and start doing your test passes. Unfortunately, it's not that simple anymore as soon as your software changes the data in the database. While there are approaches that perform actions regardless of the state of the database and include verification steps that are able to analyze the resulting state changes this comes at a cost and might be overkill for your project.

So what to do if you want to have tests that are comparable to unit tests in terms of the level of complexity (just another way of saying, you want to keep your test code simple)? Referring to unit tests already implies that each test requires the software we are testing to be in a certain state. This requirement of course includes the state of the database. As long as we have a backup of the test database in its initial state we can ensure this by simply restoring the database form the backup during the initialization phase of every test. At this point I'd like to point out that this does not make sense for large databases (based on the time required for a full database restore) since the overall execution time will be unacceptable.

Restoring a database can be done in T-SQL allowing us to create a stored procedure for this purpose so the test code does not contain any file paths which may be specific to the test server used. The following example creates such a stored procedure in the master database (though it should be obvious: this is a bad idea in a production environment):

USE [master]

GO

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

CREATE PROCEDURE [dbo].[sp_Restore_Northwind]

AS

BEGIN

    RESTORE DATABASE Northwind

            FROM DISK = 'C:\Database Backups\Northwind.bak'

            WITH FILE = 1,

                 MOVE 'Northwind'     TO 'C:\Databases\Northwind.mdf',

                 MOVE 'Northwind_log' TO 'C:\Databases\Northwind_log.ldf',

                 RECOVERY;

END

Then we can add a test initialization routine to our test suite that executes the stored procedure so the database is always in the same state before each test no matter whether or not the previous test has altered its content. The following example uses the .NET Framework Data Provider for SQL Server.

[TestInitialize]

public void ResetDatabase()

{

    using (SqlConnection connection = new SqlConnection(Settings.Default.MasterConnectionString))

    {

        connection.Open();

 

        using (SqlCommand command = new SqlCommand("EXEC sp_Restore_Northwind", connection))

            command.ExecuteNonQuery();

 

        connection.Close();

    }

}

And we're done! Except for a small problem. The .NET Framework Data Provider for SQL Server uses a connection pool to improve performance. This unfortunately gets in our way. The first test - including its initialization - will run just fine. The second one however will fail since, because the data provider uses a connection pool, there is still an active connection to the test database by the time we are trying to restore it again. The end result is that the second initialization will timeout. Since the problem is caused by connection pooling it can be solved by disabling it which can be done without any code changes by adding Pooling=False to the connection string (thanks to Mathew Charles for pointing this out):

Data Source=DbServerName;Initial Catalog=Northwind;Integrated Security=True;Pooling=False

 


This posting is provided "AS IS" with no warranties, and confers no rights.

Posted by ddietric | 0 Comments
Filed under:

Pimp your VSTT exception tests

Writing unit tests in VSTT is great since it comes with a nice unit testing framework and the test tools are neatly integrated into Visual Studio. There is one exception though: Exception testing (yes, that pun was intended). Consider the following example:

public class Foo

{

    private object[] _array;

 

    public Foo(object[] array)

    {

        if (array == null)

            throw new ArgumentNullException();

        if (array.Length == 0)

            throw new ArgumentException();

 

        _array = array;

    }

 

    public object GetItem(int index)

    {

        if (index < 0 || index >= _array.Length)

            throw new ArgumentOutOfRangeException();

 

        return _array[index];

    }

}

 

This contrived example contains three throw statements requiring four distinct checks in order to hit all code paths which will cause an exception to be thrown (the if statement in GetItem(int) contains two blocks due to short-circuit evaluation). Since the way to test for exceptions in VSTT is the ExpectedException attribute we need one test method for each code path:

[TestMethod]

[ExpectedException(typeof(ArgumentNullException))]

public void ctor_array_null()

{

    Foo foo = new Foo(null);

}

 

[TestMethod]

[ExpectedException(typeof(ArgumentException))]

public void ctor_array_empty()

{

    Foo foo = new Foo(new object[0]);

}

 

[TestMethod]

[ExpectedException(typeof(ArgumentOutOfRangeException))]

public void GetItem_index_minus_one()

{

    Foo foo = new Foo(new object[1]);

    foo.GetItem(-1);

}

 

[TestMethod]

[ExpectedException(typeof(ArgumentOutOfRangeException))]

public void GetItem_index_array_length_plus_one()

{

    Foo foo = new Foo(new object[1]);

    foo.GetItem(1);

}

 

While there is nothing wrong with this in general it does bloat both the test code base as well as the test list a little bit. Also, if I need to go through a couple of complex initialization steps before actually triggering the exception I'll have to execute those for every single test method. Another more serious potential issue is that with this implementation I can only verify that an exception caused by the test method is of a certain type. But I can never know for sure that the statement I expected to throw actually did throw the exception without stepping through the code or paying close attention to my code coverage while writing the tests. The worst case scenario here is a bug in my test method that causes the expected exception to be thrown before the statement that was supposed to throw even gets executed. This could go unnoticed since the test would still pass.

Now, if you've worked with VSTT for a while you may have noticed that there are a couple of classes for assertions. The Assert class is probably the one that is most well-known. But there are also the classes CollectionAssert and StringAssert which complement the general purpose Assert class. What's missing is an ExceptionAssert class! So let's create one.

using Microsoft.VisualStudio.TestTools.UnitTesting;

using System;

 

public static class ExceptionAssert

{

    public static void Throws(Type exceptionType, Action action)

    {

        if (exceptionType == null || action == null)

            throw new ArgumentNullException();

 

        if (exceptionType != typeof(Exception) && !exceptionType.IsSubclassOf(typeof(Exception)))

            throw new ArgumentException();

 

        try

        {

            action();

        }

        catch (Exception e)

        {

            if (e.GetType() != exceptionType)

                throw new AssertFailedException(String.Format(

                    "ExceptionAssert.Throws failed. Expected exception type: {0}. Actual exception type: {1}. Exception message: {2}",

                    exceptionType.FullName,

                    e.GetType().FullName,

                    e.Message));

 

            return;

        }

 

        throw new AssertFailedException(String.Format(

            "ExceptionAssert.Throws failed. No exception was thrown (expected exception type: {0}).",

            exceptionType.FullName));

    }

}

 

Parameter validation aside, Throws(Type, Action) takes the type of the expected exception and a delegate of the type Action pointing to the code that is supposed to throw. This delegate is called in a try block since we expect it to throw and the corresponding catch block catches all managed exceptions (this a rare instance in which it is actually okay to do so). If an exception is caught but it is not of the expected type an AssertFailedException is thrown to signal the test failure to the test runtime which is also what for example the Assert class that ships with VSTT does if the condition is not met. Finally, if calling the delegate did not cause an exception we also throw an AssertFailedException this time with a different message. Using this new assertion method simplifies our test code for the constructor of the Foo class to this:

[TestMethod]

public void Constructor()

{

    ExceptionAssert.Throws(typeof(ArgumentNullException),

                           delegate { new Foo(null); });

 

    ExceptionAssert.Throws(typeof(ArgumentException),

                           delegate { new Foo(new object[0]); });

}

 

You may argue that this alone is not that much of a simplification but it's a start. The Throws() method above only takes delegates that don't have parameters and return void. What we need to do is add overloads for different kinds of delegates. I just want to show one more example for delegates taking one parameter and returning void. While the remaining test code I haven't replaced yet could also be written using anonymous methods this overload will allow me to demonstrate the usage of lambda expressions in the test method (for all those programmers out there who love them - I think I'm slowly turning into one myself).

public static void Throws<T>(Type exceptionType, T target, Action<T> action)

{

    if (exceptionType == null || target == null || action == null)

        throw new ArgumentNullException();

    if (exceptionType != typeof(Exception) && !exceptionType.IsSubclassOf(typeof(Exception)))

        throw new ArgumentException();

 

    try

    {

        action(target);

    }

    catch (Exception e)

    {

        if (e.GetType() != exceptionType)

            throw new AssertFailedException(String.Format(

                "ExceptionAssert.Throws failed. Expected exception type: {0}. Actual exception type: {1}. Exception message: {2}",

                exceptionType.FullName,

                e.GetType().FullName,

                e.Message));

 

        return;

    }

 

    throw new AssertFailedException(String.Format(

        "ExceptionAssert.Throws failed. No exception was thrown (expected exception type: {0}).",

        exceptionType.FullName));

}

 

As you can see most of the new overload is exactly the same as before (differences in bold) and it allows us to replace the remaining tests with the following single test method:

[TestMethod]

public void GetItem()

{

    object content = new object();

    Foo foo = new Foo(new object[] { content });

 

    ExceptionAssert.Throws(typeof(ArgumentOutOfRangeException), foo, f => f.GetItem(-2));

    ExceptionAssert.Throws(typeof(ArgumentOutOfRangeException), foo, f => f.GetItem(-1));

    Assert.AreEqual(content, foo.GetItem(0));

    ExceptionAssert.Throws(typeof(ArgumentOutOfRangeException), foo, f => f.GetItem(1));

    ExceptionAssert.Throws(typeof(ArgumentOutOfRangeException), foo, f => f.GetItem(2));

}

 

This new test method does not only add a regular assert in-between exception checks but it also calls GetItem(int) with two more invalid values without the need for adding additional test methods. As cool as this may (or may not) be, I'd like to close this post with a little warning because there is something I failed to mention before which I consider to be an advantage of the attribute-based approach:

When in doubt you should assume that an exception is thrown because of literally exceptional circumstances which may leave your objects under test in an undefined state. Using an attribute and catching the expected exception in the test runtime makes it more difficult for you to shoot yourself in the foot by reusing objects in your test method which may be in a bad state (or looking at it from the other side, my ExceptionAssert class makes it easier since allowing you to keep going after an exception is exactly the point). That said, I only recommend this approach of reusing instances for multiple exception checks when you know for sure that the objects under test are not in an undefined state after throwing an exception because the exception is part of parameter validation before any state changes occur or the object can reliably recover from the error condition for example by rolling back changes.


This posting is provided "AS IS" with no warranties, and confers no rights.

Unit testing non-public types using reflection

Let's say you want to unit test the following class:

using System;

 

internal class Foo

{

    internal Foo(object parameter)

    {

        if (parameter == null)

            throw new ArgumentException();

    }

 

    internal int ReturnZero()

    {

        return 1;

    }

}

 

First of all, besides being pointless, it is buggy. The constructor should throw an ArgumentNullException and ReturnZero() should return 0. More importantly for this post though, it is not public. Now, you could sign your test assembly and use the InternalsVisibleTo attribute; however, that won't help you with types and members that are declared as private or members declared as protected. But I love reflection and with reflection I can call into anything I want though the code looks more complicated than it should. That said, I may decide to write the following test code to be executed by MSTest.exe/VSTT.

 

using Microsoft.VisualStudio.TestTools.UnitTesting;

using System;

using System.Reflection;

 

[TestClass]

public class FooTests

{

    private Type            fooType;

    private ConstructorInfo fooConstructor;

    private MethodInfo      returnZeroMethod;

 

    public FooTests()

    {

        fooType = Type.GetType("Foo, Foo", true, false);

 

        fooConstructor = fooType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,

                                                null,

                                                new Type[] { typeof(object) },

                                                null);

 

        returnZeroMethod = fooType.GetMethod("ReturnZero",

                                             BindingFlags.Instance | BindingFlags.NonPublic);