2012-01-27 2 views
5

실행되기 전에보고하고 카테고리를 관리하지 않고 쉘 스크립트를 통해 개별 테스트를 실행할 수있는 옵션이 있습니다. 우리는 프로세스를 나쁜 상태로 남겨 둘 수있는 관리되지 않는 코드를 가지고 있으며 때때로 nunit-console 실행마다 각 테스트를 개별적으로 실행하기도합니다.nunit-console은 테스트 픽스처의 모든 테스트 이름을 나열 할 수 있습니까?

+0

'NUNIT 콘솔 미리 목록을 작성한 다음 사용자에게 프롬프트하거나 (또는'/ runlist ='파일에 추가하십시오)? 카테고리 사용을 원하지 않는 이유는 무엇입니까? – ClickRick

+0

우리는 그들을 미리 원한다. 여기에서 핵심은 한 번에 하나씩 실행하고 싶다는 것입니다. 즉, 테스트 당 한 번씩 nunit-console 자체를 반복해서 실행해야합니다. 우리는 더 이상이 작업을 수행 할 필요가 없도록 구성 요소를 변경했지만 여전히 이에 대한 대답을 보지 않고는 놀랍습니다. –

+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] 특성으로 표시된 테스트를 제거하거나 기본 클래스의 테스트 메서드를 고려하는 등의 추가 필터링을 수행해야 할 수 있습니다. 기본적인 수준에서

이 코드는 다음과 같이 보일 것입니다 : 당신은 단지 특정 TestFixture에서 시험 방법을 원하는 경우
// 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); 
    } 
} 

은 확실히 당신이 조금을 간소화 할 수있을 것입니다.

주석에서 설명한 것처럼및 TestCaseSource과 같은 다른 NUnit 특성에주의해야하는 경우이 작업은 좀 더 복잡해집니다. 이 속성의 일부 기능을 지원하도록 아래 코드를 수정했습니다.

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 

더 많은 정보를 들면 : 그들은 실행하지만, 바로 당신이 원하는 것은 것을 얻을 것입니다 생각에 나는 오전으로하여 MyAssembly.dll/labels` 모든 테스트를 표시합니다 https://github.com/nunit/docs/wiki/Console-Command-Line#description