Using CassiniDev with unit testing frameworks and continuous integration

Hosting a web site or application for testing purposes using CassiniDev is very simple and performs well in continuous integration scenarios.
  • In your test project, reference the desired library, either CassiniDev-lib.dll for an in-process server or CassiniDev-console.exe for an out-of-process server, and extend the provided server fixtures
    • CassiniDevServer wraps CassiniDev-lib which provides an in-process server suitable for debugging tests and is the preferred method of usage unless an out-of-process server is required.
    • CassiniDevServerOP controls a shelled instance of CassiniDev-console that is run out-of-process.
  • Start the server in your fixture setup method. You may start the server in the per test setup method if you require extreme isolation.
  • Stop the server in your fixture teardown method or test teardown depending on how it was started.
  • Utilize the helper method NormalizeUrl to build fully qualified Urls to resources in your application. This allows the use of dynamically assigned ports to eliminate the possibility of port conflicts.
  • If you would like to debug your web site/application during unit tests simply add a reference to the site under test to the test project. Debugging is only possible with the in-process server CassiniDevServer

A simple example using NUnit (from project CassiniDev.NUnitFixtures.Tests)
    /// <summary>
    /// Note: this fixture leverages the in-process CassiniDev server. If you have restrictions or experience
    /// issues with the in-process server, simply reference CassiniDev-console and use CassiniDevServerOP. 
    /// API and usage is same.
    /// </summary>
    [TestFixture]
    public class CassiniDevNUnitFixture : CassiniDevServer
    {
        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            // assuming your test project and web project or site are in the same parent directory
            const string applicationPath = @"..\..\..\CassiniDev.TestSite";

            // Will start specified application as "localhost" on loopback and first available port in the range 8000-10000 with vpath "/"
            StartServer(applicationPath);

            // if you would like to exercise more control simply use any of the available overloads
        }

        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            StopServer();
        }

        [Test]
        public void Test()
        {

            // normalize URL provides a fully qualified URL rooted on the currently running server's hostname and port
            string url = NormalizeUrl("Default.aspx");

            WebClient wc = new WebClient();
            string actual = wc.DownloadString(url);

            Assert.IsTrue(actual.Contains("this is default.aspx"));

            // for a web testing utility library that simplifies endpoint testing see the Salient.Web namespace in http://salient.codeplex.com
        }
    }

Confirmed Testing Scenarios:
  • MSTests using Visual Studio Test Runner.
  • MSTest tests using all TestDriven runner and coverage options.
  • NUnit tests using NUnit GUI and NUnit console.
  • NUnit tests using NUnit VS integration
  • NUnit tests using Resharper VS integration
  • NUnit tests using all TestDriven runner and coverage options.
  • NUnit tests in TeamCity pulling from CodePlex

Last edited May 18, 2010 at 5:06 AM by Sky, version 6

Comments

desert000 Aug 16, 2010 at 4:14 AM 
Very nice. I have a scenario where I can't figure out how to get this to work. I have 3 projects - Proj1, Proj2 & Proj3 - in a VS 2010 solution. In IIS7, Proj1 is the web site and Proj2 & Proj3 are applications under that site. (accessed as http://localhost, http://localhost/App2 & http://localhost/App3). Proj2 & Proj3 have their web.config files with some values but they inherit other values from the parent site Proj1/web.config.

In the unit test fixture setup I started them as follows:

CassiniDevServer proj1 = new CassiniDevServer();
proj1.StartServer(@"C:\mysolution\proj1", 8000, "/", "localhost");
CassiniDevServer proj2 = new CassiniDevServer();
proj2.StartServer(@"C:\mysolution\proj2", 8001, "App2", "localhost");
CassiniDevServer proj3 = new CassiniDevServer();
proj3.StartServer(@"C:\mysolution\proj1", 8002, "App3", "localhost");

And they all started without any problem.

When my WatiN test tried to open "http://localhost:8002/App2/page1.aspx", it failed where the code was trying to read a config value but got a null, e.g., ConfigurationManager.AppSettings["SpecialValue"] because "SpecialValue" is defined only in Proj1/web.config not in Proj2/web.config. But all this config inheritance works fine when deployed in IIS.

I really like this tool and don't want to start a Process using WebDev.WebServer.EXE. Any suggestions would be appreciated.