Visual Studio - 单元测试加载项目中的资源

Posted

技术标签:

【中文标题】Visual Studio - 单元测试加载项目中的资源【英文标题】:Visual Studio - Unit tests loading resources in the project 【发布时间】:2010-12-05 04:39:57 【问题描述】:

目标是在给定这些 Xml 文件中的一些数据的情况下运行一些测试。

如何在单元测试方法中轻松地将给定的 Xml 文件加载到 XmlDoc 中?

当前状态是:

  XmlDocument doc = new XmlDocument();
  string xmlFile = "4.xml";
  string dir = System.IO.Directory.GetCurrentDirectory() + @"\Msgs\" 

  //dir is then the value of the current exe's path, which is
  //d:\sourcecode\myproject\TestResults\myComputer 2009-10-08 16_07_45\Out

  //we actually need:
  //d:\sourcecode\myproject\Msgs\ 
  doc.Load( dir + fileName); //should really use System.IO.Path.Combine()!

将路径放在app.config 中只是一件简单的事情吗?考虑到开发人员机器上存在不同路径的可能性,我希望避免这种情况。

问题:在单元测试方法中如何编写将给定 Xml 文件加载到 XmlDocument 中的算法?

【问题讨论】:

【参考方案1】:

为此有一个 Visual Studio 单元测试功能:DeploymentItemAttribute

我使用此功能将给定项目文件夹中的所有 xml 文件复制到单元测试输出文件夹,然后再测试是否存在所有必需的文件。

您可以将此属性与单元测试一起使用,以将特定文件从项目文件夹(或其他任何位置)复制到单元测试输出文件夹。像这样:

[TestMethod()]
[DeploymentItem("MyProjectFolder\\SomeDataFolder\\somefile.txt", "SomeOutputSubdirectory")]
public void FindResourcefile_Test()

    string fileName = "SomeOutputSubdirectory\\somefile.txt";
    Assert.IsTrue(System.IO.File.Exists(fileName));

您还可以复制整个文件夹的内容:

[TestMethod()]
[DeploymentItem("MyProjectFolder\\SomeDataFolder\\", "SomeOutputSubdirectory")]
public void FindResourcefile_Test()

    string fileName = "SomeOutputSubdirectory\\someOtherFile.txt";
    Assert.IsTrue(System.IO.File.Exists(fileName));

第一个参数是源文件夹,第二个参数是目标文件夹。源相对于您的解决方案文件夹(因此您可以访问正在测试的项目的单元测试项目),目标相对于单元测试程序集的输出文件夹。

更新:

您需要在测试设置中启用部署才能使其工作。这个 MSDN 页面解释了如何(真的很简单):http://msdn.microsoft.com/en-us/library/ms182475(v=vs.90).aspx#EnableDisableDeploy

【讨论】:

这不适用于 NUnitDeploymentItemAttributeMicrosoft.VisualStudio.TestTools.UnitTesting 请注意,您必须设置要使用的文件的属性“复制到输出”:在解决方案资源管理器中选择它们并将复制到输出属性设置为如果较新则复制。请参阅此链接:msdn.microsoft.com/en-us/library/…【参考方案2】:

您可以将这些文件构建到您的可执行文件中(将它们的“构建操作”属性设置为“嵌入式资源”),然后使用Assembly.GetManifestResourceStream method 获取它们。

【讨论】:

Patrick Cauldwell 有一篇关于 http://www.cauldwell.net/patrick/blog/TestingWithExternalFiles.aspx 的有趣文章【参考方案3】:

在单元测试项目中添加一个将 XML 文件复制到输出目录的构建后事件。然后,您可以使用您的原始代码来获取 XML 文件。

构建后事件将如下所示:

copy $(SolutionDir)file.xml $(ProjectDir)$(OutDir)file.xml

您可能还需要将此添加到您的路径中:

Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)

【讨论】:

我发现我的文件将进入“Project1_UnitTests\bin\Debug”,而测试试图在“TestResults\Username_PCName_datetime\Out”下找到它..??? 根据@Greg 评论的 6 次投票,我已编辑此答案并添加了附加信息以使此答案更完整。 @javamonkey79 这对java没有帮助 您不需要构建后步骤来执行此操作。只需在数据文件上设置“复制到输出目录”属性。 @DominicCronin 这不是真的。如果数据文件是被测项目的一部分,它们将被复制到项目的调试文件夹中,但它们不会被复制到单元测试输出文件夹,即单元测试期间执行程序集的位置。 【参考方案4】:

