26

Using Xunit, how can I get the name of the currently running test?

  public class TestWithCommonSetupAndTearDown : IDisposable
  {
    public TestWithCommonSetupAndTearDown ()
    {
      var nameOfRunningTest = "TODO";
      Console.WriteLine ("Setup for test '{0}.'", nameOfRunningTest);
    }

    [Fact]
    public void Blub ()
    {
    }

    public void Dispose ()
    {
      var nameOfRunningTest = "TODO";
      Console.WriteLine ("TearDown for test '{0}.'", nameOfRunningTest);
    }
  }

Edit:
In particular, I am looking for a replacement for NUnits TestContext.CurrentContext.Test.Name property.

Julian Lettner
  • 3,309
  • 7
  • 32
  • 49

3 Answers3

24

You can use BeforeAfterTestAttribute to resolve your case. There are some ways to address your issue using Xunit, which would be to make sub-class of TestClassCommand, or FactAttribute and TestCommand, but I think that BeforeAfterTestAttribute is the simplest way. Check out the code below.

public class TestWithCommonSetupAndTearDown
{
    [Fact]
    [DisplayTestMethodName]
    public void Blub()
    {
    }

    private class DisplayTestMethodNameAttribute : BeforeAfterTestAttribute
    {
        public override void Before(MethodInfo methodUnderTest)
        {
            var nameOfRunningTest = "TODO";
            Console.WriteLine("Setup for test '{0}.'", methodUnderTest.Name);
        }

        public override void After(MethodInfo methodUnderTest)
        {
            var nameOfRunningTest = "TODO";
            Console.WriteLine("TearDown for test '{0}.'", methodUnderTest.Name);
        }
    }
}
Adam Ralph
  • 29,453
  • 4
  • 60
  • 67
Jin-Wook Chung
  • 4,196
  • 1
  • 26
  • 45
  • 2
    Worked for me. The attribute can be applied to the class to run for all test methods in the class. – Tom May 01 '20 at 18:15
8

See a similar question in Github where the answer/workaround is to use some injection and reflection in the constructor.

public class Tests
  {
  public Tests(ITestOutputHelper output)
    {
    var type = output.GetType();
    var testMember = type.GetField("test", BindingFlags.Instance | BindingFlags.NonPublic);
    var test = (ITest)testMember.GetValue(output);
    }
<...>
  }
LosManos
  • 7,195
  • 6
  • 56
  • 107
1

I can't speak to xUnit ... but this did work for me in VS Testing. might be worth a shot.

Reference: How to get the name of the current method from code

Example:

[TestMethod]
public void TestGetMethod()
{
    StackTrace st = new StackTrace();
    StackFrame sf = st.GetFrame(0);
    MethodBase currentMethodName = sf.GetMethod();
    Assert.IsTrue(currentMethodName.ToString().Contains("TestGetMethod"));
 }
Community
  • 1
  • 1
urbanlemur
  • 102
  • 1
  • 4
  • Thank you for your answer. I am aware of this option (using it right now) and looking for another option. – Julian Lettner May 11 '13 at 01:12
  • 1
    Not sure it existed at the time of this answer but, if you're using MSTest, you can rely on an instance of TestContext in your test class that will be automatically set my the test runner giving you the running test name and more. – ChiefTwoPencils Oct 09 '19 at 00:53