2012-01-27 5 views
5

Chcę je zgłosić przed ich uruchomieniem i mieć opcję uruchamiania indywidualnych testów za pomocą skryptów powłoki bez zarządzania kategoriami. Mamy niezarządzany kod, który może pozostawić proces w złym stanie, a czasami z przyjemnością przeprowadzimy każdy test indywidualnie na każdym uruchomieniu konsoli.Czy nunit-console może wyświetlać wszystkie nazwy testowe w urządzeniu testowym?

+0

'nunit-konsola MyAssembly.dll/labels' pokaże wszystkie testy, jak biegać, ale mam rację sądząc, że to, co chcesz, aby ta najpierw wyświetlić listę, a następnie zapytać użytkownika (lub dodać do pliku '/ runlist =')? A jakie są powody, dla których nie chcesz używać kategorii? – ClickRick

+0

Chcemy ich z wyprzedzeniem, poprawne. Kluczem było to, że chcieliśmy uruchamiać je po jednym na raz, tzn. Uruchamiać konsolę nunitową raz po raz, raz na test. Zmieniliśmy składniki tak, że nie musimy już tego robić, ale wciąż jestem zaskoczony, że nie widzę na nie odpowiedzi. –

+0

Gdyby to nadal stanowiło problem, byłbym skłonny spojrzeć na użycie ich klasy EventListener (zobacz http://imistaken.blogspot.co.uk/2009/03/nunit-extensions-adding-logic-at-run .html na przykład), aby sprawdzić, czy można uzyskać tę listę w ten sposób, ale polegałoby to na możliwości stłumienia rzeczywistego przebiegu testów w tym miejscu, a tego nie wiem bez próby. – ClickRick

Odpowiedz

0

Konsola nunitowa nadal nie obsługuje tej opcji. Jest jednak dość proste, aby uzyskać listę przypadków testowych za pomocą refleksji. Na bardzo podstawowym poziomie, chcesz listę wszystkich public metod dowolnego public class z odpowiednimi atrybutami [Test]/[TestFixture]. W zależności od struktury, w której przeprowadzane są testy, może być konieczne dodatkowe filtrowanie, takie jak usunięcie testów oznaczonych atrybutami [Ignore] lub rozważenie metod testowania w klasach bazowych.

Na poziomie podstawowym, kod będzie wyglądał tak:

// 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); 
    } 
} 

Oczywiście, że można usprawnić ten kawałek, jeśli tylko chciał metod testowych z określonego TestFixture.

Jak już powiedziano w komentarzach, robi się to nieco bardziej skomplikowane, jeśli trzeba zwrócić uwagę na inne atrybuty NUnit, takie jak TestCase i TestCaseSource. Zmodyfikowałem poniższy kod, aby obsługiwać niektóre funkcje tych atrybutów.

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); 
} 

Jeśli spojrzeć poprzez kod powyżej, można zauważyć, że mam obsługiwane funkcjonalności gdzie TestCaseSource do testów to ciąg nazewnictwa nieruchomość/Metoda/pole. Zauważysz także, że chociaż jest więcej kodu, nadal jest to dość prosty kod, więc można go łatwo rozszerzyć, jeśli używasz alternatywnej wersji TestCaseSource, lub jeśli są inne atrybuty NUnit, których używasz, nie pokrywane.

Łatwo też dodać licznik do powyższego, aby mieć poziom komfortu, na którym wydrukowano tę samą liczbę testów, co liczba testów, które byłyby uruchomione.

+0

To dostanie podstawy, ale jeśli użyjesz niektórych bardziej zaawansowanych atrybutów, które automatycznie generują testy z różnych wejść, to masz pecha! –

+0

@SebastianGood Dodałem wsparcie dla TestCase + niektórych permutacji TestCaseSource do powyższych. Rozszerzenie kodu na obsługę innych opcji TestCaseSource (lub innych atrybutów, których nie znalazłem) powinno być proste, jeśli korzystasz z alternatywnych, jednak pozostawię to jako ćwiczenie * dla czytelnika *. – forsvarir

+0

Należy również wziąć pod uwagę przypadki, w których klasy testowe dziedziczą z (abstrakcyjnych) klas bazowych z tymi atrybutami. Następnie należy dostosować liczbę do wielokrotnego uruchamiania tych samych metod testowych, – WebDancer

Powiązane problemy