Re: Extending parametrised TestCases

193 views
Skip to first unread message

stan...@gmail.com

unread,
Dec 18, 2012, 11:08:19 AM12/18/12
to nunit-...@googlegroups.com
The previous message was posted unfinished due to misplaced input focus and an accidental "Space" press. Here is the second part:

If I open the DLL in GUI, I observe the following behaviour. Undecorated, it will show two entries under "DemoTest" - one for each TestCase. However, when I use TestCaseBuilder to extend the test, only one entry for "DemoTest" is shown - this, I expect, is the reason for "PArameter count mismatch".

I now tried using EventListener and move the result modification logic to TestFinished() event. However, that failed as I don't have Reflection access to attributes, decorating result.Test parameter.

I also did some more experimenting during the day with the ITestDecorator method and added the following if-statement to Decorate():

            if (test is ParameterizedMethodSuite)
            {
                List<Attribute> tags = Reflect.GetAttributes(member, false).OfType<ITestTag>().Cast<Attribute>().ToList();
                ParameterizedMethodSuite suite = test as ParameterizedMethodSuite;
                ParameterizedMethodSuite outputSuite = null;
               
                foreach (NUnitTestMethod testMethod in suite.Tests)
                {
                    if (outputSuite == null)
                    {
                        outputSuite = new ParameterizedMethodSuite(testMethod.Method);
                        outputSuite.Properties = suite.Properties;
                        outputSuite.Description = suite.Description;
                        outputSuite.Fixture = suite.Fixture;
                        outputSuite.RunState  = suite.RunState;
                    }
                    outputSuite.Add(new TagExtension(testMethod.Method, tags));
                }

                return outputSuite;
            }

Contrary to my hope that I will be extending each method in the ParametrizedMethodSuite, I now also get the same "Parameter count mismatch" error in this approach as well.

So, my question is: What is the proper way of extending [TestCase]'s which end up in ParametrizedMEthodSuite?

stan...@gmail.com

unread,
Dec 28, 2012, 5:52:21 AM12/28/12
to nunit-...@googlegroups.com
After studying NUnit source code in depth, I have finally figured out a way of achieving what I want, albeit in a different way.
As far as I could see, it is impossible to populate ParameterizedMethodSuite with your own test methods, which inherit from NUnitTestMethod as I cannot access private argument constructs in my derived class and thus cannot set them.
I ended up extending ParameterizedMethodSuite and overriding Run() method, with subsequent modification of TestResult returned from base.Run()
For consistency, the class, extending NUnitTestMethod now also overrides Run() method.

In the process, I also discovered an interesting anomaly: TestResult.StackTrace has a setter, while TestResult.Message does not. As I actually needed to modify the message, I was forced to go through the SetResult() method and update everything.

Here is what the final implementation looks like:

    [NUnitAddin(Name = "Custom Tag Attribute Decorator", Description = "Outputs additional information for tests tagged with custom attributes.")]
    public class TagDecorator : ITestDecorator, IAddin
    {
        public Test Decorate(Test test, MemberInfo member)

        {
            List<Attribute> tags = Reflect.GetAttributes(member, false).OfType<ITestTag>().Cast<Attribute>().ToList();
            if (tags.Count == 0)
            {
                return test;
            }

            if (test is NUnitTestMethod)
            {
                return new TestMethodExtension((test as NUnitTestMethod).Method, tags);
            }

            if (test is ParameterizedMethodSuite)
            {

                ParameterizedMethodSuite suite = test as ParameterizedMethodSuite;
                ParameterizedMethodSuiteExtension outputSuite = new ParameterizedMethodSuiteExtension(member as MethodInfo, tags);
                NUnitFramework.ApplyCommonAttributes(member, outputSuite);
                outputSuite.RunState = suite.RunState;
                outputSuite.IgnoreReason = suite.IgnoreReason;


                foreach (NUnitTestMethod testMethod in suite.Tests)
                {
                    outputSuite.Add(testMethod);
                }

                return outputSuite;
            }
           
            return test;
        }

        public bool Install(IExtensionHost host)
        {
            IExtensionPoint testDecorators = host.GetExtensionPoint("TestDecorators");
            if (testDecorators == null)
                return false;

            testDecorators.Install(this);
            return true;
        }
    }


    public static class TagExtensionHandler
    {
        public static void ModifyTestResult(TestResult testResult, List<Attribute> tags)
        {
            StringBuilder message = new StringBuilder();
            message.AppendLine("Related to:");
            foreach (ITestTag taggedAttrib in tags.OfType<ITestTag>().Select(attrib => attrib))
            {
                message.Append("     ");
                message.AppendLine(taggedAttrib.GetInfo());
                message.AppendLine();
            }

            message.AppendLine();
            message.Append(testResult.Message);

            testResult.SetResult(testResult.ResultState, message.ToString(), testResult.StackTrace, testResult.FailureSite);
        }
    }

    public class ParameterizedMethodSuiteExtension : ParameterizedMethodSuite
    {
        private readonly List<Attribute> _tags;
        public ParameterizedMethodSuiteExtension(MethodInfo method, List<Attribute> tags)
            : base(method)
        {
            _tags = tags;
        }

        public override TestResult Run(EventListener listener, ITestFilter filter)
        {
            TestResult result = base.Run(listener, filter);
            foreach (TestResult subResult in result.Results)
            {
                TagExtensionHandler.ModifyTestResult(subResult, _tags);
            }

            return result;
        }
    }

    public class TestMethodExtension : NUnitTestMethod
    {
        private readonly List<Attribute> _tags;
        public TestMethodExtension(MethodInfo methodInfo, List<Attribute> tags)
            : base(methodInfo)
        {
            _tags = tags;
        }

        public override TestResult Run(EventListener listener, ITestFilter filter)
        {
            TestResult result = base.Run(listener, filter);
            TagExtensionHandler.ModifyTestResult(result, _tags);
            return result;
        }
    }


Reply all
Reply to author
Forward
0 new messages