将参数传递到T4模板内的单元测试中

时间:2017-10-20 15:45:45

标签: c# unit-testing t4

我有以下名为(MyTest.tt) T4 模板文件,其中tail -f /proc/28897/fd/1(字符串)和TestName(操作)是参数。我可以将lambda动作传递给模板吗? 如何将数据传递给参数?

MyAction

2 个答案:

答案 0 :(得分:1)

我建议您使用NUnit来获取NuGet。

您可以使用TestCaseData发送参数化对象。它也已完成here

注意:我不使用T4。您可能需要稍微调整一下代码,但这是个主意。

namespace Test.TestTemplate
{
    [TestFixture]
    [TestCaseSource(typeof(TestTemplateData), "HasAccessData")]
    // Make the type as bool so you can run it against the NUnit .Returns
    public bool HAS_ACCESS_<#= "TestName" #>(string stringParameter, Action actionParameter)
    {
        <#= MyAction.Invoke() #>

        // Do something here with the parameters...
        // Remember you have to return here so the .Returns can assert against it.
        // No need to do Assert
    }
}

然后是包含测试数据的数据源文件

public class TestTemplateData
{
    // I assume you will use the same action all the time, so just
    // define it here
    private Action<int> square = (int x) => x * x;

    public static IEnumerable HasAccessData
    {
        get
        {
            yield return new TestCaseData
            (
                // This is the string parameter
                "Word",
                // Put whatever parameter you want for your action
                square(1)
            )
            .SetName("Name of this test case") // Test name
            .Returns(true); // What is the test expected to return

            // You can return multiple test cases this way
            yield return new TestCaseData
            (
                "Word",
                square(2)
            )
            .SetName("Name of this test case") // Test name
            .Returns(true); // What is the test expected to return
        }
    }
}

答案 1 :(得分:1)

将参数注入模板可能并不容易。如果你从visual studio运行它们的t4模板的执行上下文我认为是不可访问的。它们可以以编程方式执行,但我从未这样做过。

如果您尝试参数化t4模板,我现在可以想到几个选项。

选项1 - 预定义数据:定义匿名类型的集合(仅用于更简单的原型设计),其中包含两个字段,用于测试名称和要在t4模板中调用的委托,然后是很容易从集合中生成多个测试。

<#
// define the collection
var testCases = new [] {
 new {name = "TestCase1", method = new Action(() => { /* your action body */ }) },
 etc
};
#> 

然后从testCases数据生成测试。

<# foreach(var testCase in testCases) { #>
   [TestMethod]
   public void HAS_ACCESS_<#= testCase.name #> ()
   {
        <#= testCase.method() #>
   }

<# } #>

选项2 - 共享模板:您可以定义基本t4模板,该模板可以包含在另一个模板中并从中执行。这可以是您的基本模板

 [TestClass]
 public class Test2
 {
    [TestMethod]
      public void HAS_ACCESS_<#= TestName #>()
      {                       
       <#= MyAction.Invoke() #>                
      }
 }

请注意,使用 TestName MyAction ,因为它们是模板中定义的变量。现在在第二个模板中,您可以执行以下操作

<#
    string TestName = "TestCase1";
    Action MyAction = () => { };
#>
<#@ include file="{Yor tempalte name.tt}" #>

其中'您的模板名称.tt'是先前定义的基本t4模板的实际名称。

这样你就可以定义多个t4模板,它将使用提供的参数调用基本模板。

注意 - 注入dll:如果你真的需要从现有的dll调用预定义的方法(你提到 UICoded方法),你可以在你的内容中包含如下的dll模板然后从dll中使用你需要的东西。

<#@ assembly name="$(TargetDir)Mydll.dll" #>

<#@ assembly name="C:/..../Mydll.dll" #> 

当我需要从预定义数据生成多个测试时(当我知道我的测试用例但手动工作太多而且可以自动化时),我使用第一个选项

我在生成c#类时使用的第二个选项(对于单元测试生成而言并非如此),并且不希望所有这些都位于单个文件中。