2009-05-16 5 views
6

내 mstest 유닛 테스트 중 일부는 멀티 스레딩 경쟁 조건을 감지하는 데 도움이되므로 여러 번 연속 실행될 때 가장 유용하지만 특정 테스트 실행에 대해서만이 작업을 수행하려고합니다. - 항상 그렇지는 않아.mstest 테스트를 여러 번 반복하십시오.

테스트 목록 편집기에서 mstest를 여러 번 테스트하도록 구성하는 방법이 있습니까?

답변

10

비슷한 것을해야하므로이 해결책을 찾았습니다.

간단하지는 않지만 일단 모든 것이 설정되면 프로젝트 전체에서 다시 사용할 수 있습니다. 나는 또한 GitHub (https://github.com/johnkoerner/MSTestLooper)에이 코드를 다운로드했다. 그러나 어떤 점에서 사라지면, 내가 어떻게했는지 여기에있다.

먼저 모든 테스트를 여러 번 실행하도록 클래스에 적용 할 속성을 만듭니다. DLL은 특별한 위치에 있어야하기 때문에 별도의 어셈블리에서이 모든 작업을 수행하십시오.

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 

    } 
} 

마지막으로 우리는 사용자 정의 호출자를 추가

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

다음으로 우리는 사용자 정의 테스트 클래스 실행 클래스를 만들어야합니다 클래스는 출력을 위해 문자열을 구성하기 만하면 원하는 방식으로 처리 할 수 ​​있으며이 코드를 포함시키지 않으므로이 게시물을 훨씬 길게 만들 수 있습니다.

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 시험 루퍼. 또한 데이터 기반 테스트를 사용하여 두 데이터를 결합하여 데이터 세트 전체에서 큰 순열을 생성 할 수 있음을 보여줍니다.

+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