8

I have a nunit class library containing test cases. I want to programmatically get a list of all tests in the library, mainly the test names and their test ids. Here is what I have so far:

var runner = new NUnit.Core.RemoteTestRunner();
runner.Load(new NUnit.Core.TestPackage(Request.PhysicalApplicationPath + "bin\\SystemTest.dll"));
var tests = new List<NUnit.Core.TestResult>();
foreach (NUnit.Core.TestResult result in runner.TestResult.Results)
{
    tests.Add(result);
}

The issue is that runner.TestResult is null until you actually run the tests. I obviously don't want to run the tests at this point, I just want to get a list of which tests are in the library. After that, I will give users the ability to select a test and run it individually, passing in the test id to the RemoteTestRunner instance.

So how can I get the list of tests without actually running all of them?

Justin
  • 17,670
  • 38
  • 132
  • 201

3 Answers3

6

You could use reflection to load the assembly and look for all the test attributes. This would give you all the methods that are test methods. The rest is up to you.

Here is an example on msdn about using reflection to get the attributes for a type. http://msdn.microsoft.com/en-us/library/z919e8tw.aspx

Seth Flowers
  • 8,990
  • 2
  • 29
  • 42
  • 2
    +1, however there is a twist: with the TestCaseAttribute you can parametrize a test method, thus turning it into multiple (logical) tests. Nothing that couldn't be handled by reflection, but something to keep in mind. – Christian.K May 23 '12 at 17:09
  • I was thinking about doing this originally, as it would give me the test (function) names, however it wouldn't give me the test ids. As long as I can do a RemoteTestRunner run filtered by test name instead of test id then this should work ok, will check it out. – Justin May 23 '12 at 17:39
  • Unfortunately it seems that I can't filter the RemoteTestRunner by a test name, I need the test id too, so I can't mark this as the correct answer. – Justin May 23 '12 at 18:40
  • @Justin Are the ids always the same? I'm more familiar with MSTest than nUnit. – Seth Flowers May 23 '12 at 18:48
  • That makes it sound like the ids are generated during the test run which sort of answers your question... or invalidates it unfortunately. – Seth Flowers May 23 '12 at 19:02
  • Not necessarily, my guess is they are instantiated on load of the test runner. The question is how to get them before actually doing the run. – Justin May 23 '12 at 19:13
  • Well, you always have the option of looking at the nunit source to determine how they are generated, and if you have options for getting at them. https://launchpad.net/nunitv2 – Seth Flowers May 23 '12 at 19:16
4

Here is the code to retrieve all of the test names out of the test class library assembly:

//load assembly.
            var assembly = Assembly.LoadFile(Request.PhysicalApplicationPath + "bin\\SystemTest.dll");
            //get testfixture classes in assembly.
            var testTypes = from t in assembly.GetTypes()
                let attributes = t.GetCustomAttributes(typeof(NUnit.Framework.TestFixtureAttribute), true)
                where attributes != null && attributes.Length > 0
                orderby t.Name
                    select t;
            foreach (var type in testTypes)
            {
                //get test method in class.
                var testMethods = from m in type.GetMethods()
                                  let attributes = m.GetCustomAttributes(typeof(NUnit.Framework.TestAttribute), true)
                    where attributes != null && attributes.Length > 0
                    orderby m.Name
                    select m;
                foreach (var method in testMethods)
                {
                    tests.Add(method.Name);
                }
            }
Justin
  • 17,670
  • 38
  • 132
  • 201
2

The answer by Justin does not work for me. The following does (retrieves all the method names with a Test attribute):

Assembly assembly = Assembly.LoadFrom("pathToDLL");
foreach (Type type in assembly.GetTypes())
{
    foreach (MethodInfo methodInfo in type.GetMethods())
    {
        var attributes = methodInfo.GetCustomAttributes(true);
        foreach (var attr in attributes)
        {
            if (attr.ToString() == "NUnit.Framework.TestAttribute")
            {
               var methodName = methodInfo.Name;
                // Do stuff.
            }
        }
    }
}
Vagelis Prokopiou
  • 2,285
  • 19
  • 14
  • This works. If you want to get the count of the tests in your current running testclass isstead of the whole dll add the following code: if (TestContext.CurrentContext.Test.ClassName.Contains(type.Name)) {... – Josh Graham Feb 21 '18 at 20:23