Zamówienie uruchomienia testowego NUnit


110

Domyślnie testy nunit są uruchamiane alfabetycznie. Czy ktoś zna jakiś sposób na ustawienie zlecenia wykonania? Czy istnieje dla tego atrybut?


7
Dlaczego chcesz to zrobić? Wygląda na to, że masz zależność od kolejności uruchamiania, co jest złe. Musisz ponownie przemyśleć, dlaczego tego chcesz. Testy jednostkowe powinny działać w izolacji i być całkowicie niezależne od innych. Wygląda na to, że tworzysz kandydatów do testu zapachowego Erratic Tests .
RichardOD

To wygląda na duplikat, ale możesz zobaczyć moją odpowiedź tutaj
Johnno Nolan.

12
@RichardOD - powinien! = Musi. I tak naprawdę nie jest to konieczne, ponieważ w rzeczywistości prawie wszystkie testy integracyjne są uruchamiane po kolei - zapytaj zespół ds. Kontroli jakości, czy losuje kolejność testów.
tymtam,

4
Obecnie mam kilka testów, których kolejność wydaje się mieć znaczenie, chociaż nie powinna. Osobiście chciałbym mieć sposób na losowanie kolejności testów, aby pomóc mi upewnić się, że moje testy NIE są w jakiś sposób zależne od kolejności. Oczywiście, NAPRAWDĘ chciałbym, żeby tester uruchomił wszystkie moje testy w przypadkowej kolejności, aż znajdzie problem lub powiem stop. Gdybym przebiegł to przez noc, a rano wszystko nadal było zielone, to mógłbym być pewien, że wyeliminowałem ostatnie z niezamierzonych skutków ubocznych.
Mel

1
to pytanie stałoby się bardziej istotne, gdyby zostało zaktualizowane, aby sprecyzować, że mówimy tutaj o testach integracyjnych ... Wszyscy znamy zasady dotyczące testów jednostkowych, przynajmniej jeśli czytałeś wzorce testowe XUnit i śledziłeś wujka Boba itp. robisz ... ale frameworki takie jak NUnit są również bardzo przydatne do szybkiego uruchamiania i uruchamiania testów integracyjnych .. i zdecydowanie nie chcesz, aby były one losowe, zwłaszcza gdy w
grę wchodzi

Odpowiedzi:


51

Twoje testy jednostkowe powinny być w stanie działać niezależnie i samodzielnie. Jeśli spełniają to kryterium, kolejność nie ma znaczenia.

Są jednak sytuacje, w których będziesz chciał najpierw przeprowadzić pewne testy. Typowym przykładem jest sytuacja ciągłej integracji, w której niektóre testy działają dłużej niż inne. Używamy atrybutu category, abyśmy mogli uruchamiać testy wykorzystujące mockowanie przed testami korzystającymi z bazy danych.

tj. umieść to na początku swoich szybkich testów

[Category("QuickTests")]

Jeśli masz testy, które są zależne od pewnych warunków środowiskowych, rozważ atrybuty TestFixtureSetUp i TestFixtureTearDown , które pozwalają oznaczyć metody do wykonania przed i po testach.


2
@Chris, zwykle nie używam tych atrybutów, to jest interesujący wpis na blogu - jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html . Niezła uwaga na temat testów kategorii.
RichardOD

29
Innym przykładem testów zależnych od kolejności jest użycie frameworku nunit do uruchomienia testu integracji ...
Byron Ross,

1
@ByronRoss: Mam tendencję do powiększania testów, kiedy to robię, i opieram się na istniejących testach jednostkowych tak bardzo, jak to możliwe, aby móc napisać mniej testów. Wtedy każdy pełny przebieg może zawieść oddzielnie. Staram się również projektować moje dane tak, aby mogły istnieć oddzielnie od istniejących danych, a nie w zależności od istniejących danych.
Merlyn Morgan-Graham

1
Jeśli nie uruchamiasz testów w przypadkowej kolejności, jak możesz sprawdzić, czy faktycznie działają, gdy się skończą? To, co mówisz, jest analogiczne do powiedzenia „Jeśli twoje oprogramowanie nie ma błędów, testowanie jest zbędne”.
jforberg,

@jforberg: Jeśli masz awarię, która pojawia się losowo, jak powiesz, kiedy ją naprawiłeś?
NeedHack

175

