misma prueba unitaria para diferentes implementaciones

Resuelto Alex asked hace 11 años • 6 respuestas

Digamos que tengo dos implementaciones de un algoritmo de búsqueda que devuelven el mismo resultado para la misma entrada. Ambos implementan la misma interfaz.

¿Cómo puedo usar uno único [TestClass]para probar ambas implementaciones, en lugar de crear dos archivos de prueba con la misma lógica?

¿Puedo decirle a MSUnit que inicie una de las pruebas dos veces con un parámetro de constructor diferente?
¿Quizás debería inyectarlo de alguna manera?

Alex avatar Mar 22 '13 18:03 Alex
Aceptado

Utilice una clase de prueba abstracta :

[TestClass]
public abstract class SearchTests
{
    private ISearcher _searcherUnderTest;

    [TestSetup]
    public void Setup()
    {
        _searcherUnderTest = CreateSearcher();
    }

    protected abstract ISearcher CreateSearcher();

    [TestMethod]
    public void Test1(){/*do stuff to _searcherUnderTest*/ }

    // more tests...

    [TestClass]
    public class CoolSearcherTests : SearcherTests
    {
         protected override ISearcher CreateSearcher()
         {
             return new CoolSearcher();
         }
    }

    [TestClass]
    public class LameSearcherTests : SearcherTests
    {
         protected override ISearcher CreateSearcher()
         {
             return new LameSearcher();
         }
    }
}
tallseth avatar Mar 24 '2013 21:03 tallseth

Has etiquetado tu pregunta con NUnit, pero preguntas sobre MSTest. Lo que pregunta se puede lograr con dispositivos de prueba parametrizados en NUnit. No estoy lo suficientemente familiarizado con MSTest como para sugerir un enfoque equivalente allí, y una búsqueda rápida indica que es posible que MSTest no tenga esta característica.

En NUnit, usted parametriza el dispositivo de prueba aplicando múltiples [TestFixture(...)]atributos a la clase de dispositivo con diferentes parámetros. Estos parámetros se pasarán al constructor del dispositivo.

Dado que existen límites en los tipos de parámetros que se pueden pasar, probablemente necesitará pasar una cadena al especificar el algoritmo y luego, en el constructor, asignar el delegado u objeto que proporciona el algoritmo de búsqueda a un campo miembro que se utiliza en los exámenes.

Por ejemplo:

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

namespace MyTests
{
    public static class SearchAlgorithms
    {
        public static int DefaultSearch(int target, IList<int> data)
        {
            return data.IndexOf(target);
        }

        public static int BrokenSearch(int target, IList<int> data)
        {
            return 789;
        }
    }

    [TestFixture("forward")]
    [TestFixture("broken")]
    public class SearchTests
    {
        private Func<int, IList<int>, int> searchMethod;

        public SearchTests(string algorithmName)
        {
            if (algorithmName == "forward")
            {
                this.searchMethod = SearchAlgorithms.DefaultSearch;
                return;
            }

            if (algorithmName == "broken")
            {
                this.searchMethod = SearchAlgorithms.BrokenSearch;
            }
        }

        [Test]
        public void SearchFindsCorrectIndex()
        {
            Assert.AreEqual(
                1, this.searchMethod(2, new List<int> { 1, 2, 3 }));
        }

        [Test]
        public void SearchReturnsMinusOneWhenTargetNotPresent()
        {
            Assert.AreEqual(
                -1, this.searchMethod(4, new List<int> { 1, 2, 3 }));
        }
    }
}
Ergwun avatar Mar 22 '2013 12:03 Ergwun