За замовчуванням тести на нуніти виконують за алфавітом. Хтось знає про будь-який спосіб встановити порядок виконання? Чи існує для цього атрибут?
За замовчуванням тести на нуніти виконують за алфавітом. Хтось знає про будь-який спосіб встановити порядок виконання? Чи існує для цього атрибут?
Відповіді:
Кожен ваш тест повинен мати можливість самостійно працювати і самостійно. Якщо вони задовольняють цьому критерію, то порядок значення не має.
Однак бувають випадки, коли спочатку потрібно запустити певні тести. Типовий приклад - це ситуація безперервної інтеграції, коли деякі тести тривають довше інших. Ми використовуємо атрибут категорії, щоб ми могли запускати тести, які використовують глузування перед тестами, які використовують базу даних.
тобто поставте це на початку ваших швидких тестів
[Category("QuickTests")]
Якщо у вас є тести, які залежать від певних умов навколишнього середовища, врахуйте атрибути TestFixtureSetUp та TestFixtureTearDown , які дозволяють позначити методи, які потрібно виконати до і після тестів.
Я просто хочу зазначити, що хоча більшість опитаних вважали, що це були одиничні тести, у питанні не було вказано, що вони є.
nUnit - чудовий інструмент, який можна використовувати в різних ситуаціях тестування. Я бачу відповідні причини, які хочуть контролювати тестовий порядок.
У таких ситуаціях мені довелося вдатися до включення порядку виконання у назву тесту. Було б чудово, щоб можна було вказати порядок виконання за допомогою атрибута.
001_first_test
002_second_test
тощо?
NUnit 3.2.0 додав OrderAttribute
, див .:
https://github.com/nunit/docs/wiki/Order-Attribute
Приклад:
public class MyFixture
{
[Test, Order(1)]
public void TestA() { ... }
[Test, Order(2)]
public void TestB() { ... }
[Test]
public void TestC() { ... }
}
Бажаючи, щоб тести запускалися в певному порядку, не означає, що тести залежать один від одного - я зараз працюю над проектом TDD, і будучи хорошим TDDer, я все знущався / заглушив, але це зробить він легше читається, якщо я міг би вказати порядок відображення результатів тестів - тематично замість алфавіту. Поки що єдине, про що я можу придумати, - це передати a_ b_ c_ до класів до класів, просторів імен та методів. (Не приємно) Я думаю, що атрибут [TestOrderAttribute] був би непоганим - не суворо дотримувався рамки, а підказки, щоб ми могли досягти цього
Незалежно від того, залежать чи ні тести від порядку ... деякі з нас просто хочуть контролювати все впорядковано.
Одиничні тести, як правило, створюються в порядку складності. Отже, чому б їх також не проводити в порядку складності чи порядку, в якому вони були створені?
Особисто мені подобається бачити тести, які виконуються в тому порядку, в якому я їх створив. У TDD кожен наступний тест, природно, буде складнішим і потребує більше часу для запуску. Я б швидше побачив, що простіший тест провалиться спочатку, оскільки це буде кращим показником щодо причини відмови.
Але я також бачу вигоду від запуску їх у випадковому порядку, особливо якщо ви хочете перевірити, що ваші тести не залежать від інших тестів. Як щодо додавання опції для тестування бігунів до "Виконання тестів випадковим чином до зупинки"?
Я тестую селен на досить складному веб-сайті, і весь набір тестів може тривати більше півгодини, і я ще не в змозі охопити всю програму. Якщо я повинен переконатися, що всі попередні форми правильно заповнені для кожного тесту, це додасть великої кількості часу, а не лише невеликої кількості часу, до загального тесту. Якщо занадто багато накладних витрат на тести, люди не запускатимуть їх так часто, як слід.
Отже, я приводжу їх у порядок і залежать від попередніх тестів, щоб текстові поля та такі були заповнені. Я використовую Assert.Ignore (), коли попередні умови не дійсні, але мені потрібно, щоб вони працювали в порядку.
Мені дуже подобається попередня відповідь.
Я трохи змінив його, щоб мати можливість використовувати атрибут для встановлення діапазону замовлень:
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
більше не підтримується в NUnit 3.
Я знаю, що це відносно стара публікація, але ось ще один спосіб зберегти свій тест для того, щоб БЕЗ робити незрозумілих імен тестів. Використовуючи атрибут TestCaseSource і маючи об’єкт, який ви передаєте, є делегатом (Action), ви можете повністю не тільки контролювати порядок, але і називати тест, яким він є.
Це працює, тому що, згідно з документацією, елементи колекції, повернені з тестового джерела, завжди виконуватимуться в тому порядку, який вони вказані.
Ось демонстрація презентації, яку я даю завтра:
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
як спосіб запуску замовлених тестів є геніальним штрихом. Молодці. Я застосував цей підхід разом із наведеним нижче та додав кілька додаткових модифікацій, щоб полегшити його використання. Дивіться посилання у моїй відповіді для додаткової інформації, але основна ідея - це від цієї чудової відповіді!
TestCaseSource
повинен бути статичним, що виключає використання шаблону. Бампер.
TestCaseSource
має бути статичним об'єктом в NUnit 3, інакше тести не виконуватимуться. І ви не можете створювати динамічні об'єкти в статичному об'єкті. Ось чому це не буде працювати в т. 3.
Я працюю з тестовими випадками UI інтерфейсу Selenium WebDriver, написаними на C #, які виконуються за допомогою NUnit Framework. (Не одиничні випадки як такі)
Ці тести на користувальницький інтерфейс, безумовно, залежать від порядку виконання, оскільки інший тест повинен додати деякі дані як попередню умову. (Неможливо виконати кроки у кожному тесті)
Тепер, додавши десятий тестовий випадок, я бачу, що NUnit хоче запустити в такому порядку: Test_1 Test_10 Test_2 Test_3 ..
Тож я гадаю, що мені зараз доводиться занадто алфавізувати назви тестових випадків, але було б добре, щоб ця невелика особливість контролю наказу про виконання була додана до NUnit.
Зазвичай Тест одиниці повинен бути незалежним, але якщо потрібно, то ви можете назвати свої методи в алфавітному порядку, наприклад:
[Test]
public void Add_Users(){}
[Test]
public void Add_UsersB(){}
[Test]
public void Process_Users(){}
або ви можете зробити ..
private void Add_Users(){}
private void Add_UsersB(){}
[Test]
public void Process_Users()
{
Add_Users();
Add_UsersB();
// more code
}
a_
b_
t1_
, t2_
замість цього або покладаєтесь на пропустити
Для використання механізму тестового замовлення є дуже вагомі причини. Більшість моїх власних тестів використовують добру практику, таку як налаштування / вибування. Іншим потрібна велика кількість налаштувань даних, які потім можуть бути використані для тестування цілого ряду функцій. До цих пір я використовував великі тести для обробки цих інтеграційних тестів (Selenium Webdriver). Однак, я вважаю, що запропонований вище пост на https://github.com/nunit/docs/wiki/Order-Attribute має багато достоїнств. Ось приклад того, чому замовлення було б надзвичайно цінним:
Цей 10-хвилинний час очікування сповільнює набір тестів. Коли ви множите подібні затримки кешування у безлічі тестів, це забирає багато часу. Замовлення тестів може дозволити налаштування даних робити як "Тест" прямо на початку тестового набору, при цьому тести покладаються на кеш, щоб бюст виконувався наприкінці тестового циклу.
Це питання справді старе, але для людей, які можуть досягти цього в результаті пошуку, я взяв відмінні відповіді від user3275462 та PvtVandals / Rico і додав їх у сховище GitHub разом із деякими власними оновленнями. Я також створив пов’язану публікацію блогу з додатковою інформацією, яку ви можете переглянути для отримання додаткової інформації.
Сподіваюся, що це корисно для всіх вас. Крім того, мені часто подобається використовувати атрибут Категорія, щоб відрізняти мої інтеграційні тести або інші тестові цілі від моїх фактичних одиничних тестів. Інші зазначають, що одиничні тести не повинні залежати від порядку, але інші типи тестів часто це роблять, тому це дає хороший спосіб запустити лише потрібну категорію тестів, а також замовити ці тестові тести.
Я здивований, що у спільноті NUnit нічого не придумали, тому я пішов створити щось подібне сам.
Зараз я розробляю бібліотеку з відкритим кодом, яка дозволяє замовити свої тести з NUnit. Ви можете замовити тестові пристосування та замовити "замовлені специфікації тестування" так само.
Бібліотека пропонує такі функції:
Бібліотека насправді надихається тим, як MSTest здійснює тестове впорядкування .orderedtest
файлів. Перегляньте приклад нижче.
[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
}
Якщо ви використовуєте [TestCase]
, аргумент TestName
вказує назву тесту.
Якщо не вказано, ім'я створюється на основі назви методу та наданих аргументів.
Ви можете контролювати порядок виконання тесту, як наведено нижче:
[Test]
[TestCase("value1", TestName = "ExpressionTest_1")]
[TestCase("value2", TestName = "ExpressionTest_2")]
[TestCase("value3", TestName = "ExpressionTest_3")]
public void ExpressionTest(string v)
{
//do your stuff
}
Тут я використав "ExpressionTest"
суфікс назви методу з числом.
Ви можете використовувати будь-які імена, упорядковані за алфавітом, див. Атрибут TestCase
Ви не повинні залежати від порядку, в якому тестова рамка підбирає тести для виконання.Тести повинні бути ізольованими та незалежними. У зв'язку з цим вони не повинні залежати від деяких інших тестових установок для них чи прибирання після них. Вони також повинні давати однаковий результат незалежно від порядку виконання тестів (для даного знімка SUT)
Я трохи погукав. Як завжди, деякі люди вдаються до підступних хитрощів (замість того, щоб вирішувати основні проблеми тестування / дизайну
Дивіться також: характеристики хорошого тесту
У разі використання TestCaseSource
ключа - це override string ToString
метод, як це працює:
Припустимо, у вас є клас TestCase
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
}
І список тестових випадків:
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
}
};
}
Тепер давайте використовувати його за допомогою методу тестування і побачити, що станеться:
[TestCaseSource(nameof(TestSource))]
public void MethodXTest(TestCase testCase)
{
var x = Power(testCase.Input);
x.ShouldBe(testCase.Expected);
}
Це не буде перевірено в порядку, і результат буде таким:
Тож якщо ми додали override string ToString
до нашого класу на кшталт:
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
public override string ToString()
{
return Name;
}
}
Результат зміниться, і ми отримаємо порядок та назву тесту на зразок:
Примітка: