2012-05-22 64 views
8

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

参考:

  1. VS Team Test: .Net Unit Testing with Excel as Data Source: Adapter Failed

  2. How to create Startup and Cleanup script for Visual Studio Test Project?

  3. VS 2010 Load Tests Results with custom counters

  4. How to log unit test entry and leave in MSTest

  5. Can a unit test project load the target application's app.config file?

回答

18

根据MSDNTestInitializeAttribute

  • 不能使用超过一次(=的AllowMultiple假)和
  • 不能被继承来创建自己的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 
    } 
} 
+1

谢谢。这似乎是可行的。人们遵循的标准做法是什么? – Lijo

+0

这是我的团队遵循的做法。我不知道是否还有另一种更好的方法:) – Schaliasos

+5

'AllowMultiple = false'只在同一元素中强制执行单个用法......这意味着单个方法不能用多个'TestInitializeAttribute'标记。它不能用于不同方法的规则与'AllowMultiple = false'无关。 –

3

如果他们需要三个独立的inits;那么他们可能应该在三个独立的灯具,每个都有自己的init!

+0

Schaliasos建议上述方法。这应该没问题。你有没有看到缺点? – Lijo

+2

不,不是。只要三个测试在逻辑上相关。我个人......我将它分成三个装置,但这是个人喜好的事情。上面看起来很好。之后你还需要做测试清理吗?可以使用相同的方法吗? –

11

如果你有三个测试方法,并每种方法都有其自身的初始化步骤,那么为什么你感动初始化到每次测试之前都会运行的方法?我看到的唯一好处就是那个不错的开关块,它在源文件中添加了一些行。但是它给你带来了缺点 - 在这些测试方法的任何一个上看,你不能真正知道在哪个上下文方法将被执行。所以,我使用初始化方法来设置只有基础上下文,这是所有测试夹具真正使用的。

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

如果您有几种使用公共上下文的方法,那么只需提取方法,它将为它们设置上下文,并在arrange部分调用它。您还可以将每个上下文设置分割为几个步骤,并重复使用这些步骤(例如在Given-When-Then工具(例如Specflow)中完成)。

而且,当然,创建不同的灯具也是选项。

+1

在通过集成测试进行负载测试的范围内(例如在加载测试WCF服务层的情况下),您希望测试方法尽可能干净,因为测试方法执行时间是要跟踪的内容。这是一个明确的例子,移动所有初始化逻辑来测试初始化​​是唯一的方法! –

+1

@DavidRodrigues不仅。您可以为正在测试的每个功能创建单独的TestFixture类。这将是非常简单的,它的SetUp方法将不会有任何开关块。另外,我会用SpecFlow等东西进行验收测试。有很好的给定的方法,很好地组织,可以重复使用。 SpecFlow将所有步骤执行时间写入输出窗口 –

4

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

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

我们使用布尔值来判断Admin测试是否需要额外的安装开销。以这种方式应用所需的任何变量,并通过使用一种方法为您提供多个初始化。