Home > C#, NUnit, Testing > How to run integration tests with File Dependencies

How to run integration tests with File Dependencies

Disclaimer

In many cases a developer test needs to execute with a specific file / set of files that need to be on the file system.  Many “purists” think this is a bad idea and you should “Mock” your system out in such a way that this is not required.  In certain cases that may be true – but I am a “realist” and understand that the complexity requirements around doing things like this can and many times do far outweigh the benefits from just leveraging the file system for the test.  This does however move the test from being a true “unit” test to an “integration” test.  I am content with this as it is also my belief that integration tests provide more value than unit tests.  If setup and run in the correct way – this test can run locally in visual studio, via MS build and the command line, or on a build server running build agents like Team City. 

You can download the source code here: TestClass.zip

Requirements for this Test

  • Test Runner ( I like using TestDriven.Net as it lets me execute in line as well as debug). 
  • A file class that wraps some of the system.IO functions that allows you implement IDisposable. This is useful for creating a “sandbox” that once is out of scope – and it removes any temp files that are used so clean up is done automatically  (an example class is attached in the sample).
  • NUnit or MSTest.  I still prefer NUnit.
      Usage Options

    The requirements for the usage of the test files will determine how and when to set them up and clean up (delete). 

    • Per Test – files are regenerated per test run against them
    • Per Test Class – files are generated once per test class

    In both instances the FileSandBox class is used to create a temporary location for the files to live and then be removed once the test(s) are complete.

     

    Per Class Usage

    [TestFixture]
        public class PerClass
        {
            private FileSandbox _sandbox;
            private string _tempFileLocation;
    
            public PerClass() {}
    
            /// <summary>
            /// Setup class - runs once per class 
            /// </summary>
            [TestFixtureSetUp]
            public void SetupClass()
            {
                _sandbox = new FileSandbox();
                    
                // Getting Temp file name to use
                _tempFileLocation = _sandbox.GetTempFileName("txt");
                // Get the current executing assembly (in this case it's the test dll)
                Assembly myassembly = Assembly.GetExecutingAssembly();
                // Get the stream (embedded resource) - be sure to wrap in a using block
                using (Stream stream = myassembly.GetManifestResourceStream("TestClass.TestFiles.TextFile1.txt"))
                {
                    // In this case using an external method to write the stream to the file system
                    _tempFileLocation = TestHelper.StreamToFile(stream, _tempFileLocation);
                }
            }
    
            /// <summary>
            /// Tear down class (cleanup)
            /// </summary>
            [TestFixtureTearDown]
            public void TearDownClass()
            {
                _sandbox.Dispose();
            }
    
            [Test, Description("Testing doing something with files on the filesystem")]
            public void MyFileSystemTest()
            {
                string[] lines = File.ReadAllLines(_tempFileLocation);
                Assert.IsTrue(lines.Length > 0);
            }
        }

    Per Test Usage (Option 1)

        [TestFixture]
        public class PerTest
        {
            public PerTest(){}
    
            /// <summary>
            /// Setup class - runs once per class 
            /// </summary>
            [TestFixtureSetUp]
            public void SetupClass()
            {
                // NOOP
            }
    
            /// <summary>
            /// Tear down class (cleanup)
            /// </summary>
            [TestFixtureTearDown]
            public void TearDownClass()
            {
                // NOOP
            }
    
            [Test, Description("Testing doing something with files on the filesystem")]
            public void MyFileSystemTest()
            {
                using (FileSandbox sandbox = new FileSandbox())
                {
                    // Getting Temp file name to use
                    string tempfile = sandbox.GetTempFileName("txt");
                    // Get the current executing assembly (in this case it's the test dll)
                    Assembly myassembly = Assembly.GetExecutingAssembly();
                    // Get the stream (embedded resource) - be sure to wrap in a using block
                    using (Stream stream = myassembly.GetManifestResourceStream("TestClass.TestFiles.TextFile1.txt"))
                    {
                        // In this case using an external method to write the stream to the file system
                        tempfile = TestHelper.StreamToFile(stream, tempfile);
                        string[] lines = File.ReadAllLines(tempfile);
                        Assert.IsTrue(lines.Length > 0);
                    }
                }
            }
        }

     

    Per Test Usage (Option 2)

      [TestFixture]
        public class PerEachTest
        {
            private FileSandbox _sandbox;
            private string _tempFileLocation;
    
            public PerEachTest() { }
    
            /// <summary>
            /// Setup class - runs once per class 
            /// </summary>
            [TestFixtureSetUp]
            public void SetupClass()
            {
                // NOOP
            }
    
            /// <summary>
            /// Tear down class (cleanup)
            /// </summary>
            [TestFixtureTearDown]
            public void TearDownClass()
            {
                // NOOP
            }
    
            [SetUp]
            public void Setup()
            {
                _sandbox = new FileSandbox();
    
                // Getting Temp file name to use
                _tempFileLocation = _sandbox.GetTempFileName("txt");
                // Get the current executing assembly (in this case it's the test dll)
                Assembly myassembly = Assembly.GetExecutingAssembly();
                // Get the stream (embedded resource) - be sure to wrap in a using block
                using (Stream stream = myassembly.GetManifestResourceStream("TestClass.TestFiles.TextFile1.txt"))
                {
                    // In this case using an external method to write the stream to the file system
                    _tempFileLocation = TestHelper.StreamToFile(stream, _tempFileLocation);
                }   
            }
    
            [TearDown]
            public void Teardown()
            {
                _sandbox.Dispose();
            }
    
            [Test, Description("Testing doing something with files on the filesystem")]
            public void MyFileSystemTest()
            {
                string[] lines = File.ReadAllLines(_tempFileLocation);
                Assert.IsTrue(lines.Length > 0);
            }
        }

     

     

    You can download the source code here:  TestClass.zip

    About these ads
    1. August 1, 2012 at 7:37 am | #1

      Thx from Stackoverflow

    1. No trackbacks yet.
    You must be logged in to post a comment.
    Follow

    Get every new post delivered to your Inbox.

    Join 164 other followers

    %d bloggers like this: