2009-05-16 49 views
6

私のmstestユニットテストの中には、マルチスレッド競合状態を検出するのに役立つものがあります。何度も繰り返し実行すると最も便利ですが、 - すべてではありません。mstestテストを複数回実行する

テストリストエディタでmstestを設定してテストを複数回実行する方法はありますか?

答えて

10

私は同様のことをする必要があったので、私はこれに対する解決策を考え出しました。

これは簡単ではありませんが、すべてがセットアップされたら、プロジェクト全体で再利用できます。私もGitHub(https://github.com/johnkoerner/MSTestLooper)でこのコードをダウンロードしていますが、ある時点で消えてしまった場合は、ここでどうしましたか?

まず、すべてのテストを複数回実行するようにクラスに適用する属性を作成します。 DLLは特別な場所に置く必要があるため、このすべてを別のアセンブリで行います。

[Serializable] 
public class TestLooperAttribute : TestClassExtensionAttribute 
{ 
    private static readonly Uri thisGuy = new Uri("urn:TestLooperAttribute"); 

    private string _PropertyName; 
    public string PropertyName 
    { 
     get 
     { return _PropertyName; } 
     set 
     { 
      _PropertyName = value; 
     } 
    } 
    public override Uri ExtensionId 
    { 

     get { 
      return thisGuy; } 
    } 


     public override TestExtensionExecution GetExecution() 
    { 

     return new TestLooperExecution(PropertyName); 
    } 
} 

次は、我々は独自のテストクラスの実行クラスを作成する必要があります。

class TestLooperInvoker : ITestMethodInvoker 
{ 
    private TestMethodInvokerContext m_invokerContext; 
    private string PropertyName; 

    public TestLooperInvoker(TestMethodInvokerContext InvokerContext, string PropertyName) 
    { 
     m_invokerContext = InvokerContext; 
     this.PropertyName = PropertyName; 
    } 

    public TestMethodInvokerResult Invoke(params object[] args) 
    { 

     // Our helper results class to aggregate our test results 
     HelperTestResults results = new HelperTestResults(); 

     IEnumerable<object> objects = m_invokerContext.TestContext.Properties[PropertyName] as IEnumerable<object>; 

     foreach (var d in objects) 
      results.AddTestResult(m_invokerContext.InnerInvoker.Invoke(d), new object[1] { d.GetType().ToString()}); 

     var output = results.GetAllResults(); 
     m_invokerContext.TestContext.WriteLine(output.ExtensionResult.ToString()); 

     return output; 
    } 
} 

HelperTestResults:

class TestLooperExecution : TestExtensionExecution 
{ 
    private string PropertyName; 

    public TestLooperExecution(string PropertyName) 
    { 
     this.PropertyName = PropertyName; 
    } 

    public override ITestMethodInvoker CreateTestMethodInvoker(TestMethodInvokerContext InvokerContext) 
    { 
     return new TestLooperInvoker(InvokerContext, PropertyName); 
    } 

    public override void Dispose() 
    { 
     //TODO: Free, release or reset native resources 
    } 

    public override void Initialize(TestExecution Execution) 
    { 
     //TODO: Wire up event handlers for test events if needed 

    } 
} 

最後に、我々はループを実行するところであるカスタム呼び出しを追加クラスは出力用の文字列を構築するだけです。あなたはこれをどのように扱うことができますか?そして、このコードをもっと長く保存するので、そのコードを含めたくありません。

は、DLLにこれをコンパイルして、あなたはまた、クラスのレジストリエントリを作成する必要が

C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies 

にコピーする必要があります。

Windows Registry Editor Version 5.00 
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\TestTypeExtensions\TestLooperAttribute] 
"AttributeProvider"="TestLooper.TestLooperAttribute, TestLooper" 

今、あなたはそのすべてを持っていること最後にクラスを使用することができます:

using System; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using TestLooper; 
using System.Collections.Generic; 
namespace UnitTestSamples 
{ 
    [TestLooper(PropertyName="strings")] 
    public class UnitTest1 
    { 
     public static List<String> strings = new List<String>(); 
     private TestContext testContextInstance; 

     public TestContext TestContext 
     { 
      get 
      { 
       return testContextInstance; 
      } 
      set 
      { 
       testContextInstance = value; 
      } 
     } 
     [ClassInitialize()] 
     public static void Init(TestContext x) 
     { 
      strings.Add("A"); 
      strings.Add("B"); 
      strings.Add("C"); 
      strings.Add("D"); 

     } 

     [TestInitialize()] 
     public void TestInit() 
     { 
      if (!TestContext.Properties.Contains("strings")) 
      testContextInstance.Properties.Add("strings", strings); 
     } 

     [TestMethod] 
     [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "DataDriven1.csv", "DataDriven1#csv", DataAccessMethod.Sequential)] 
     [DeploymentItem("DataDriven1.csv")] 
     public void TestMethodStrings(string s) 

     { 
      int value1 = Convert.ToInt32(TestContext.DataRow["Col1"]); ; 
      TestContext.WriteLine(String.Format("{0}:{1}", s, value1)); 
     } 
    } 
} 

私たちのテストメソッドは、fテストルーパー。また、データ駆動型テストを使用してこれを示して、2つを組み合わせてデータセット全体で大きな順列を生成できることを示します。

+0

私はMSTestがそのような拡張性を持っていたことさえ知りませんでした。これは素晴らしいです、ありがとう! –

2

いくつかのスレッドをスピンオフするテストを作成することを検討してください。テストリストでは、同じテストで複数のエントリを持つことはできません。ただし、マルチスレッドテストを独自のリストに割り当てて、その特定のテストを実行する場合にのみ呼び出すことができます。

+0

これは興味深いアプローチです。ありがとう。 –

2

私は答えがノーだと思います。

3
[TestMethod()] 
public void RepetableTest(){ 
    for(int i = 0; i < repeatNumber; i++){ 

    //test code goes here 


    } 
} 
+1

http://stackoverflow.com/questions/25565574/run-unittest-several-time-not-just-loop-itを参照してください。なぜこれでいつも必要な結果が得られないからです。 – Ricibob

関連する問題