Pregunta

Se me ha pedido que escriba una aplicación de prueba que necesita probar un nuevo procedimiento almacenado en varias filas en una base de datos, en esencia quiero hacer algo como esto:


[Test]
public void TestSelect()
{
    foreach(id in ids)
    {
        DataTable old = Database.call("old_stored_proc",id);
        DataTable new_ = Database.call("new_stored_proc",id);

        Assert.AreEqual(old.Rows[0]["column"],ne_.Rows[0]["column"]);
    }
}

Cuando ejecuto esta prueba, si 1 fila no coincide con la otra, la prueba completa falla; en cambio, me gustaría contar cuántas veces se aprobó la afirmación y cuántas veces ha fallado. ¿Hay alguna manera de hacer esto con NUnit?

Me doy cuenta de que NUnit podría ser una exageración y esta es una tarea simple sin eso ... solo quería aprenderlo. ;)

¿Fue útil?

Solución

1) Si los ID son constantes y no se buscan en el tiempo de ejecución de la prueba, cree un dispositivo de prueba de unidad por separado para cada ID. De esa manera sabrás qué id están fallando realmente. Vea aquí una reseña sobre los problemas con las pruebas basadas en datos:
http://googletesting.blogspot.com/2008/09/tott -data-driven-traps.html

2) Si necesita buscar dinámicamente los identificadores que hacen imposible crear un elemento para cada identificador, use la sugerencia de akmad con un cambio. Mantenga una lista de identificadores donde los valores no sean iguales y agregue la lista al mensaje de error. Será extremadamente difícil diagnosticar una prueba fallida que solo indique la cantidad de errores, ya que no sabrá qué id. Causa los errores.

3) No sé lo difícil que sería hacerlo en NUnit, pero en PyUnit, cuando necesitamos ejecutar pruebas en datos generados dinámicamente, creamos dinámicamente accesorios de pruebas y los adjuntamos a la clase TestCase para que podamos tiene una prueba fallida para cada pieza de datos que no pasa. Aunque imagino que esto sería mucho más difícil sin las habilidades dinámicas de Python.

Otros consejos

Parece que solo estás afirmando lo incorrecto. Si desea verificar todos los valores y luego afirmar que no hay errores (o mostrar el número de errores), intente esto:

[Test]
public void TestSelect()
{
    int errors = 0;
    foreach(id in ids)
    {
        DataTable old = Database.call("old_stored_proc",id);
        DataTable new_ = Database.call("new_stored_proc",id);

        if (old.Rows[0]["column"] != new_.Rows[0]["column"])
        {
            errors++;
        }            
    }

    Assert.AreEqual(0, errors, "There were " + errors + " errors.");
}

Sé que la pregunta es específicamente sobre NUnit, pero curiosamente, Gallio / MbUnit tiene una función que permite ejecutar y capturar varias afirmaciones a la vez.

[Test]
public void MultipleTest()
{
    Assert.Multiple(() =>
    {
       Assert.IsTrue(blabla);
       Assert.AreEqual(pik, pok);
       // etc.
    }
}

El Assert.Multiple está capturando todas las afirmaciones fallidas y las informará al final de la prueba.

Contaría el número de filas que no coinciden y luego escribiría una aserción que compararía este número con 0 y devolvería el número de cadenas no coincidentes en el mensaje.

también podría usar Assert.Greater para esto.

P.S. En principio, debe intentar hacer una afirmación por prueba de unidad. Esa es la esencia de eso.

Bueno, puedes declarar un contador y luego afirmar el valor del contador para determinar si se aprueba o no pasa

Además, podría realizar la mayor parte del trabajo en la configuración de la prueba y luego crear varias pruebas.

No tengo claro por qué necesita todas las afirmaciones en la misma prueba.

Según el objetivo establecido, la prueba completa debería fallar si una fila no coincide con otra. Contar el número de veces que una afirmación pasa o falla le da menos información que una comparación del resultado que esperaba con el resultado que realmente obtuvo.

Recientemente tuve el mismo problema. Combiné la idea de contar errores con la mención de Yann Trevin de Assert.Multiple en un método de extensión para IEnumberable que me permite hacer cosas como:

[Test]
public void TestEvenNumbers()
{
    int[] numbers = new int[] { 2, 4, 12, 22, 13, 42 };
    numbers.AssertAll((num) => Assert.That((num % 2) == 0, "{0} is an odd number", num));
}

Que da como resultado la salida de NUnit:

TestEvenNumbers:
  5 of 6 tests passed; 0 inconclusive
FAILED: 13:   13 is an odd number
  Expected: True
  But was:  False

  Expected: 6
  But was:  5

Y la solución al problema del OP sería:

[Test]
public void TestSelect()
{
    ids.AssertAll(CheckStoredProcedures);
}

private void CheckStoredProcedures(Id id)
{
    DataTable old = Database.call("old_stored_proc",id);
    DataTable new_ = Database.call("new_stored_proc",id);

    Assert.AreEqual(old.Rows[0]["column"], new_.Rows[0]["column"]);
}

Aquí está el método de extensión (tenga en cuenta que utilicé "Todos" en lugar de "Múltiple" para mantener la coherencia con la terminología de Linq):

using System;
using System.Text;
using System.Collections.Generic;
using NUnit.Framework;

public static class NUnitExtensions
{
    public static void AssertAll<T>(this IEnumerable<T> objects, Action<T> test)
    {
        int total = 0;
        int passed = 0;
        int failed = 0;
        int inconclusive = 0;
        var sb = new StringBuilder();
        foreach (var obj in objects)
        {
            total++;
            try
            {
                test(obj);
                passed++;
            }
            catch (InconclusiveException assertion)
            {
                inconclusive++;
                string message = string.Format("INCONCLUSIVE: {0}: {1}", obj.ToString(), assertion.Message);
                Console.WriteLine(message);
                sb.AppendLine(message);
            }
            catch (AssertionException assertion)
            {
                failed++;
                string message = string.Format("FAILED: {0}: {1}", obj.ToString(), assertion.Message);
                Console.WriteLine(message);
                sb.AppendLine(message);
            }
        }

        if (passed != total)
        {
            string details = sb.ToString();
            string message = string.Format("{0} of {1} tests passed; {2} inconclusive\n{3}", passed, total, inconclusive, details);
            if (failed == 0)
            {
                Assert.Inconclusive(message);
            }
            else
            {
                Assert.AreEqual(total, passed, message);
            }
        }
    }
}

Puede usar el [TestCase ()] atributo si se trata de una simple lista codificada de ID.

[Test]
[TestCase(1234)]
[TestCase(5678)]
[TestCase(7654)]
public void TestSelect(int id)
{
    DataTable old = Database.call("old_stored_proc", id);
    DataTable new_ = Database.call("new_stored_proc", id);

    Assert.AreEqual(old.Rows[0]["column"], new_.Rows[0]["column"]);
}

Esto generará tres pruebas separadas para cada ID y cualquier corredor de prueba de nunit que use mostrará recuentos de aprobación / falla.

Si necesita generar una lista dinámica de ID, recomiende utilizar [TestCaseSource ()] atributo .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top