Chcę tylko zaznaczyć, że chociaż większość respondentów zakładała, że ​​są to testy jednostkowe, w pytaniu nie określono, że tak.

nUnit to świetne narzędzie, którego można używać w różnych sytuacjach testowych. Widzę odpowiednie powody, dla których chcę kontrolować zlecenie testowe.

W takich sytuacjach musiałem uciec się do włączenia kolejności uruchamiania do nazwy testu. Byłoby wspaniale móc określić kolejność uruchamiania za pomocą atrybutu.


Masz na myśli na przykład wywołanie swoich testów 001_first_test 002_second_testi tak dalej?
popioły 999

Tak, zgadza się, chociaż zazwyczaj używam wzorca, który pozwala mi łatwo wstawiać testy w razie potrzeby, więc może 010_first_test, 020_second_test itp.
Les

83
Dziękuję za jedyną rozsądną odpowiedź. To jest specyficzne pytanie, ale jakoś niejasne, pedantyczne odpowiedzi są popierane. Tak, wszyscy wiemy, jakie powinny być testy jednostkowe, ale to nie jest pytanie.
Egor Pavlikhin,

1
Należy nie polegać na kolejności wykonywania będącego alfabetyczna. Wielu programów uruchamiających testy wykonuje testy jednocześnie w wielu wątkach lub procesach i niekoniecznie w kolejności alfabetycznej. Na przykład NCrunch nadaje priorytet testom na podstawie kodu, który zmienisz (testy, których to dotyczy), następnie na podstawie tego, czy ostatnio zakończyły się niepowodzeniem, a następnie na podstawie tego, czy przebiegają szybko, czy wolno. Jeśli chcesz mieć zdefiniowaną kolejność , po prostu utwórz meta-runner dla tych testów i wyklucz je ze zwykłych uruchomień.
Abel

3
Innym dobrym powodem do określenia kolejności jest wyłapanie pewnych problemów przed kontynuowaniem pracy z resztą zestawu testów. innymi słowy, jeśli mój test tworzenia użytkownika nie powiedzie się, nie potrzebuję wszystkiego innego do uruchomienia, zanim znajdę ten wynik. W moim innym teście prawdopodobnie kpię z użytkownika, ale ważne jest dla mnie, aby był to pierwszy test, który zakończy się niepowodzeniem - szczególnie gdy zestaw testów jest duży.
Bron Davies

125

Dodano NUnit 3.2.0 OrderAttribute, patrz:

https://github.com/nunit/docs/wiki/Order-Attribute

Przykład:

public class MyFixture
{
    [Test, Order(1)]
    public void TestA() { ... }


    [Test, Order(2)]
    public void TestB() { ... }

    [Test]
    public void TestC() { ... }
}

5
Dzięki, od razu to, czego szukałem - i żadnych dyskusji, dlaczego jest dobrze lub źle :)
aknoepfel

1
A potem robią z niego liczbę całkowitą zamiast dziesiętną, więc jeśli trzeba wstawić test, wszystkie testy muszą zostać ponownie ponumerowane.
epitka

Zawsze możesz zacząć od bardzo dużych liczb, takich jak miliony lub coś podobnego, jeśli chcesz w ten sposób wprowadzić elementy środkowe - po prostu więcej pisania. Imo, powinien istnieć łatwiejszy sposób porządkowania rzeczy niż używanie liczb dla priorytetów, takich jak drzewo zależności metod, ale każda z nich ma swoje własne dys / zalety.
Răzvan Flavius ​​Panda

9
Dobra odpowiedź, ale uwaga, dokumentacja stwierdza, że ​​testy nie czekają na zakończenie poprzednich testów.
ROX

Co ciekawe, z mojego doświadczenia, jeśli dodamy osobno atrybuty Test i Order, nie ma gwarancji, że testy zostaną uporządkowane.
AT

22

Chęć uruchomienia testów w określonej kolejności nie oznacza, że ​​testy są od siebie zależne - w tej chwili pracuję nad projektem TDD, a będąc dobrym TDDer, wyszydziłem / zakopałem wszystko, ale to sprawi, że byłoby bardziej czytelne, gdybym mógł określić kolejność, w jakiej wyświetlane są wyniki testów - tematycznie zamiast alfabetycznie. Jak dotąd jedyne, o czym przychodzi mi do głowy, to dołączanie a_ b_ c_ do klas do klas, przestrzeni nazw i metod. (Niezbyt przyjemne) Myślę, że atrybut [TestOrderAttribute] byłby fajny - nie jest ściśle powiązany z ramą, ale podpowiedź, abyśmy mogli to osiągnąć


