Search code examples
externalxunit

How can I use an Excel file as test data correctly?


How can I best use an Excel file as input for an xUnit test? Note that I do not want to use the data inside the Excel, but the Excel itself.

Let's say I have a UnitTests project, where I want to place some Excel files, that I need to put in my tests:

[Fact]
public void Constructor_ShouldReadExcelFile()
{
    var mapping = new ExcelMapping("excelfiles/test1.xlsx");

    Assert.True(mapping.Valid);
}

but, when running that, the CurrentWorkingDirectory is set to the bin\Debug\net7.0 dir, and I need to make a relative path:

[Fact]
public void Constructor_ShouldReadExcelFile()
{
    var mapping = new ExcelMapping("../../../excelfiles/test1.xlsx");

    Assert.True(mapping.Valid);
}

This will work, but is this the "right" way?


Solution

  • Your solution looks fine to me.

    I often need to retrieve test data files for unit tests and generally proceed as follows. The test data are also under version control but in a different folder than the unit tests. In my unit test class, I define a relative path for the test data and make a member for the absolute path:

            const string testDataRelativePath = @"..\..\..\..\excelfiles\";
            string testDataFolderAbsolutePath;
    

    The relative path is relative to the project folder where the unit test dll is output.

    In the constructor of the test class I define a value for the absolute path.

    using System.IO;
    using System.Reflection;
    
        public class MyTestClass
        {
            public MyTestClass()
            {
                string projectDir = getProjectDir();
                testDataFolderAbsolutePath = Path.GetFullPath(Path.Combine(projectDir, testDataRelativePath));
            }
    
            internal static string getProjectDir()
            {
                Assembly assembly = Assembly.GetExecutingAssembly();
                return directoryPathNameFromAssemblyCodeBase(assembly);
            }
    
            internal static string directoryPathNameFromAssemblyCodeBase(Assembly assembly)
            {
                Uri codeBaseUrl = new Uri(assembly.CodeBase);
                string codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
                return Path.GetDirectoryName(codeBasePath);
            }
        
            // ... Tests ...
        }
    

    In the test itself, I then do something like this:

    string excelFilePath = Path.Combine(testDataFolderAbsolutePath, "test1.xlsx");
    

    I find that this gives better results on the plurality of systems on which the tests are running.