Loading External Files for Image Comparison using Specflow and MSTests

Every now and then you need to be able to load an external file into your test such as an image or a spread sheet of expected results. The normal way to do this for an application would be to add the file to your project and then set the “Build Action” and “Copy to Output Directory” properties to ensure that the content is built with an application.

image

The problem with this is that it does not work for Tests when you try to access it via a relative path. This is because tests are either run in the same folder as the test or in a separate deployment folder. Before the test runs the Test Assembly, Dependant Assemblies and any files you have specified are copied to the deployment folder. So how do you specify a file to be included in this deployment? This is done by using the DeploymentItem attribute.

image

This attribute can be added to either the TestMethod or the TestClass. The problem with this though is that the TestClass and TestMethods are generated in specflows feature.cs file. In the current version there is no support to add files as deployment items in the generated code but there is a work around. The TestClass is a partial class, this means we can extend that class to give us the ability to add the DeploymentItem attribute.

image

1. Create a new partial class with the same name as the generated class and add the deployment item attribute to the class.

image

2. Under Solution Items double click the testsettings file for your environment. The default is Local.testsettings. Go to Deployment and enable deployment. If you have files that are used by all tests you can add them in this location. However if only a few tests use the file it is better to use the attribute so the file is not copied if the test that uses it is not run.

image

3. Set the Copy to Output Directory to “Copy if newer” and make sure the Build Action is “Content”

image

4. Reference the resource in your step definition just as you would have referenced a relative resource. Note that the resource is copied into Test Results output folder so it doesn’t keep the folder structure.

image

using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using ImageViewer;
using IncludingFilesInTests.Helpers;
using Microsoft.Test.VisualVerification;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TechTalk.SpecFlow;

namespace IncludingFilesInTests
{
    [Binding]
    public class ImageViewerStepDefinitions
    {
        [Given(@"i have the image (.*)")]
        public void GivenIHaveTheImagePenguins_Jpg(string image)
        {
            //store the image uri
            ScenarioContext.Current.Add("imageUri", new Uri(image, UriKind.Relative));
        }

        [When(@"I load the image")]
        public void WhenILoadTheImage()
        {
            //load the image that was deployed with the [DeploymentItem] attribute
            ImageManager.Instance.LoadImage((Uri)ScenarioContext.Current["imageUri"]);
        }

        [Then(@"the image viewer should have loaded Penguins\.jpg")]
        public void ThenTheImageViewerShouldHaveLoadedPenguins_Jpg()
        {
            //Verify that the deployed image was loaded correctly. Image Comparison is using TestApi - http://testapi.codeplex.com

            var expectedImageUri = (Uri)ScenarioContext.Current["imageUri"];

            Snapshot actualImage = Snapshot.FromBitmap(ImageManager.Instance.Image.ToBitmap());
            Snapshot expectedImage = Snapshot.FromFile(expectedImageUri.OriginalString);

            //Get the difference between the images
            Snapshot difference = actualImage.CompareTo(expectedImage);

            //Save images to test results out folder for review
            expectedImage.ToFile(@"Master-expected.jpg", ImageFormat.Jpeg);
            actualImage.ToFile(@"Master-actual.jpg", ImageFormat.Jpeg);
            difference.ToFile(@"Master-difference.jpg", ImageFormat.Jpeg);

            //Tolerance map is black because there is no tolerance, the images should be exactly the same.
            //This would be different if there was conversion involved
            Snapshot toleranceMap = Snapshot.FromFile("PenguinsToleranceMap.jpg");

            //Verify using the tolerance map
            SnapshotVerifier verifier = new SnapshotToleranceMapVerifier(toleranceMap);
            Assert.AreEqual(VerificationResult.Pass, verifier.Verify(difference));
        }
    }
}

The sample code can be found here

https://skydrive.live.com/embedicon.aspx/Specflow/IncludingFilesInTests.zip?cid=45301901ee7e4a69&sc=documents

Advertisements
  1. #1 by REDDY on August 9, 2012 - 8:17 pm

    I have multiple files and tried using this [DeploymentItem(@”\foldername\”)] but didn’t work? the files were not copied.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: