11

我在 TeamTest 中有一个名为“MyClassTest”的单元测试项目。这个项目有三个TestMethods。每个方法都需要自己的测试初始化​​步骤。但是当我将TestInitializeAttribute应用于三个初始化方法时,它说该属性不应多次使用。那么在 Visual Studio Team Test 中用于初始化每个测试方法的属性应该是什么?

参考:

  1. VS 团队测试:使用 Excel 作为数据源的 .Net 单元测试:适配器失败

  2. 如何为 Visual Studio 测试项目创建启动和清理脚本?

  3. 带有自定义计数器的 VS 2010 负载测试结果

  4. 如何在 MSTest 中记录单元测试进入和离开

  5. 单元测试项目可以加载目标应用程序的 app.config 文件吗?

4

5 回答 5

24

根据MSDNTestInitializeAttribute:_

  • 不能多次使用(AllowMultiple = false),并且
  • 不能继承来创建自己的TestInitializeAttribute.

所以,我的建议是创建没有该TestInitialize属性的测试初始化​​方法。然后在唯一TestInitialize方法中检查当前执行TestMethod的方法并调用适当的初始化方法:

[TestClass]
public class UnitTest
{
    public TestContext TestContext { get; set; }

    [TestInitialize]
    public void Initialize()
    {
        switch (TestContext.TestName)
        {
            case "TestMethod1":
                this.IntializeTestMethod1();
                break;
            case "TestMethod2":
                this.IntializeTestMethod2();
                break;
            default:
                break;
        }
    }

    [TestMethod]
    public void TestMethod1()
    {
    }

    [TestMethod]
    public void TestMethod2()
    {
    }

    public void IntializeTestMethod1()
    {
        //Initialize Test Method 1
    }

    public void IntializeTestMethod2()
    {
        //Initialize Test Method 2
    }
}
于 2012-05-22T10:33:57.080 回答
12

如果您有三个测试方法,并且每个方法都有自己的初始化步骤,那么为什么要将初始化转移到将在每次测试之前运行的方法?我看到的唯一好处是那个不错的 switch 块,它在你的源文件中添加了一些行。但它给您带来了缺点 - 查看这些测试方法中的任何一种,您都无法真正判断将在哪个上下文方法中执行。所以,我使用初始化方法来设置基本的上下文,这是真正被夹具中的所有测试使用的。

只需将上下文创建移动到arrange每个方法的一部分。

如果您有几个使用公共上下文的方法,那么只需提取方法,它将为它们设置上下文,并在arrange部分调用它。您还可以将每个上下文设置拆分为多个步骤并重用这些步骤(就像在Specflow等 Given-When-Then 工具中所做的那样)。

当然,创建不同的固定装置也是一种选择。

于 2012-05-22T12:35:39.643 回答
6

这有点老帖子,但我想出了以下似乎工作正常:首先,定义一个属性类:

[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class InitialiseWithAttribute : Attribute
{
    public string Id { get; private set; }

    public InitialiseWithAttribute(string id)
    {
        Id = id;
    }
}

然后在一些方便的实用程序类中定义一个扩展方法:

    public static bool IsInitialisedWith(this string testName, string value)
    {
        bool result = false;
        Type testClassType = new StackFrame(1).GetMethod().DeclaringType;
        MethodInfo methodInfo = testClassType.GetMethod(testName);
        if (methodInfo != null)
        {
            InitialiseWithAttribute initialiseWithAttribute =
                methodInfo.GetCustomAttribute<InitialiseWithAttribute>(true);
            if (initialiseWithAttribute != null)
            {
                result = initialiseWithAttribute.Id == value;
            }
        }
        return result;
    }

现在编写您的测试,因此:

    public TestContext TestContext {get; set;}
    [TestInitialize]
    public void TestInitialise()
    {
        if (TestContext.TestName.IsInitalisedWith("DoSomethingSpecial")
        {
             // ... Do something special
        }
        else
        {
             // ... Do something normal
        }
    }

    [TestMethod]
    [InitialiseWith("DoSomethingSpecial")]
    public void MySpecialTest()
    {
         // The test
    }
于 2015-01-27T16:44:21.013 回答
3

如果他们需要三个单独的初始化;那么它们可能应该在三个独立的装置中,每个装置都有自己的 init!

于 2012-05-22T10:26:19.333 回答
2

在我的工作中,我们将一个参数传递给 TestInitialize 方法以确定我们希望初始化如何工作。

public partial class CommonActions
{
   public void TestInitialize(bool adminTest)
   {
      try
      {
         if (adminTest)
         {
            //do stuff
         } 

然后我们在类定义中有一个标准的初始化,默认为 false。

[TestClass]
public class ProjectTestBase : FrameworkTestBase
{ 
  public CommonActions common { get; set; } = new CommonActions();

  [TestInitialize]
   public void TestInitialize() => common.TestInitialize(false);

然后在测试用例本身中,您可以为您想要的任何测试覆盖 TestInitialize。

[TestClass]
public class SetReportsInAdmin : ProjectTestBase
{
    [TestInitialize]
    public new void TestInitialize() => common.TestInitialize(true);

我们使用布尔值来判断是否需要进行管理员测试,这需要额外的设置开销。采取这个并应用您想要的任何变量,通过使用一种方法为您提供多个初始化。

于 2017-03-21T14:49:11.297 回答