C# VS团队测试:测试类中有多个测试初始化方法

C# VS团队测试:测试类中有多个测试初始化方法,c#,.net,visual-studio-2010,unit-testing,C#,.net,Visual Studio 2010,Unit Testing,我在TeamTest中有一个名为“MyClassTest”的单元测试项目。这个项目有三种测试方法。每个方法都需要自己的测试初始化步骤。但是当我将TestInitializeAttribute应用于三种初始化方法时,它表示该属性不应被多次使用。那么,在VisualStudioTeamTest中,用于初始化每个测试方法的属性应该是什么 参考: 如果他们需要三个独立的初始化;然后,他们可能会在三个单独的装置中,每个装置都有自己的init 根据TestInitializeAttribute:

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

参考:


  • 如果他们需要三个独立的初始化;然后,他们可能会在三个单独的装置中,每个装置都有自己的init

    根据
    TestInitializeAttribute

    • 不能多次使用(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
        }
    }
    

    如果您有三个测试方法,并且每个方法都有自己的初始化步骤,那么为什么要将初始化移到每个测试之前运行的方法?我看到的唯一好处是漂亮的开关块,它在源文件中添加了一些行。但它给了您一个缺点——查看这些测试方法中的任何一种,您都无法真正判断将在哪个上下文方法中执行。所以,我使用初始化方法只设置基本上下文,该上下文实际上由fixture中的所有测试使用

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

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


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

    这是一篇有点老的文章,但我提出了以下几点,似乎还可以: 首先,定义一个属性类:

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

    在我的工作中,我们传入一个参数来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);
    

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

    谢谢。这似乎是可行的。这是人们遵循的标准实践吗?这是我的团队遵循的实践。我不知道还有没有更好的方法:)
    AllowMultiple=false
    只在同一个元素中强制使用单一用法。。。这意味着单个方法不能标记为多个
    TestInitializeAttribute
    。不能在不同的方法上使用它的规则与
    AllowMultiple=false
    无关。虽然这是可行的,但它的缺点是,如果测试名称被重构,并且魔法字符串没有更新,测试就会中断。为什么初始化不能成为测试“安排”部分的一部分(即,如果多个测试需要相同的初始化,则在测试体或私有方法中)?然后可以从测试中的try..finally块启动清理。我个人这样做,到目前为止效果很好。那应该很好。你看到什么缺点了吗?没有。。不是真的。只要这三个测试在逻辑上是相关的。我个人。。我会把它分成三场比赛,但这是我个人的偏好。上面的看起来不错。之后是否也需要执行测试清理?可以使用相同的方法吗?在通过集成测试进行负载测试的范围内,例如在WCF服务层的负载测试中,您希望测试方法尽可能干净,因为测试方法的执行时间是要跟踪的。在这种情况下,将所有初始化逻辑移动到testinitialize是唯一的方法@戴维德罗德里格斯不仅如此。您可以为正在测试的每个功能创建单独的TestFixture类。这将是非常简单的,它的设置方法将不会有任何开关块。我也会使用SpecFlow之类的东西进行验收测试。有一些很好的方法,它们组织得很好,可以重用。SpecFlow将所有步骤的执行时间写入输出窗口
    [TestClass]
    public class SetReportsInAdmin : ProjectTestBase
    {
        [TestInitialize]
        public new void TestInitialize() => common.TestInitialize(true);