.net - asp - test net core
Orden de ejecuciĆ³n de prueba NUnit (15)
Esta pregunta es realmente antigua ahora, pero para las personas que pueden llegar a esto de la búsqueda, tomé las excelentes respuestas de user3275462 y PvtVandals / Rico y las agregué a un repositorio de GitHub junto con algunas de mis propias actualizaciones. También creé una publicación de blog asociada con información adicional que puedes consultar para obtener más información.
Espero que esto sea útil para todos ustedes. Además, a menudo me gusta usar el atributo Categoría para diferenciar mis pruebas de integración u otras pruebas de extremo a extremo de mis pruebas unitarias reales. Otros han señalado que las pruebas unitarias no deberían tener una dependencia de orden, pero otros tipos de prueba a menudo sí lo hacen, por lo que esto proporciona una buena manera de ejecutar solo la categoría de pruebas que desee y también ordenar esas pruebas de extremo a extremo.
Por defecto, las pruebas de nunit se ejecutan alfabéticamente. ¿Alguien sabe de alguna forma de establecer el orden de ejecución? ¿Existe un atributo para esto?
Estoy probando con Selenium en un sitio web bastante complejo y todo el conjunto de pruebas puede durar más de media hora, y aún no estoy cerca de cubrir toda la aplicación. Si tengo que asegurarme de que todos los formularios anteriores se completan correctamente para cada prueba, esto agrega una gran cantidad de tiempo, no solo una pequeña cantidad de tiempo, a la prueba general. Si hay demasiados gastos generales para ejecutar las pruebas, las personas no los ejecutarán con la frecuencia que deberían.
Entonces, los pongo en orden y dependo de pruebas previas para tener cuadros de texto y así completados. Yo uso Assert.Ignore () cuando las condiciones previas no son válidas, pero necesito que se ejecuten en orden.
Estoy trabajando con los casos de prueba de interfaz de usuario de extremo a extremo de Selenium WebDriver escritos en C #, que se ejecutan utilizando el marco NUnit. (No casos de unidades como tales)
Estas pruebas de UI ciertamente dependen del orden de ejecución, ya que otras pruebas necesitan agregar algunos datos como condición previa. (No es factible hacer los pasos en cada prueba)
Ahora, después de agregar el décimo caso de prueba, veo que NUnit quiere ejecutar en este orden: Test_1 Test_10 Test_2 Test_3 ...
Así que supongo que también tengo que alfabetizar los nombres de casos de prueba por ahora, pero sería bueno tener esta pequeña característica de control de ejecución añadida a NUnit.
Hay muy buenas razones para utilizar un mecanismo de pedido de prueba. La mayoría de mis propias pruebas usan buenas prácticas como configuración / desmontaje. Otros requieren una gran cantidad de configuración de datos, que luego se puede utilizar para probar una serie de características. Hasta ahora, he usado pruebas grandes para manejar estas pruebas de integración (Selenium Webdriver). Sin embargo, creo que la publicación sugerida anteriormente en https://github.com/nunit/docs/wiki/Order-Attribute tiene mucho mérito. Aquí hay un ejemplo de por qué ordenar sería extremadamente valioso:
- Usando Selenium Webdriver para ejecutar una prueba para descargar un informe
- El estado del informe (ya sea descargable o no) se almacena en caché durante 10 minutos
- Eso significa que, antes de cada prueba, necesito restablecer el estado del informe y esperar hasta 10 minutos antes de que se confirme que el estado ha cambiado, y luego verificar que el informe se descargue correctamente.
- Los informes no se pueden generar de manera práctica / oportuna mediante burlas o cualquier otro mecanismo dentro del marco de prueba debido a su complejidad.
Este tiempo de espera de 10 minutos ralentiza el conjunto de pruebas. Cuando multiplica demoras de caché similares en una multitud de pruebas, consume mucho tiempo. Las pruebas de pedido pueden permitir que la configuración de datos se realice como una "Prueba" justo al comienzo del conjunto de pruebas, con pruebas que dependen de que el caché se bloquee ejecutándose hacia el final de la ejecución de prueba.
Independientemente de si las pruebas dependen o no del orden ... algunos de nosotros solo queremos controlar todo, de manera ordenada.
Las pruebas unitarias generalmente se crean por orden de complejidad. Entonces, ¿por qué no deberían también ejecutarse en orden de complejidad, o el orden en el que fueron creados?
Personalmente, me gusta ver que las pruebas se ejecuten en el orden en que las creé. En TDD, cada prueba sucesiva naturalmente será más compleja y llevará más tiempo ejecutarla. Prefiero ver que la prueba más simple falla primero, ya que será un mejor indicador de la causa de la falla.
Pero también puedo ver el beneficio de ejecutarlos en orden aleatorio, especialmente si desea probar que sus pruebas no tienen dependencias en otras pruebas. ¿Qué le parece agregar una opción para probar a los corredores a "Ejecutar pruebas aleatoriamente hasta que se detengan"?
Las pruebas de su unidad deben poder ejecutarse de manera independiente y autónoma. Si cumplen este criterio, entonces el orden no importa.
Sin embargo, hay ocasiones en las que querrá ejecutar ciertas pruebas primero. Un ejemplo típico es en una situación de integración continua donde algunas pruebas se ejecutan más tiempo que otras. Usamos el atributo de categoría para que podamos ejecutar las pruebas que usan burla antes de las pruebas que usan la base de datos.
es decir, pon esto al comienzo de tus pruebas rápidas
[Category("QuickTests")]
Si tiene pruebas que dependen de ciertas condiciones ambientales, considere los atributos TestFixtureSetUp y TestFixtureTearDown , que le permiten marcar los métodos que se ejecutarán antes y después de las pruebas.
Me sorprende que la comunidad NUnit no haya encontrado nada, así que fui a crear algo como esto yo mismo.
Actualmente estoy desarrollando una biblioteca de código abierto que le permite ordenar sus pruebas con NUnit. Puede solicitar accesorios de prueba y pedir "especificaciones de prueba ordenadas" por igual.
La biblioteca ofrece las siguientes características:
- Construir jerarquías de ordenamiento de pruebas complejas
- Omita las pruebas subsiguientes si falla una prueba en orden
- Solicite sus métodos de prueba por dependencia en lugar de por orden entera
- Admite el uso lado a lado con pruebas desordenadas. Las pruebas desordenadas se ejecutan primero.
La biblioteca está inspirada en la forma en que MSTest hace una prueba de ordenación con archivos .orderedtest
. Por favor, mira un ejemplo a continuación.
[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
}
NUnit 3.2.0 agregó un OrderAttribute
, ver:
https://github.com/nunit/docs/wiki/Order-Attribute
Ejemplo:
public class MyFixture
{
[Test, Order(1)]
public void TestA() { ... }
[Test, Order(2)]
public void TestB() { ... }
[Test]
public void TestC() { ... }
}
Por lo general, la Prueba Unitaria debe ser independiente, pero si debe, puede nombrar sus métodos en orden alfabético ex:
[Test]
public void Add_Users(){}
[Test]
public void Add_UsersB(){}
[Test]
public void Process_Users(){}
o puedes hacer ..
private void Add_Users(){}
private void Add_UsersB(){}
[Test]
public void Process_Users()
{
Add_Users();
Add_UsersB();
// more code
}
Querer que las pruebas se ejecuten en un orden específico no significa que las pruebas dependan una de la otra. Estoy trabajando en un proyecto TDD en este momento, y como soy un buen TDDer, me he burlado / tropezado todo, pero haría es más legible si pudiera especificar el orden en que se muestran los resultados de las pruebas, temáticamente en lugar de alfabéticamente. Hasta ahora, lo único en lo que puedo pensar es anteponer a_b_c_ a clases en clases, espacios de nombres y métodos. (No es agradable) Creo que un atributo [TestOrderAttribute] sería agradable, no estrictamente seguido por el marco, pero una pista para que podamos lograr esto
Realmente me gusta la respuesta anterior.
Lo cambié un poco para poder usar un atributo para establecer el rango de orden:
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);
}
}
}
}
}
}
Sé que esta es una publicación relativamente antigua, pero esta es otra forma de mantener su prueba en orden SIN hacer que los nombres de las pruebas sean incómodos. Al utilizar el atributo TestCaseSource y hacer que el objeto que pase tenga un delegado (Acción), no solo puede controlar el orden, sino también nombrar el examen como es.
Esto funciona porque, de acuerdo con la documentación, los elementos de la colección devueltos por la fuente de prueba siempre se ejecutarán en el orden en que se enumeran.
Aquí hay una demostración de una presentación que estoy dando mañana:
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");
}
}
}
}
Si está utilizando [TestCase]
, el argumento TestName
proporciona un nombre para la prueba.
Si no se especifica, se genera un nombre basado en el nombre del método y los argumentos proporcionados.
Puede controlar el orden de ejecución de la prueba como se indica a continuación:
[Test]
[TestCase("value1", TestName = "ExpressionTest_1")]
[TestCase("value2", TestName = "ExpressionTest_2")]
[TestCase("value3", TestName = "ExpressionTest_3")]
public void ExpressionTest(string v)
{
//do your stuff
}
Aquí utilicé el sufijo de nombre de método "ExpressionTest"
con un número.
Puede usar cualquier nombre ordenado alfabéticamente. Ver el atributo TestCase.
Solo quiero señalar que, si bien la mayoría de los encuestados asumió que se trataba de pruebas unitarias, la pregunta no especificaba que lo fueran.
nUnit es una gran herramienta que puede usarse para una variedad de situaciones de prueba. Puedo ver razones apropiadas para querer controlar el orden de las pruebas.
En esas situaciones, tuve que recurrir a incorporar una orden de ejecución en el nombre de la prueba. Sería genial poder especificar el orden de ejecución usando un atributo.
No debe depender del orden en que el marco de prueba elige pruebas para su ejecución. Las pruebas deben ser aisladas e independientes. En eso no deben depender de alguna otra prueba que les prepare el escenario o que los limpie después de ellos. También deben producir el mismo resultado, independientemente del orden de ejecución de las pruebas (para una instantánea dada del SUT)
Hice un poco de googlear. Como de costumbre, algunas personas han recurrido a trucos furtivos (en lugar de resolver el problema subyacente de capacidad de prueba / diseño)
- nombrar las pruebas de una manera ordenada alfabéticamente de manera que las pruebas aparezcan en el orden en que ''necesitan'' ejecutarse. Sin embargo, NUnit puede optar por cambiar este comportamiento con una versión posterior y, luego, se realizarán análisis de mangueras en sus pruebas. Mejor controlar los binarios NUnit actuales en el control de código fuente.
- VS (en mi humilde opinión fomentando el comportamiento incorrecto con sus "herramientas ágiles") tiene algo llamado "Pruebas ordenadas" en su marco de prueba de EM. No perdí el tiempo leyendo, pero parece estar dirigido a la misma audiencia
Ver también: características de una buena prueba