2012-01-27 5 views
5

Я хотел бы сообщить о них до их запуска и иметь возможность запускать отдельные тесты с помощью сценариев оболочки без управления категориями. У нас есть неуправляемый код, который может оставить процесс в плохом состоянии, и иногда с удовольствием запускает каждый тест отдельно для запуска nunit-console.Может ли nunit-console перечислить все тестовые имена в тестовом устройстве?

+0

'NUnit-консоль MyAssembly.dll/labels' покажет все тесты, как они работают, но я прав, полагая, что то, что вы хотите получить, что , а затем запросить пользователя (или добавить их в файл '/ runlist =')? И в чем же причина, по которой вы не хотите использовать категории? – ClickRick

+0

Мы хотим их раньше времени, правильно. Ключевым моментом здесь было то, что мы хотели запускать их по одному, т. Е. Запускать nunit-консоль снова и снова, один раз за тест. Мы изменили компоненты таким образом, что нам действительно не нужно это делать больше, но я все еще удивлен тем, что не вижу ответа на это. –

+0

Если это все еще проблема для вас, у меня возникнет соблазн изучить их класс EventListener (см. Http://imistaken.blogspot.co.uk/2009/03/nunit-extensions-adding-logic-at-run .html для примера), чтобы увидеть, можете ли вы получить список таким образом, но это будет полагаться на возможность подавить фактический запуск тестов в этот момент, и это то, что я не знаю, не попробовав его. – ClickRick

ответ

0

nunit-console по-прежнему не поддерживает этот вариант. Однако довольно просто получить список тестовых примеров с использованием отражения. На базовом уровне вам нужен список всех методов public любых public class с соответствующими атрибутами [Test]/[TestFixture]. В зависимости от того, как ваши тесты структурированы, вам может потребоваться дополнительная фильтрация, например, для удаления любых тестов, отмеченных атрибутами [Ignore], или для рассмотрения методов тестирования в базовых классах.

На базовом уровне, код будет выглядеть примерно так:

// Load the assembly containing your fixtures 
Assembly a = Assembly.LoadFrom(assemblyName); 

// Foreach public class that is a TestFixture and not Ignored 
foreach (var c in a.GetTypes() 
        .Where(x=>x.IsPublic 
        && (x.GetCustomAttributes(typeof(NUnit.Framework.TestFixtureAttribute)).Count() > 0) 
        && (x.GetCustomAttributes(typeof(NUnit.Framework.IgnoreAttribute)).Count() ==0))) 
{ 
    // For each public method that is a Test and not Ignored 
    foreach (var m in c.GetMethods() 
         .Where(x=>x.IsPublic 
         && (x.GetCustomAttributes(typeof(NUnit.Framework.TestAttribute)).Count() > 0) 
         && (x.GetCustomAttributes(typeof(NUnit.Framework.IgnoreAttribute)).Count() ==0))) 
    { 
     // Print out the test name 
     Console.WriteLine("{0}.{1}", c.ToString(), m.Name); 
     // Alternately, print out the command line to run test case using nunit-console 
     //Console.WriteLine("nunit-console /run:{0}.{1} {2}", c.ToString(), m.Name, assemblyName); 
    } 
} 

Очевидно, что вы были бы в состоянии упорядочить это немного, если вы только хотели методы испытаний от конкретного TestFixture.

Как уже было сказано в комментариях, это становится немного сложнее, если вам нужно обратить внимание на другие атрибуты NUnit, такие как TestCase и TestCaseSource. Я изменил код ниже, чтобы поддержать некоторые функциональные возможности этих атрибутов.

static void PrintTestNames(string assemblyName) { 
    Assembly assembly = Assembly.LoadFrom(assemblyName); 

    foreach (var fixture in assembly.GetTypes().Where(x => x.IsPublic 
             && (x.GetCustomAttributes(typeof(TestFixtureAttribute)).Count() > 0) 
             && (x.GetCustomAttributes(typeof(IgnoreAttribute)).Count() == 0))) { 
     foreach(var method in fixture.GetMethods().Where(x=>x.IsPublic 
      && (x.GetCustomAttributes(typeof(IgnoreAttribute)).Count() == 0) 
      && ((x.GetCustomAttributes(typeof(TestAttribute)).Count() > 0) 
       || (x.GetCustomAttributes(typeof(TestCaseAttribute)).Count() > 0) 
       || (x.GetCustomAttributes(typeof(TestCaseSourceAttribute)).Count() > 0)) 
      )) { 
      var testAttributes = method.GetCustomAttributes(typeof(TestAttribute)) as IEnumerable<TestAttribute>; 
      var caseAttributes = method.GetCustomAttributes(typeof(TestCaseAttribute)) as IEnumerable<TestCaseAttribute>; 
      var caseSourceAttributes = method.GetCustomAttributes(typeof(TestCaseSourceAttribute)) as IEnumerable<TestCaseSourceAttribute>; 

      if (caseAttributes.Count() > 0) { 
       foreach(var testCase in caseAttributes) { 
        if (!string.IsNullOrEmpty(testCase.TestName)) { 
         PrintTestName(fixture.ToString(), testCase.TestName); 
        } 
        else { 
         string arguments = ExtractArguments(testCase.Arguments); 
         PrintTestName(fixture.ToString(), method.Name + arguments); 
        } 
       } 
      } 
      else if (caseSourceAttributes.Count() > 0) { 
       foreach (var testCase in caseSourceAttributes) { 
        var sourceName = testCase.SourceName; 
        if (!string.IsNullOrEmpty(sourceName)) { 
         var staticMember = fixture.GetField(sourceName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); 
         var instanceMember = fixture.GetField(sourceName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); 
         var staticMethodMember = fixture.GetMethod(sourceName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); 
         var instanceMethodMember = fixture.GetMethod(sourceName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); 
         var staticPropMember = fixture.GetProperty(sourceName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); 
         var instancePropMember = fixture.GetProperty(sourceName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); 


         IEnumerable memberValues; 

         if (null != staticMember) { 
          memberValues = staticMember.GetValue(null) as IEnumerable; 
         } 
         else if (null != instanceMember) { 
          var instance = Activator.CreateInstance(fixture); 
          memberValues = instanceMember.GetValue(instance) as IEnumerable; 
         } else if(null != staticMethodMember) { 
          memberValues = staticMethodMember.Invoke(null,new object [0]) as IEnumerable; 
         } 
         else if (null != instanceMethodMember) { 
          var instance = Activator.CreateInstance(fixture); 
          memberValues = instanceMethodMember.Invoke(instance, new object[0]) as IEnumerable; 
         } 
         else if (null != staticPropMember) { 
          memberValues = staticPropMember.GetValue(null) as IEnumerable; 
         } 
         else if (null != instancePropMember) { 
          var instance = Activator.CreateInstance(fixture); 
          memberValues = instancePropMember.GetValue(instance) as IEnumerable; 
         } 
         else { 
          Console.WriteLine("*** Ooops...Looks like I don't know how to get {0} for fixture {1}", sourceName, fixture.ToString()); 
          continue; 
         } 

         foreach (var memberValue in memberValues) { 
          if (null != memberValue as IEnumerable) { 
           PrintTestName(fixture.ToString(), method.Name + ExtractArguments(memberValue as IEnumerable)); 
          } 
          else { 
           PrintTestName(fixture.ToString(), method.Name + "(" + memberValue.ToString() + ")"); 
          } 
         } 
        } else { 
         Console.WriteLine("*** Ooops...Looks like I don't know how to handle test {0} for fixture {1}", method.Name, fixture.ToString()); 
        } 
       } 
      } 
      else { 
       PrintTestName(fixture.ToString(), method.Name); 
      } 
     } 
    } 
} 

static string ExtractArguments(IEnumerable arguments) { 
    string caseArgs = "("; 
    bool first = true; 
    foreach (var arg in arguments) { 
     if (first) first = false; 
     else caseArgs += ","; 
     caseArgs += Convert.ToString(arg); 
    } 
    return caseArgs + ")"; 
} 

static void PrintTestName(string fixture, string testName) { 
    Console.WriteLine("{0}.{1}", fixture, testName); 
    //Console.WriteLine("nunit-console /run:{0}.{1} {2}", fixture, testName, assemblyName); 
} 

Если посмотреть через код выше, вы можете заметить, что я перевалено функциональность, где TestCaseSource для испытаний является строкой, содержащим названием свойства/метода/поля. Вы также заметите, что в то время как есть код, он по-прежнему довольно простой код, поэтому его можно было бы легко расширить, если вы использовали альтернативную версию TestCaseSource, или если есть другие атрибуты NUnit, которые вы используете, что я не удовлетворяют.

Было бы достаточно просто добавить счетчик выше, чтобы у вас был уровень комфорта, при котором было напечатано столько же тестов, сколько количества тестов, которые будут выполняться с помощью nunit-console.

+0

Это позволит получить основы, но если вы используете некоторые из более продвинутых атрибутов, которые могут автоматически генерировать тесты с разных входов, вам не повезло! –

+0

@SebastianGood Я добавил поддержку TestCase + некоторых подстановок TestCaseSource к вышеперечисленному. Расширение кода для обработки других параметров TestCaseSource (или других атрибутов, которые я не нашел) должно быть простым, если вы используете альтернативные, но я оставлю это как упражнение для читателя *. – forsvarir

+0

Вам также необходимо рассмотреть случаи, когда классы тестов наследуют (абстрактные) базовые классы с этими атрибутами. Затем счет нужно настроить для одновременного использования одних и тех же методов тестирования, – WebDancer

1

В настоящее время имеется опция командной строки --explore, которая может использоваться для перечисления всех тестовых примеров без проведения тестов. Более конкретно

nunit3-console.exe MyProject.dll --explore 

Для получения дополнительной информации: https://github.com/nunit/docs/wiki/Console-Command-Line#description