10

Niezależnie od tego, czy testy są zależne od kolejności, niektórzy z nas chcą po prostu kontrolować wszystko w uporządkowany sposób.

Testy jednostkowe są zwykle tworzone w kolejności złożoności. Dlaczego więc nie miałyby być również uruchamiane według stopnia złożoności lub kolejności, w jakiej zostały utworzone?

Osobiście lubię widzieć testy uruchamiane w kolejności, w jakiej je utworzyłem. W TDD każdy kolejny test będzie naturalnie bardziej złożony i jego wykonanie zajmie więcej czasu. Wolałbym, aby prostszy test zakończył się niepowodzeniem jako pierwszy, ponieważ będzie to lepszy wskaźnik co do przyczyny niepowodzenia.

Ale widzę również korzyści płynące z uruchamiania ich w losowej kolejności, zwłaszcza jeśli chcesz sprawdzić, czy Twoje testy nie mają żadnych zależności od innych testów. Co powiesz na dodanie opcji testowania biegaczy do „Uruchom testy losowo do zatrzymania”?


9

Testuję z Selenium na dość złożonej witrynie internetowej, a cały zestaw testów może trwać dłużej niż pół godziny, a nie jestem jeszcze bliski pokrycia całej aplikacji. Jeśli muszę upewnić się, że wszystkie poprzednie formularze są poprawnie wypełnione dla każdego testu, dodaje to dużo czasu, a nie tylko niewielką ilość czasu do całego testu. Jeśli przeprowadzenie testów jest zbyt duże, ludzie nie będą ich uruchamiać tak często, jak powinni.

Więc uporządkowałem je i zależę od poprzednich testów, aby mieć pola tekstowe i takie wypełnione. Używam Assert.Ignore (), gdy warunki wstępne są nieprawidłowe, ale muszę je uruchomić w porządku.


1
Całkowicie. Jestem na tej samej łodzi.
Sleeper Smith

Ja też! Dokładnie dlaczego trafiłem na to pytanie!
Niklas Wulff

@NiklasRingdahl, jeśli używasz Visual Studio z nunit, zrzuć nunit i użyj testów MS. następnie możesz wykorzystać zamówiony plik testowy Visual Studio, aby uporządkować przypadki testowe w kolejności, w jakiej chcesz je wykonać
Rahul Lodha,

@RahulLodha Thanks! Przyjrzę się temu.
Niklas Wulff

9

Bardzo podoba mi się poprzednia odpowiedź.

Zmieniłem to trochę, aby móc użyć atrybutu do ustawienia zakresu zamówienia:

namespace SmiMobile.Web.Selenium.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using NUnit.Framework;

    public class OrderedTestAttribute : Attribute
    {
        public int Order { get; set; }


        public OrderedTestAttribute(int order)
        {
            Order = order;
        }
    }

    public class TestStructure
    {
        public Action Test;
    }

    class Int
    {
        public int I;
    }

    [TestFixture]
    public class ControllingTestOrder
    {
        private static readonly Int MyInt = new Int();

        [TestFixtureSetUp]
        public void SetUp()
        {
            MyInt.I = 0;
        }

        [OrderedTest(0)]
        public void Test0()
        {
            Console.WriteLine("This is test zero");
            Assert.That(MyInt.I, Is.EqualTo(0));
        }

        [OrderedTest(2)]
        public void ATest0()
        {
            Console.WriteLine("This is test two");
            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
        }


        [OrderedTest(1)]
        public void BTest0()
        {
            Console.WriteLine("This is test one");
            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
        }

        [OrderedTest(3)]
        public void AAA()
        {
            Console.WriteLine("This is test three");
            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
        }


        [TestCaseSource(sourceName: "TestSource")]
        public void MyTest(TestStructure test)
        {
            test.Test();
        }

        public IEnumerable<TestCaseData> TestSource
        {
            get
            {
                var assembly =Assembly.GetExecutingAssembly();
                Dictionary<int, List<MethodInfo>> methods = assembly
                    .GetTypes()
                    .SelectMany(x => x.GetMethods())
                    .Where(y => y.GetCustomAttributes().OfType<OrderedTestAttribute>().Any())
                    .GroupBy(z => z.GetCustomAttribute<OrderedTestAttribute>().Order)
                    .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

                foreach (var order in methods.Keys.OrderBy(x => x))
                {
                    foreach (var methodInfo in methods[order])
                    {
                        MethodInfo info = methodInfo;
                        yield return new TestCaseData(
                            new TestStructure
                                {
                                    Test = () =>
                                        {
                                            object classInstance = Activator.CreateInstance(info.DeclaringType, null);
                                            info.Invoke(classInstance, null);
                                        }
                                }).SetName(methodInfo.Name);
                    }
                }

            }
        }
    }
}