我使用辅助类来处理获取我可能希望在单元测试中访问的基本路径。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Brass9.Testing

    public static class TestHelper
    
        public static string GetBinPath()
        
            return System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
        

        public static string GetProjectPath()
        
            string appRoot = GetBinPath();
            var dir = new DirectoryInfo(appRoot).Parent.Parent.Parent;
            var name = dir.Name;
            return dir.FullName + @"\" + name + @"\";
        

        public static string GetTestProjectPath()
        
            string appRoot = GetBinPath();
            var dir = new DirectoryInfo(appRoot).Parent.Parent;
            return dir.FullName + @"\";
        

        public static string GetMainProjectPath()
        
            string testProjectPath = GetTestProjectPath();
            // Just hope it ends in the standard .Tests, lop it off, done.
            string path = testProjectPath.Substring(0, testProjectPath.Length - 7) + @"\";
            return path;
        
    

有时我与路径的交互更复杂;我经常使用我命名为“App”的中心类来指示有关应用程序的一些基本细节,例如它的根文件夹、它的根命名空间和模块等。类有时取决于 App 的存在,因此我将放置一个 init App 上的方法,该方法使用上述代码为测试工具初始化自身,并从单元测试中的 Init 命令调用该方法。

(更新)

旧答案

我发现这有助于获取任意路径来访问您打算测试的项目文件夹中的文件(与测试项目文件夹中的文件相反,如果您需要复制内容,这可能会很忙)。

DirectoryInfo projectDir = new DirectoryInfo(@"..\..\..\ProjectName");
string projectDirPath = projectDir.FullName;

然后,您可以使用其中任何一个变量从相关项目中访问您需要的任何内容。显然将“ProjectName”替换为您的项目的实际名称。

【讨论】:

或者,如果你的路径看起来像“TestResults\Username_PCName_datetime\Out”,你可以使用ProjectDir = new System.IO.DirectoryInfo(@"..\..\..\..\..\..\ProjectName"); 我在使用这种方法时遇到了问题。一条路径适用于 MS 测试运行器,但对于其他运行器可能不起作用。例如,一些开发人员使用 MS Test Runner 和一些 ReSharper 并且测试路径不同 (\TestResults\) 并且以一种或另一种方式失败。由黑客修复:/【参考方案5】:

资源就是资源,仅此而已,无需复杂化。如果您不想嵌入它们,那么您可以将这些文件作为“内容”资源添加到您的项目中,并将它们设置为Copy always。然后在代码中指定子文件夹:

var xmlDoc = XElement.Load("ProjectSubFolder\\Resource.xml");

这将自动从项目输出(运行程序集位置)bin\$(Configuration)\ResourceSubfolder\加载资源

这适用于所有类型的项目,而不仅仅是单元测试。

【讨论】:

【参考方案6】:

我只是将路径放在 app.config 中并从默认路径加载。在我的团队中,我真的很讨厌开发人员更改路径,所以我让我的所有开发人员在他们的计算机上拥有相同的确切路径和文件,所以我没有任何流氓开发人员更改路径以适应他的工作空间的问题。

例如,我团队中的所有开发人员都必须使用 C:\Project\Product\Module 等。我还确保他们安装的所有软件也是标准的。这样,我可以轻松地将任何机器幻像到任何其他机器。

【讨论】:

【参考方案7】:

我认为在 VS.NET 2012 DeploymentItem 属性中无需任何测试设置配置即可工作。

【讨论】:

以上是关于Visual Studio - 单元测试加载项目中的资源的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Visual Studio 2017 中构建我的单元测试项目

使用本机单元测试项目在 Visual Studio 2017 中对 C 代码进行单元测试

Qt:使用 Visual Studio 进行单元测试

在 Visual Studio 2013 中使用 HttpClient 进行单元测试/集成测试 Web API

在Visual Studio2015中使用单元测试

您可以在单元测试项目中使用 Visual Studio 数据库项目来为功能测试设置一个空数据库吗?