How to get the unit test method name at runtime fr

2019-02-02 06:09发布

问题:

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?

回答1:

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


回答2:

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);
        // .... //
    }
}


回答3:

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


回答4:

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


回答5:

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