По умолчанию тесты nunit выполняются в алфавитном порядке. Кто-нибудь знает, как установить порядок выполнения? Есть ли для этого атрибут?
По умолчанию тесты nunit выполняются в алфавитном порядке. Кто-нибудь знает, как установить порядок выполнения? Есть ли для этого атрибут?
Ответы:
Каждый из ваших модульных тестов должен уметь работать независимо и автономно. Если они удовлетворяют этому критерию, то порядок не имеет значения.
Однако есть случаи, когда вам нужно сначала запустить определенные тесты. Типичным примером является ситуация непрерывной интеграции, когда одни тесты выполняются дольше, чем другие. Мы используем атрибут category, чтобы мы могли запускать тесты, использующие имитацию, перед тестами, которые используют базу данных.
т.е. поместите это в начало ваших быстрых тестов
[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 каждый последующий тест, естественно, будет более сложным, и на его выполнение уйдет больше времени. Я бы предпочел сначала провалить более простой тест, поскольку он будет лучшим индикатором причины сбоя.
Но я также вижу преимущества запуска их в случайном порядке, особенно если вы хотите проверить, что ваши тесты не зависят от других тестов. Как насчет добавления опции для участников тестирования в «Запускать тесты в случайном порядке до остановки»?
Я тестирую Selenium на довольно сложном веб-сайте, и весь набор тестов может длиться более получаса, и я еще не близок к тому, чтобы охватить все приложение. Если мне нужно убедиться, что все предыдущие формы заполнены правильно для каждого теста, это добавляет много времени, а не только небольшое количество времени, к общему тесту. Если выполнение тестов требует слишком больших затрат, люди не будут запускать их так часто, как следовало бы.
Итак, я привел их в порядок и полагаюсь на предыдущие тесты, чтобы иметь текстовые поля и тому подобное. Я использую 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 и имея объект, который вы передаете, имеет делегат (действие), вы можете полностью не только управлять порядком, но и называть тест, какой он есть.
Это работает, потому что, согласно документации, элементы в коллекции, возвращенной из тестового источника, всегда будут выполняться в том порядке, в котором они перечислены.
Вот демонстрация презентации, которую я даю завтра:
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.
Я работаю с тестовыми примерами сквозного пользовательского интерфейса Selenium WebDriver, написанными на C #, которые выполняются с использованием фреймворка NUnit. (Не единицы как таковые)
Эти тесты пользовательского интерфейса, безусловно, зависят от порядка выполнения, поскольку другой тест должен добавлять некоторые данные в качестве предварительного условия. (Невозможно выполнить шаги в каждом тесте)
Теперь, после добавления 10-го тестового примера, я вижу, что 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 вместе с некоторыми из моих собственных обновлений. Я также создал связанный пост в блоге с некоторой дополнительной информацией, которую вы можете найти для получения дополнительной информации.
Надеюсь, это будет полезно для всех вас. Кроме того, мне часто нравится использовать атрибут Category, чтобы отличать мои интеграционные тесты или другие сквозные тесты от моих реальных модульных тестов. Другие отмечали, что модульные тесты не должны иметь зависимости от порядка, но другие типы тестов часто имеют, так что это дает хороший способ запускать только ту категорию тестов, которую вы хотите, а также упорядочивать эти сквозные тесты.
Я удивлен, что сообщество 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; }
}
И список TestCases:
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
}
};
}
Теперь давайте используем его с методом Test и посмотрим, что произойдет:
[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;
}
}
Результат изменится, и мы получим порядок и название теста, например:
Примечание: