Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VS Team Test: Multiple Test Initialize Methods in Test Class

I have unit test project called “MyClassTest” in TeamTest. This project has three TestMethods. Each method needs its own test initialization steps. But when I apply TestInitializeAttribute to three initialization methods, it says the attribute should not be used more than once. Then what should be the attribute to be used to initialize each test method in Visual Studio Team Test?

Reference:

  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?

like image 751
LCJ Avatar asked May 22 '12 10:05

LCJ


3 Answers

According to MSDN the TestInitializeAttribute:

  • cannot be used more than once (AllowMultiple = false), and
  • cannot be inherited to create your own TestInitializeAttribute.

So, my suggestion is to create the Test Initialize Methods without the TestInitialize attribute. Then in the unique TestInitialize method check which is the current executed TestMethod and call the appropriate initialize method:

[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
    }
}
like image 104
chaliasos Avatar answered Nov 16 '22 06:11

chaliasos


If you have three test methods, and each method has its own initialization steps, then why are you moving initialization to method which will run before every test? Only benefit I see, is that nice switch block, which adds some lines to your source file. But it gives you drawback - looking on any of these test methods, you can't really tell in which context method will be executed. So, I use initialization method to setup only basic context, which is really used by all tests in fixture.

Just move context creation to arrange part of each method.

If you have several methods, which use common context, then just extract method, which will setup context for them, and call it at the arrange part. You also can split each context setup to several steps and reuse those steps (like it done in Given-When-Then tools like Specflow).

And, of course, creating different fixtures also option.

like image 24
Sergey Berezovskiy Avatar answered Nov 16 '22 04:11

Sergey Berezovskiy


It's a bit of an old post, but I came up with the following which seems to work OK: First, define an attribute class:

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

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

then define an extension method in some convenient utilities class:

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

Now write your tests, thus:

    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
    }
like image 6
Dave Avatar answered Nov 16 '22 05:11

Dave