web-dev-qa-db-ja.com

VisualStudio-プロジェクトにリソースをロードするユニットテスト

目標は、それらの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にロードするアルゴリズムをどのように記述しますか?

23
p.campbell

単体テストプロジェクトで、XMLファイルを出力ディレクトリにコピーするビルド後のイベントを追加します。次に、元のコードを使用してXMLファイルを取得できます。

ビルド後のイベントは次のようになります。

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

パスに追加するためにこれが必要になる場合もあります。

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

これには、Visual Studioの単体テスト機能があります。 DeploymentItemAttribute

この機能を使用して、必要なすべてのファイルが存在するかどうかをテストする前に、特定のプロジェクトフォルダー内のすべてのxmlファイルを単体テスト出力フォルダーにコピーします。

この属性を単体テストで使用して、特定のファイルをProjectフォルダー(またはその他の場所)から単体テスト出力フォルダーにコピーできます。そのようです:

[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));
}

最初のパラメーターはソースで、2番目のパラメーターは宛先フォルダーです。ソースはソリューションフォルダーに相対的であり(したがって、テスト対象のプロジェクトの単体テストプロジェクトにアクセスできます)、宛先は単体テストアセンブリの出力フォルダーに相対的です。

更新:

これを機能させるには、テスト設定で展開を有効にする必要があります。このMSDNページでは、その方法について説明しています(非常に簡単です): http://msdn.Microsoft.com/en-us/library/ms182475(v = vs.90).aspx#EnableDisableDeploy

24
Pieter Müller

これらのファイルを実行可能ファイルにビルドし(「BuildAction」プロパティを「EmbeddedResource」に設定)、Assembly.GetManifestResourceStream methodを使用して取得できます。

23
ChrisW

ユニットテストでアクセスしたい基本的なパスの取得を処理するために、ヘルパークラスを使用しています。

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」という名前の中央クラスを使用して、ルートフォルダー、ルート名前空間、モジュールなど、アプリケーションに関する基本的な詳細を示します。クラスはアプリの存在に依存することがあるため、代わりにinitを配置します。上記のようなコードを使用してテストハーネス用に自身を初期化し、単体テストのInitコマンドからそのメソッドを呼び出すアプリのメソッド。

(更新しました)

古い答え

これは、テストするプロジェクトフォルダー内のファイルにアクセスするための任意のパスを取得するのに役立つことがわかりました(コピーする必要がある場合に忙しい作業になる可能性があるテストプロジェクトフォルダー内のファイルとは対照的です)。

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

次に、これらの変数のいずれかを使用して、関連するプロジェクトから必要なものにアクセスできます。明らかに、「ProjectName」をプロジェクトの実際の名前と交換してください。

4
Chris Moschini

リソースは単なるリソースであり、それだけです。複雑にする必要はありません。それらを埋め込みたくない場合は、これらのファイルを「コンテンツ」リソースとしてプロジェクトに追加し、_Copy always_に設定できます。次に、コードでサブフォルダーを指定します。

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

これにより、プロジェクト出力(実行中のアセンブリの場所)からリソースが自動的に読み込まれますbin\$(Configuration)\ResourceSubfolder\

これは、単体テストだけでなく、すべてのタイプのプロジェクトで機能します。

1
vezenkov

パスをapp.configに入れて、デフォルトのパスからロードします。私のチームでは、開発者がパスを変更することについて本当に肛門的です。したがって、すべての開発者がコンピューター上で同じ正確なパスとファイルを持つようにします。したがって、不正な開発者が自分のワークスペースに合わせてパスを変更するという問題はありません。

たとえば、私のチームのすべての開発者は、C:\ Project\Product\Moduleなどを使用する必要があります。また、インストールされているすべてのソフトウェアも標準であることを確認します。このようにして、どのマシンも他のマシンに簡単にゴースト化できます。

0
Andrew Keith

VS.NET 2012では、DeploymentItem属性はテスト設定を構成しなくても機能すると思います。

0
freeze