【问题标题】:Repeat mstest test run multiple times多次重复 mstest 测试运行
【发布时间】:2009-05-16 15:50:21
【问题描述】:

我的一些 mstest 单元测试有助于检测多线程竞争条件,因此它们在连续运行多次时最有用,但我只想针对特定的测试运行执行此操作 - 并非一直如此。

有没有办法配置 mstest(最好在测试列表编辑器中)以多次运行测试?

【问题讨论】:

    标签: .net mstest


    【解决方案1】:

    我需要做类似的事情,所以我想出了一个解决方案。

    这并不简单,但一旦一切就绪,您就可以跨项目重复使用它。我还在 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
    
        }
    }
    

    最后我们添加一个自定义调用器,我们在其中执行循环:

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

    请注意,我们的测试方法接受一个来自测试循环器的参数。我还使用数据驱动测试来展示这一点,以表明您可以将两者结合在一起以在您的数据集中生成大的排列。

    【讨论】:

    • 我什至不知道 MSTest 有这样的可扩展性。太好了,谢谢!
    【解决方案2】:
    [TestMethod()]
    public void RepetableTest(){
       for(int i = 0; i < repeatNumber; i++){
    
         //test code goes here
    
    
       }
    }
    

    【讨论】:

    【解决方案3】:

    考虑创建一个测试来分离几个线程。测试列表不允许您为同一测试拥有多个条目。但是,您可以将多线程测试分配给它自己的列表,并仅在您想要运行该特定测试时调用它。

    【讨论】:

    • 这是一个有趣的方法。谢谢。
    【解决方案4】:

    我猜答案是否定的。

    【讨论】:

      猜你喜欢
      • 2010-10-08
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 2010-10-13
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 2014-03-12
      相关资源
      最近更新 更多