Myślę, że to podejście jest świetne. Zwróć jednak uwagę, że kod odbicia pobierze wszystkie metody z atrybutem, więc jeśli próbujesz uruchomić określone urządzenie testowe, możesz być zaskoczony, gdy zobaczysz, że działa ono częściej niż myślisz. Możesz łatwo zmodyfikować zapytanie LINQ, jeśli nie jest to pożądane zachowanie. Zobacz linki w mojej odpowiedzi, aby uzyskać więcej informacji.
Chrispy

OrderedTestnie jest już obsługiwany w NUnit 3.
Conrad

7

Wiem, że to stosunkowo stary post, ale oto inny sposób na utrzymanie porządku w teście BEZ utrudniania nazw testów. Używając atrybutu TestCaseSource i przekazując obiektowi delegata (Action), możesz całkowicie nie tylko kontrolować kolejność, ale także nazwać test, czym to jest.

Działa to, ponieważ zgodnie z dokumentacją elementy w kolekcji zwrócone ze źródła testowego będą zawsze wykonywane w kolejności, w jakiej są wymienione.

Oto demo z prezentacji, którą wygłoszę jutro:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;

namespace NUnitTest
{
    public class TestStructure
    {
        public Action Test;
    }

    class Int
    {
        public int I;
    }

    [TestFixture]
    public class ControllingTestOrder
    {
        private static readonly Int MyInt= new Int();

        [TestFixtureSetUp]
        public void SetUp()
        {
            MyInt.I = 0;
        }

        [TestCaseSource(sourceName: "TestSource")]
        public void MyTest(TestStructure test)
        {
            test.Test();
        }

        public IEnumerable<TestCaseData> TestSource
        {
            get
            {
                yield return new TestCaseData(
                    new TestStructure
                    {
                        Test = () =>
                        {
                            Console.WriteLine("This is test one");
                            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(1));
                        }
                    }).SetName(@"Test One");
                yield return new TestCaseData(
                    new TestStructure
                    {
                        Test = () =>
                        {
                            Console.WriteLine("This is test two");
                            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(2));
                        }
                    }).SetName(@"Test Two");
                yield return new TestCaseData(
                    new TestStructure
                    {
                        Test = () =>
                        {
                            Console.WriteLine("This is test three");
                            MyInt.I++; Assert.That(MyInt.I, Is.EqualTo(3));
                        }
                    }).SetName(@"Test Three");
            }
        }
    }
}

Używam tego wzorca do równoległych testów integracji, których uruchomienie liniowe byłoby zbyt czasochłonne. Wszystkie testy są jednego typu, więc używam Action <T in>, a każda Action ma klucz, który mówi, co robi „ShouldBeFoo”. W ten sposób to, co robi test, będzie widoczne w nazwie testu, a źródło TestCaseSource można filtrować, dzięki czemu różne typy testów zostaną pogrupowane. Jak na ironię, nie obchodzi mnie zlecenie wykonania, ale zgadzam się, że to zadziała.
Novaterata

Używanie go TestCaseSourcejako sposobu na przeprowadzanie zleconych testów to genialny pomysł. Dobra robota. Zastosowałem to podejście wraz z poniższym i dodałem kilka dodatkowych modyfikacji, aby ułatwić korzystanie z niego. Zobacz linki w mojej odpowiedzi, aby uzyskać dodatkowe informacje, ale podstawowa idea pochodzi z tej wspaniałej odpowiedzi!
Chrispy

Niestety, w przypadku NUnit 3 źródło TestCaseSourcemusi być statyczne, co wyklucza użycie wzorca. Porażka.
Conrad

@Conrad. Nie rozumiem, jaką różnicę robi statyczność metody. Test nadal powraca w kolejności.
Dave Bush

