Por padrão, os testes de unidade são executados em ordem alfabética. Alguém conhece alguma forma de definir a ordem de execução? Existe um atributo para isso?
Por padrão, os testes de unidade são executados em ordem alfabética. Alguém conhece alguma forma de definir a ordem de execução? Existe um atributo para isso?
Respostas:
Cada um dos seus testes de unidade deve ser executado de forma independente e autônoma. Se eles satisfizerem esse critério, a ordem não importa.
No entanto, há ocasiões em que você desejará executar determinados testes primeiro. Um exemplo típico é uma situação de integração contínua em que alguns testes demoram mais tempo do que outros. Usamos o atributo category para que possamos rodar os testes que usam mocking antes dos testes que usam o banco de dados.
ou seja, coloque isso no início de seus testes rápidos
[Category("QuickTests")]
Onde houver testes que dependem de certas condições ambientais, considere os atributos TestFixtureSetUp e TestFixtureTearDown , que permitem marcar métodos a serem executados antes e depois dos testes.
Só quero salientar que, embora a maioria dos respondentes presumisse que eram testes de unidade, a pergunta não especificou que sim.
nUnit é uma ótima ferramenta que pode ser usada em uma variedade de situações de teste. Posso ver as razões apropriadas para querer controlar o pedido de teste.
Nessas situações, tive que recorrer à incorporação de uma ordem de execução no nome do teste. Seria ótimo poder especificar a ordem de execução usando um atributo.
001_first_test
002_second_test
e assim por diante?
NUnit 3.2.0 adicionado e OrderAttribute
, consulte:
https://github.com/nunit/docs/wiki/Order-Attribute
Exemplo:
public class MyFixture
{
[Test, Order(1)]
public void TestA() { ... }
[Test, Order(2)]
public void TestB() { ... }
[Test]
public void TestC() { ... }
}
Querer que os testes sejam executados em uma ordem específica não significa que os testes sejam dependentes uns dos outros - estou trabalhando em um projeto TDD no momento e, sendo um bom TDDer, simulei / fiz stub de tudo, mas faria seria mais legível se eu pudesse especificar a ordem em que os resultados dos testes são exibidos - tematicamente em vez de alfabeticamente. Até agora, a única coisa que posso pensar é adicionar a_ b_ c_ às classes para classes, namespaces e métodos. (Não é legal) Acho que um atributo [TestOrderAttribute] seria bom - não seguido estritamente pela estrutura, mas uma dica para que possamos conseguir isso
Independentemente de os testes serem ou não dependentes da ordem ... alguns de nós apenas querem controlar tudo, de maneira ordenada.
Os testes de unidade geralmente são criados em ordem de complexidade. Então, por que eles também não deveriam ser executados em ordem de complexidade ou na ordem em que foram criados?
Pessoalmente, gosto de ver os testes executados na ordem em que os criei. No TDD, cada teste sucessivo naturalmente será mais complexo e levará mais tempo para ser executado. Eu preferiria ver o teste mais simples falhar primeiro, pois será um indicador melhor da causa da falha.
Mas, também posso ver a vantagem de executá-los em ordem aleatória, especialmente se você quiser testar se seus testes não têm nenhuma dependência de outros testes. Que tal adicionar uma opção para testar os corredores para "Executar testes aleatoriamente até parar"?
Estou testando com Selenium em um site bastante complexo e todo o conjunto de testes pode ser executado por mais de meia hora, e não estou perto de cobrir todo o aplicativo ainda. Se eu tiver que ter certeza de que todos os formulários anteriores foram preenchidos corretamente para cada teste, isso adicionará muito tempo, não apenas uma pequena quantidade de tempo, ao teste geral. Se houver muita sobrecarga para executar os testes, as pessoas não os executarão com a frequência que deveriam.
Então, eu os coloco em ordem e dependo de testes anteriores para ter caixas de texto e tal preenchidas. Eu uso Assert.Ignore () quando as pré-condições não são válidas, mas preciso executá-las em ordem.
Eu realmente gosto da resposta anterior.
Mudei um pouco para poder usar um atributo para definir o intervalo do pedido:
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
não é mais compatível com NUnit 3.
Eu sei que esta é uma postagem relativamente antiga, mas aqui está outra maneira de manter seu teste em ordem SEM tornar os nomes dos testes estranhos. Usando o atributo TestCaseSource e tendo o objeto que você passa tem um delegado (Action), você pode controlar totalmente não apenas o pedido, mas também nomear o teste como ele é.
Isso funciona porque, de acordo com a documentação, os itens da coleção retornados da fonte de teste serão executados sempre na ordem em que estão listados.
Aqui está uma demonstração de uma apresentação que farei amanhã:
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
como uma forma de executar testes ordenados é um golpe de gênio. Bem feito. Eu peguei essa abordagem junto com a abaixo e adicionei algumas modificações adicionais para torná-la mais fácil de usar. Veja os links em minha resposta para obter informações adicionais, mas a ideia subjacente vem desta ótima resposta!
TestCaseSource
deve ser estática, o que impede o uso de padrão. Vadio.
TestCaseSource
deve ser um objeto estático no NUnit 3, ou os testes não serão executados. E você não pode criar objetos dinâmicos dentro de um objeto estático. É por isso que não funcionará no v. 3.
Estou trabalhando com casos de teste de IU de ponta a ponta do Selenium WebDriver escritos em C #, que são executados usando a estrutura NUnit. (Não são casos unitários como tal)
Esses testes de IU certamente dependem da ordem de execução, pois outro teste precisa adicionar alguns dados como uma pré-condição. (Não é viável fazer as etapas em todos os testes)
Agora, após adicionar o 10º caso de teste, vejo que o NUnit deseja ser executado nesta ordem: Test_1 Test_10 Test_2 Test_3 ..
Portanto, acho que devo colocar em ordem alfabética os nomes dos casos de teste por enquanto, mas seria bom ter esse pequeno recurso de controle da ordem de execução adicionado ao NUnit.
Normalmente, o Teste de Unidade deve ser independente, mas se for necessário, você pode nomear seus métodos em ordem alfabética, por exemplo:
[Test]
public void Add_Users(){}
[Test]
public void Add_UsersB(){}
[Test]
public void Process_Users(){}
ou você pode fazer ..
private void Add_Users(){}
private void Add_UsersB(){}
[Test]
public void Process_Users()
{
Add_Users();
Add_UsersB();
// more code
}
a_
b_
t1_
, em t2_
vez ou contando com personagens
Existem boas razões para utilizar um mecanismo de pedido de teste. A maioria dos meus próprios testes usa boas práticas, como configuração / desmontagem. Outros requerem uma grande quantidade de configuração de dados, que podem ser usados para testar uma variedade de recursos. Até agora, usei grandes testes para lidar com esses testes de integração (Selenium Webdriver). No entanto, acho que a postagem sugerida acima em https://github.com/nunit/docs/wiki/Order-Attribute tem muito mérito. Aqui está um exemplo de porque o pedido seria extremamente valioso:
Esse tempo de espera de 10 minutos retarda o conjunto de testes. Quando você multiplica atrasos de armazenamento em cache semelhantes em uma infinidade de testes, isso consome muito tempo. Os testes de pedido podem permitir que a configuração dos dados seja feita como um "Teste" logo no início do conjunto de testes, com os testes contando com o cache para ser executado no final da execução do teste.
Esta pergunta é muito antiga agora, mas para as pessoas que podem chegar a isso pesquisando, peguei as excelentes respostas do user3275462 e do PvtVandals / Rico e as adicionei a um repositório GitHub junto com algumas de minhas próprias atualizações. Também criei uma postagem de blog associada com algumas informações adicionais que você pode consultar para obter mais informações.
Espero que isso seja útil para todos vocês. Além disso, geralmente gosto de usar o atributo Categoria para diferenciar meus testes de integração ou outros testes ponta a ponta de meus testes de unidade reais. Outros indicaram que os testes de unidade não devem ter uma dependência de ordem, mas outros tipos de teste costumam ter, então isso fornece uma boa maneira de executar apenas a categoria de testes que você deseja e também ordenar esses testes ponta a ponta.
Estou surpreso que a comunidade NUnit não apareceu com nada, então fui criar algo assim sozinho.
Atualmente estou desenvolvendo uma biblioteca de código aberto que permite que você solicite seus testes com o NUnit. Você pode solicitar acessórios de teste e também "especificações de teste solicitadas".
A biblioteca oferece os seguintes recursos:
A biblioteca é realmente inspirada em como o MSTest testa pedidos de .orderedtest
arquivos. Por favor, veja um exemplo abaixo.
[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
}
Se você estiver usando [TestCase]
, o argumento TestName
fornece um nome para o teste.
Se não for especificado, um nome será gerado com base no nome do método e nos argumentos fornecidos.
Você pode controlar a ordem de execução do teste conforme abaixo:
[Test]
[TestCase("value1", TestName = "ExpressionTest_1")]
[TestCase("value2", TestName = "ExpressionTest_2")]
[TestCase("value3", TestName = "ExpressionTest_3")]
public void ExpressionTest(string v)
{
//do your stuff
}
Aqui, usei o "ExpressionTest"
sufixo do nome do método com um número.
Você pode usar qualquer nome em ordem alfabética, consulte o atributo TestCase
Você não deve depender da ordem em que a estrutura de teste seleciona os testes para execução. Os testes devem ser isolados e independentes. Nesse sentido, eles não devem depender de algum outro teste preparando o cenário para eles ou limpando depois deles. Eles também devem produzir o mesmo resultado, independentemente da ordem de execução dos testes (para um determinado instantâneo do SUT)
Eu pesquisei um pouco no Google. Como de costume, algumas pessoas recorreram a truques furtivos (em vez de resolver o problema de testabilidade / design subjacente
Veja também: características de um bom teste
No caso de usar TestCaseSource
a chave é o override string ToString
método, como isso funciona:
Suponha que você tenha a classe TestCase
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
}
E uma lista de 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
}
};
}
Agora vamos usá-lo com um método de teste e ver o que acontece:
[TestCaseSource(nameof(TestSource))]
public void MethodXTest(TestCase testCase)
{
var x = Power(testCase.Input);
x.ShouldBe(testCase.Expected);
}
Isso não será testado em ordem e a saída será assim:
Portanto, se adicionarmos override string ToString
à nossa classe:
public class TestCase
{
public string Name { get; set; }
public int Input { get; set; }
public int Expected { get; set; }
public override string ToString()
{
return Name;
}
}
O resultado mudará e obteremos a ordem e o nome do teste como:
Nota: