We shipped v1 of the SharePoint Guidance with a good set of unit tests. These unit tests paid for themselves several times over each time we refactored the code base. As an agile developer, this made me very happy.

After we shipped, my project manager, wanted a set of integration tests that could be used to stress test the application, so he asked me if we could repurpose our unit tests to also run as integration tests. Crazy idea eh?

Unit tests are great to assert the behavior of granular pieces of functionality. Optimally, unit tests are written so that only the granular piece of functionality is tested. Dependant services and systems are replaced with stubs or mocks. Unit tests written this way are short and readable. The code’s functionality is clear by reading the unit test. However since dependant systems and services are not actually called in these unit tests, they don’t work very well as integration tests.

Here is an example unit test:

[TestMethod]
[ExpectedException(typeof(SPException), "The Enrollment Deadline Date can not be before today's date.\r\n")]
public void AddingCourseWithInvalidEnrollmentDateCancelsWithError()
{
    //Setup our mock so that our enrollment date is invalid
    TrainingCourse course = new TrainingCourse
    {
        Title = "My Title",
        Code = "12345678",
        EnrollmentDate = DateTime.Today.AddDays(-1),
        StartDate = DateTime.Today.AddDays(1),
        EndDate = DateTime.Today.AddDays(2),
        Cost = 100
    };
    SPWeb web = CreateMockSPWeb();

    TrainingCourseRepository repository = new TrainingCourseRepository();
    repository.Add(course, web);
}

If we wanted to leverage this code as an integration test, we would need to modify the CreateMockSPWeb method to return a mock when run as a unit test, and return a real SPWeb from a live instance of SharePoint when run as an integration test. Sounds pretty simple, until you realize all the setup and teardown code that needs to be written. There is a point where you add so much code to your unit tests, making them less readable and maintainable, that it makes more sense to just write a separate set of integration tests. We quickly reached this point and decided to invest in writing a set of integration tests.

Here is an example integration test that asserts the same functionality as the unit test above:

[TestMethod]
[ExpectedException(typeof(SPException), "The Enrollment Deadline Date can not be before today's date.\r\n")]
public void AddingCourseWithInvalidEnrollmentDateCancelsWithError()
{
    //Setup our mock so that our enrollment date is invalid
    TrainingCourse course = new TrainingCourse
    {
        Title = "My Title",
        Code = "12345678",
        EnrollmentDate = DateTime.Today.AddDays(-1),
        StartDate = DateTime.Today.AddDays(1),
        EndDate = DateTime.Today.AddDays(2),
        Cost = 100
    };

    using (SPSite site = new SPSite(siteUrl))
    {
        using (SPWeb web = site.AllWebs[webId])
        {
            TrainingCourseRepository repository = new TrainingCourseRepository();
            repository.Add(course, web);
        }
    }
}

We shipped several integration test projects together with our Build Verification Tests. Please note that integration tests are typically written by developers to validate that their code integrates correctly with other sub systems. Integration tests run “below the glass”, executing code using the API. BVT’s on the other hand, are typically written by testers and run “above the glass”, executing code through the application’s UI.

We