To nie metoda musi być statyczna - źródło (zmienna lub właściwość) TestCaseSourcemusi być statycznym obiektem w NUnit 3, inaczej testy nie zostaną wykonane. Nie możesz tworzyć dynamicznych obiektów w statycznym obiekcie. Dlatego nie zadziała w w. 3.
Conrad

5

Pracuję z kompletnymi przypadkami testowymi UI Selenium WebDriver napisanymi w C #, które są uruchamiane przy użyciu frameworka NUnit. (Nie dotyczy przypadków jednostkowych jako takich)

Te testy interfejsu użytkownika z pewnością zależą od kolejności wykonywania, ponieważ inne testy muszą dodać pewne dane jako warunek wstępny. (Nie jest możliwe wykonanie tych czynności w każdym teście)

Teraz, po dodaniu dziesiątego przypadku testowego, widzę, że NUnit chce działać w tej kolejności: Test_1 Test_10 Test_2 Test_3 ..

Wydaje mi się, że muszę na razie za bardzo ułożyć alfabetycznie nazwy przypadków testowych, ale dobrze byłoby mieć tę małą funkcję kontroli kolejności wykonywania dodaną do NUnit.


9
Nie zgadzam się na aranżację: testy interfejsu użytkownika są z natury sekwencjami małych kroków. Każdy krok powinien być testem (powód - jeśli się nie powiedzie, muszę wiedzieć, który krok). Sekwencje mogą być niezależne, ale w ramach sekwencji kolejność ma znaczenie i konieczne jest zatrzymanie się w przypadku niepowodzenia.
Zasz

3

Zwykle Test jednostkowy powinien być niezależny, ale jeśli musisz, możesz nazwać swoje metody w kolejności alfabetycznej, np .:

[Test]
public void Add_Users(){}

[Test]
public void Add_UsersB(){}

[Test]
public void Process_Users(){}

lub możesz to zrobić ...

        private void Add_Users(){}

        private void Add_UsersB(){}

        [Test]
        public void Process_Users()
        {
           Add_Users();
           Add_UsersB();
           // more code
        }

