ChaseMedallion
ChaseMedallion

Reputation: 21756

How can I get access to the current test method in NUnit

TestContext.CurrentContext.Test has several properties like FullName which can be parsed to get the current test method within NUnit. However, these don't help at all when the test's name is overridden using the TestName property on the TestCase attribute.

Is there a simple way to get the MethodInfo for the current test method from within an NUnit test? I can't simply use a stack trace, because I need this information in SetUp and TearDown when the test method is not on the stack.

I'm using NUnit 2.6.2

Upvotes: 2

Views: 1046

Answers (3)

Paul
Paul

Reputation: 1264

In NUnit 3 (not sure about the older 2.x.y versions), there is a MethodName property in the TestAdapter class TestContext.CurrentContext.Test.MethodName, that contains the original method name.

If I need to pass more information to my tests, especially for conditional setup, I'm using properties:

[Test, Property("SpecialTest", 1)]
public void MySpecialTest() {}

in conjunction with two little extension methods:

internal static class TestExtensions
{
    public static bool TestHasProperty(this TestContext context, string propName) => context.Test.HasProperty(propName);

    public static bool HasProperty(this TestAdapter test, string propName) => test.Properties.ContainsKey(propName);
}

Then I set it up accordingly:

[SetUp]
public void SetupEachTest()
{
    if (TestContext.CurrentContext.TestHasProperty("SpecialTest"))
    {
        DoSpecialSetup();
    }
}

Upvotes: 0

TarmoPikaro
TarmoPikaro

Reputation: 5223

NUnit by default does not provide such information - but it can be queries via private fields and properties. Following code could be used for example (Tested with NUnit 3.13.2):

    /// <summary>
    /// Accesses private class type via reflection.
    /// </summary>
    /// <param name="_o">input object</param>
    /// <param name="propertyPath">List of properties in one string, comma separated.</param>
    /// <returns>output object</returns>
    object getPrivate(object _o, string propertyPath)
    {
        object o = _o;
        var flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
        
        foreach (var name in propertyPath.Split('.'))
        {
            System.Type type = o.GetType();

            if (char.IsUpper(name[0]))
                o = type.GetProperty(name, flags).GetValue(o);
            else
                o = type.GetField(name, flags).GetValue(o);
        }

        return o;
    }

    [SetUp]
    public void EachSpecSetup()
    {
        var mi = (MemberInfo)getPrivate(TestContext.CurrentContext.Test, "_test.Method.MethodInfo");
        // Alternative method - using Exposed nuget package:
        //dynamic test = Exposed.From(TestContext.CurrentContext.Test)._test;
        //dynamic method = Exposed.From(test)._method;
        FactAttribute attr = mi.GetCustomAttribute<FactAttribute>();
        string path = attr.FilePath;
        string funcName = attr.FunctionName;
    }

Like mentioned in code above it's also possible to use Exposed.From - but main example should be theoretically faster.

Code will throw exception if any field / property is not valid - and this is intentional - use Visual studio watch window to identify type / field / properties.

Upvotes: 0

Dio F
Dio F

Reputation: 2538

One thing that comes to my mind is writing a custom NUnit EventListener addin.

Then you could hook into the runcycle of the test runner and at least on the TestStarted overload you will have the TestName object. This won't have the MethodInfo available directly, but you may get it by playing around with the given properties there.

Good luck!

Upvotes: 0

Related Questions