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