Domyślnie testy nunit są uruchamiane alfabetycznie. Czy ktoś zna jakiś sposób na ustawienie zlecenia wykonania? Czy istnieje dla tego atrybut?
Domyślnie testy nunit są uruchamiane alfabetycznie. Czy ktoś zna jakiś sposób na ustawienie zlecenia wykonania? Czy istnieje dla tego atrybut?
Odpowiedzi:
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.
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.
001_first_test
002_second_test
i tak dalej?
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() { ... }
}
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ąć
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”?
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.
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);
}
}
}
}
}
}
OrderedTest
nie jest już obsługiwany w NUnit 3.
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");
}
}
}
}
TestCaseSource
jako 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!
TestCaseSource
musi być statyczne, co wyklucza użycie wzorca. Porażka.
TestCaseSource
musi 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.
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.
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
}
a_
b_
t1_
, t2_
zamiast tego lub polegasz na łatwych do przeoczenia postaciach końcowych
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:
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.
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.
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:
Biblioteka jest właściwie zainspirowana sposobem, w jaki MSTest testuje porządkowanie .orderedtest
plikó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
}
Jeśli używasz [TestCase]
, argument TestName
zawiera 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
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
Zobacz także: cechy dobrego testu
W przypadku użycia TestCaseSource
klucza to override string ToString
metoda, 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:
Więc jeśli dodaliśmy override string ToString
do 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:
Uwaga: