The Light
The Light

Reputation: 27021

How to get the unit test method name at runtime from within the unit test?

How to get the unit test name from the within unit test?

I have the below method inside a BaseTestFixture Class:

public string GetCallerMethodName()
{
    var stackTrace = new StackTrace();
    StackFrame stackFrame = stackTrace.GetFrame(1);
    MethodBase methodBase = stackFrame.GetMethod();
    return methodBase.Name;
}

My Test Fixture class inherits from the base one:

[TestFixture]
public class WhenRegisteringUser : BaseTestFixture
{
}

and I have the below system test:

[Test]
public void ShouldRegisterThenVerifyEmailThenSignInSuccessfully_WithValidUsersAndSites()
{
    string testMethodName = this.GetCallerMethodName();
    //
}

When I run this from within the Visual Studio, it returns my test method name as expected.

When this runs by TeamCity, instead _InvokeMethodFast() is returned which seems to be a method that TeamCity generates at runtime for its own use.

So how could I get the test method name at runtime?

Upvotes: 32

Views: 27871

Answers (5)

Candide Guevara Marino
Candide Guevara Marino

Reputation: 2352

When using Visual Studio to run your tests if you add a TestContext property in your test class you can get this information easily.

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

    [TestInitialize]
    public void setup()
    {
        logger.Info(" SETUP " + TestContext.TestName);
        // .... //
    }
}

Upvotes: 24

Jay Patel
Jay Patel

Reputation: 19

If you are not using Nunit or any other third party tool. you will not get TestAttribute.

So you can do this to get Test Method name. Use TestMethodAttribute insted of TestAttribute.

    public string GetTestMethodName()
    {
            // for when it runs via Visual Studio locally
            var stackTrace = new StackTrace();
            foreach (var stackFrame in stackTrace.GetFrames())
            {
                MethodBase methodBase = stackFrame.GetMethod();
                Object[] attributes = methodBase.GetCustomAttributes(typeof(TestMethodAttribute), false);
                if (attributes.Length >= 1)
                {
                    return methodBase.Name;
                }
            }
            return "Not called from a test method";
    }

Upvotes: 1

The Light
The Light

Reputation: 27021

Thanks guys; I used a combined approach so it now works in all environments:

public string GetTestMethodName()
{
    try
    {
        // for when it runs via TeamCity
        return TestContext.CurrentContext.Test.Name;
    }
    catch
    {
        // for when it runs via Visual Studio locally
        var stackTrace = new StackTrace(); 
        foreach (var stackFrame in stackTrace.GetFrames())
        {
            MethodBase methodBase = stackFrame.GetMethod();
            Object[] attributes = methodBase.GetCustomAttributes(
                                      typeof(TestAttribute), false); 
            if (attributes.Length >= 1)
            {
                return methodBase.Name;
            }
        }
        return "Not called from a test method";  
    }
}

Upvotes: 7

Michael Lloyd Lee mlk
Michael Lloyd Lee mlk

Reputation: 14661

If you are not using NUnit you can loop over the stack and find the test method:

foreach(var stackFrame in stackTrace.GetFrames()) {
  MethodBase methodBase = stackFrame.GetMethod();
  Object[] attributes = methodBase.GetCustomAttributes(typeof(TestAttribute), false);
  if (attributes.Length >= 1) {
    return methodBase.Name;
  } 
}
return "Not called from a test method";

Upvotes: 7

nemesv
nemesv

Reputation: 139788

If you are using NUnit 2.5.7 / 2.6 you can use the TestContext class:

[Test]
public void ShouldRegisterThenVerifyEmailThenSignInSuccessfully()
{
    string testMethodName = TestContext.CurrentContext.Test.Name;
}

Upvotes: 26

Related Questions