Повторите тест mstest несколько раз - PullRequest
8 голосов
/ 16 мая 2009

Некоторые из моих модульных тестов mstest помогают обнаруживать условия многопоточной гонки, и поэтому они наиболее полезны при многократном запуске подряд, но я хочу сделать это только для определенных тестовых прогонов - не всегда.

Есть ли способ настроить mstest (желательно в редакторе списка тестов) для запуска теста несколько раз?

Ответы [ 4 ]

11 голосов
/ 03 февраля 2013

Мне нужно было сделать нечто подобное, поэтому я нашел решение для этого.

Это не просто, но как только все настроено, вы можете использовать его в разных проектах. У меня также есть загрузка этого кода на 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 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

    }
}

Наконец, мы добавляем пользовательский invoker, в котором мы выполняем цикл:

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 просто создает строки для вывода, вы можете обрабатывать это так, как хотите, и я не хочу включать этот код, потому что он просто сделает этот пост намного длиннее.

Скомпилируйте это в 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));
        }
    }
}

Обратите внимание, что наш тестовый метод принимает параметр, который поступает от тестового петлителя. Я также показываю это с помощью теста, управляемого данными, чтобы показать, что вы можете объединить их вместе для создания больших перестановок в ваших наборах данных.

6 голосов
/ 12 января 2011
[TestMethod()]
public void RepetableTest(){
   for(int i = 0; i < repeatNumber; i++){

     //test code goes here


   }
}
2 голосов
/ 20 ноября 2009

Полагаю, ответ - нет.

2 голосов
/ 04 июня 2009

Подумайте о создании теста, чтобы раскрутить пару потоков. Список тестов не позволит вам иметь несколько записей для одного теста. Однако вы можете назначить многопоточный тест своему собственному списку и вызывать его только тогда, когда вы хотите запустить этот конкретный тест.

...