【问题标题】:Convert string to C# code将字符串转换为 C# 代码
【发布时间】:2016-03-09 02:01:05
【问题描述】:

在当前的 NUnit 版本中,我可以参数化 TestFixture 并多次实例化它。例如:

[TestFixture("var1")]  
[TestFixture("var2")]  
[TestFixture("var3")]  
public class MyTestFixture  
{  
    private string var;  

    public MyTestFixture(string var)  
    {  
        this.var = var;  
    }  

    ...  

}  

这将使用参数参数实例化 MyTestFixture 3 次。我的问题是当前的 NUnit 没有 TextFixture 属性的数据源功能(只有 TestCaseSource)。我需要根据数据输入实例化TestFixture,每个TestFixture都有不同的测试用例数据输入集。多亏了TestCaseSource,驱动测试用例数据没有问题。但是如何为 TestFixture 属性执行此操作?

我的想法是动态生成 TestFixture 属性,然后将其更改为代码字符串并插入到测试代码中,例如:类似这样的内容:

ConvertToCode(GenerateTestFixture());  
public class MyTestFixture  
{  
   ...  
}  

我该怎么做?还是有更好的方法?

非常感谢您的帮助。

最好的问候,
爱德华

【问题讨论】:

    标签: c# nunit nunit-2.5


    【解决方案1】:

    动态为您的方法创建属性是可能的,但很难。你最好找到另一种方法。

    当您的代码被编译并自动插入到您的代码中时,编译器会读取您拥有的那种属性(例如[TestFixture])。

    要为类生成您自己的属性,您需要使用 Reflection.Emit 之类的东西来修改生成的程序集,作为项目的构建后步骤。这就像直接编写汇编语言(您将创建 MSIL),这可能很有趣但并不容易,并且会使您的代码非常难以维护!

    另一种方法可能是让一个枚举控制测试用例,并有一个检查枚举并返回适当数据的方法:

    public enum TestController
    {
        Value1,
        Value2,
        Value3
    }
    
    [TestFixture(TestController.Value1)]   
    [TestFixture(TestController.Value2)]   
    [TestFixture(TestController.Value3)]   
    public class MyTestFixture   
    {   
        public MyTestFixture(TestController testController)   
        {   
            var dataForTest = GetDataForTest(testController);
        }   
    
        ...   
    
    }   
    

    然后GetDataForTest() 方法将有某种 switch 语句来生成数据。

    另一种方法可能是使用类型而不是枚举,然后在 GetDataForTest() 方法中实例化类型并调用工厂方法 - 但我认为这可能有点过于复杂。

    【讨论】:

    • 非常感谢杰里米。问题是 TestFixture 是数据驱动的,所以我不会事先知道会有多少价值。另一种方法是否适用于数据驱动的 TestFixture?如果是的话,你能给我一个简短的样本吗?再次非常感谢您的帮助。最好的问候,爱德华
    • 如果你不知道会有多少,那么我认为不可能对每个数据项进行单独的测试。相反,您需要进行一项测试来测试所有数据项。
    • 实际上已经存在一个测试用例测试所有数据项的测试,我们也有自定义测试结果来为每个数据项生成结果。但是由于 NUnit 2.5 支持数据驱动,我的任务是将现有的测试转换为 UNUnit 数据驱动。这比现有测试有一些好处,例如在 UI 中看起来更好,可以运行一个测试等。我可以只使用 TestCaseSource,问题是测试名称变得很长,并且作为测试用例有很多重复层次分明。我想我会试试 Reflection.Emit 方法。非常感谢您的帮助。最好的问候,爱德华
    • Reflection.Emit 在这里肯定不是微不足道的——你实际上是在复制像 PostSharp 这样的面向方面编程的工具。
    【解决方案2】:

    看看那里:

    http://www.dotnetspider.com/resources/26499-Making-NUnit-test-cases-data-driven.aspx

    [TestCaseSource] 和 TestCaseData 是您要查找的类

    【讨论】:

      【解决方案3】:

      现在可以在 NUnit 3.x 中使用 TestFixtureSource 属性。创建一个使用您的值实现 IEnumerable 的类,然后像这样使用它:

      [TestFixtureSource(typeof(Foo), Category = "Quux")]
      public class BarTest
      {    
           public BarTest(object baz)
           {
               _baz = baz;
           {
      }
      

      随着 TestCaseSource 发生变化并适用于 TestFixtureSource 的一件事是,您必须给它一个实现 IEnumerable 的类型或给它一个静态方法。如果您依赖从构造函数生成数据的属性或方法,那么您需要以静态方式重构,或者只让类自己实现 IEnumerable 并将自己作为源类型传入。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-13
        • 2012-09-10
        • 2011-03-09
        • 2019-05-18
        • 1970-01-01
        • 2014-09-30
        • 1970-01-01
        相关资源
        最近更新 更多