2
Tylko że teraz nazwy muszą być ułożone alfabetycznie, co jest okropnym rozwiązaniem. :(

@ user166390 - nie, to nie jest okropne. Działa i zależy od udokumentowanego zachowania NUnit.
tymtam,

➕1 wystarczająco dobry dla mnie, znacznie łatwiejszy, jeśli zaczniesz testy od a_ b_ t1_, t2_zamiast tego lub polegasz na łatwych do przeoczenia postaciach końcowych
Chris Marisic

3

Istnieją bardzo dobre powody, aby korzystać z mechanizmu zamawiania testów. Większość moich własnych testów wykorzystuje dobre praktyki, takie jak konfiguracja / porzucenie. Inne wymagają konfiguracji ogromnych ilości danych, które można następnie wykorzystać do przetestowania szeregu funkcji. Do tej pory używałem dużych testów do obsługi tych testów integracji (Selenium Webdriver). Myślę jednak, że powyższy sugerowany post na https://github.com/nunit/docs/wiki/Order-Attribute ma wiele zalet. Oto przykład, dlaczego zamówienie byłoby niezwykle cenne:

  • Użycie Selenium Webdriver do uruchomienia testu w celu pobrania raportu
  • Stan raportu (niezależnie od tego, czy można go pobrać, czy nie) jest zapisywany w pamięci podręcznej 10 minut
  • Oznacza to, że przed każdym testem muszę zresetować stan raportu, a następnie odczekać do 10 minut, zanim stan zostanie potwierdzony, że zmienił się, a następnie zweryfikować, czy raport został pobrany poprawnie.
  • Ze względu na ich złożoność raporty nie mogą być generowane w sposób praktyczny / terminowy poprzez mockowanie ani żaden inny mechanizm w ramach testów.

Ten 10-minutowy czas oczekiwania spowalnia zestaw testów. Mnożenie podobnych opóźnień w pamięci podręcznej w wielu testach zajmuje dużo czasu. Zamawianie testów może pozwolić na konfigurację danych jako „test” na początku zestawu testów, przy czym testy polegające na pamięci podręcznej są wykonywane pod koniec przebiegu testu.


2

To pytanie jest teraz naprawdę stare, ale dla osób, które mogą dotrzeć do tego z wyszukiwania, wziąłem doskonałe odpowiedzi od user3275462 i PvtVandals / Rico i dodałem je do repozytorium GitHub wraz z niektórymi własnymi aktualizacjami. Utworzyłem również powiązany wpis na blogu z dodatkowymi informacjami, na które możesz spojrzeć, aby uzyskać więcej informacji.

Mam nadzieję, że jest to pomocne dla wszystkich. Ponadto często lubię używać atrybutu Category, aby odróżnić moje testy integracyjne lub inne testy kompleksowe od rzeczywistych testów jednostkowych. Inni zwrócili uwagę, że testy jednostkowe nie powinny mieć zależności od kolejności, ale inne typy testów często mają, więc zapewnia to dobry sposób na uruchamianie tylko wybranej kategorii testów, a także zamawianie tych testów od końca do końca.


czy możesz mi pomóc z problemem, który mam, tutaj jest link: stackoverflow.com/questions/31281395/…
Morgan Soren

1

Jestem zaskoczony, że społeczność NUnit niczego nie wymyśliła, więc sam postanowiłem stworzyć coś takiego.

Obecnie rozwijam bibliotekę open source która umożliwia zamawianie testów w NUnit. Można zamawiać oprawy testowe i zamawiać „zamówione specyfikacje testów”.

Biblioteka oferuje następujące funkcje:

  • Twórz złożone hierarchie kolejności testów
  • Pomiń kolejne testy, jeśli test w kolejności zakończy się niepowodzeniem
  • Sortuj metody testowe według zależności zamiast kolejności liczb całkowitych
  • Obsługuje użytkowanie obok siebie z nieuporządkowanymi testami. Nieuporządkowane testy są wykonywane jako pierwsze.

Biblioteka jest właściwie zainspirowana sposobem, w jaki MSTest testuje porządkowanie .orderedtestplików. Spójrz na poniższy przykład.

[OrderedTestFixture]
public sealed class MyOrderedTestFixture : TestOrderingSpecification {
    protected override void DefineTestOrdering() {
        TestFixture<Fixture1>();

        OrderedTestSpecification<MyOtherOrderedTestFixture>();

        TestFixture<Fixture2>();
        TestFixture<Fixture3>();
    }

    protected override bool ContinueOnError => false; // Or true, if you want to continue even if a child test fails
}

1

Jeśli używasz [TestCase], argument TestNamezawiera nazwę testu.

Jeśli nie zostanie określony, nazwa jest generowana na podstawie nazwy metody i podanych argumentów.

Możesz kontrolować kolejność wykonywania testów, jak podano poniżej:

                    [Test]
            [TestCase("value1", TestName = "ExpressionTest_1")]
            [TestCase("value2", TestName = "ExpressionTest_2")]
            [TestCase("value3", TestName = "ExpressionTest_3")]
            public void ExpressionTest(string  v)
            {
                //do your stuff
            }

Tutaj użyłem "ExpressionTest"przyrostka nazwy metody z liczbą.

Możesz użyć dowolnych nazw uporządkowanych alfabetycznie, zobacz TestCase Attribute


0

Nie należy polegać na kolejności, w jakiej środowisko testów wybiera testy do wykonania.Testy powinny być izolowane i niezależne. Nie powinni polegać na jakimś innym teście przygotowującym dla nich scenę lub sprzątającym po nich. Powinny też dawać ten sam wynik niezależnie od kolejności wykonywania testów (dla danej migawki SUT)

Trochę googlowałem. Jak zwykle, niektórzy ludzie uciekają się do podstępnych sztuczek (zamiast rozwiązywać podstawowy problem z testowalnością / projektem

  • nazwanie testów w kolejności alfabetycznej, tak aby testy pojawiały się w kolejności, w jakiej „muszą” zostać wykonane. Jednak NUnit może zdecydować się na zmianę tego zachowania w późniejszej wersji, a następnie testy zostaną zakończone. Lepiej sprawdź bieżące pliki binarne NUnit w kontroli źródła.
  • VS (IMHO zachęcające do niewłaściwego zachowania swoimi „narzędziami zwinnymi”) ma coś, co nazywa się „Zamówionymi testami” w ich ramach testów MS. Nie traciłem czasu na czytanie, ale wydaje się, że jest skierowany do tej samej publiczności

Zobacz także: cechy dobrego testu


Są sytuacje, w których chciałbyś, aby szybciej działające testy były wykonywane przed długotrwałymi testami, szczególnie w testach integracyjnych i akceptacyjnych. Na przykład w aplikacji do blogowania: najpierw testujesz logowanie, ponieważ jeśli ta funkcja nie działa, wysyłanie również nie będzie działać, więc nie ma sensu wykonywać tego testu (możesz zatrzymać runner ręcznie). Ale jeśli spróbujesz kontynuować testy, zajmie to więcej czasu.
Marcel Valdez Orozco

@MarcelValdezOrozco - możesz osiągnąć ten cel, dzieląc testy na różne fizyczne biblioteki DLL lub używając tagów / kategorii. Możesz tworzyć skrypty kompilacji, aby uruchamiać biblioteki DLL / kategorie w kolejności. Ogólnie rzecz biorąc, zezwolenie na porządkowanie testów prowadzi zwykle do testów sprzężonych, które rozwijają zależności od sąsiednich testów (oczywiście w czasie). AFAIR w kolejnym dużym wydaniu NUnit, będzie obsługiwał inną kolejność testów, np. Losowe itp.
Gishu

2
Dalsze dzielenie na partycje tego samego typu testów (na przykład testów akceptacyjnych) nie ma sensu, a rozdzielenie ich na inną bibliotekę DLL niepotrzebnie zwiększa złożoność wszędzie: kod źródłowy, skrypty budowania, skrypty testowe, strukturę projektu itp. testy.
Marcel Valdez Orozco

Emitowanie (a więc w zasadzie wszystkie kpiące biblioteki) są powodem, dla którego porządek byłby ważny. Nie możesz zwolnić domeny aplikacji, a moduł uruchamiający nunit (jeśli uruchomisz wszystkie testy w zestawie) zachowuje tę domenę dla wszystkich testów przynajmniej w tym `` rozwiązaniu ''. Jeśli jeden test tworzy typy do testowania, a inny test powoduje konflikt z tym utworzonym typem z powodu kolejności, nie jest to błędny test. Są logicznie izolowane, po prostu nUnit nie zapewnia właściwej izolacji między samymi „testami”.
Kelly Elton

6
Jest to dość protekcjonalna odpowiedź i sprawia, że ​​jest zabawna, ponieważ tak naprawdę dotyczy tylko testów jednostkowych i całkowicie ignoruje pragmatyzm.
tymtam,

0

W przypadku użycia TestCaseSourceklucza to override string ToStringmetoda, jak to działa:

Załóżmy, że masz klasę TestCase

public class TestCase
{
    public string Name { get; set; }
    public int Input { get; set; }
    public int Expected { get; set; }
}

I lista przypadków testowych:

private static IEnumerable<TestCase> TestSource()
{
    return new List<TestCase>
    {
        new TestCase()
        {
           Name = "Test 1",
           Input = 2,
           Expected = 4
        },
        new TestCase()
        {
            Name = "Test 2",
            Input = 4,
            Expected = 16
        },
        new TestCase()
        {
            Name = "Test 3",
            Input = 10,
            Expected = 100
        }
    };
}

Teraz użyjmy go z metodą testową i zobaczmy, co się stanie:

[TestCaseSource(nameof(TestSource))]
public void MethodXTest(TestCase testCase)
{
    var x = Power(testCase.Input);
    x.ShouldBe(testCase.Expected);
}

To nie będzie testowane w kolejności, a wynik będzie taki:

wprowadź opis obrazu tutaj

Więc jeśli dodaliśmy override string ToStringdo naszej klasy:

public class TestCase
{
    public string Name { get; set; }
    public int Input { get; set; }
    public int Expected { get; set; }

    public override string ToString()
    {
        return Name;
    }
}

Wynik ulegnie zmianie i otrzymamy kolejność i nazwę testu:

wprowadź opis obrazu tutaj

Uwaga:

  1. To jest tylko przykład ilustrujący, jak uzyskać nazwę i kolejność w teście, kolejność jest brana numerycznie / alfabetycznie, więc jeśli masz więcej niż dziesięć testów, sugeruję wykonanie testu 01, testu 02 ... testu 10, testu 11 itd., Ponieważ jeśli wykonasz test 1, a w pewnym momencie test 10, a kolejność będzie testem 1, testem 10, testem 2… itd.
  2. Dane wejściowe i oczekiwane mogą być dowolnym typem, ciągiem, obiektem lub klasą niestandardową.
  3. Oprócz porządku, dobrą rzeczą jest to, że widzisz nazwę testu, która jest ważniejsza.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.