Pregunta

Estoy trabajando con una clase que tiene muchas propiedades. Por ejemplo;

public class Bib
{        
    public int PartQty { get; set; }
}

Ahora a la prueba unitaria; Hice la prueba de XUnit algo como

    [Fact]
    public void CanGetAndSetPartQuantity()
    {
        const int expected = 3;

        var target = new Bib() {PartQty = expected};

        Assert.Equal(expected, target.PartQty);
    }

Aquí, odio cómo estoy codificando duro = 3. ¿Cuál es una buena manera de probar esta propiedad para accesor y mutador?

¿Fue útil?

Solución

No determinismo restringido es una buena opción para este tipo de prueba unitaria. Escríbelo así en su lugar:

[Fact]
public void CanGetAndSetPartQuantity()
{
    const int expected = new Random().Next();

    var target = new Bib() {PartQty = expected};

    Assert.Equal(expected, target.PartQty);
}

Esto asegura que la salida represente correctamente la entrada, sin importar cuál sea la entrada.

Otros consejos

Dado que esta propiedad no tiene otro comportamiento que ser un obtonador/setter para un entero, esencialmente solo está probando que el compilador funcionó. Esto agrega básicamente ningún valor a su prueba. Considere eliminarlo por completo. Eso lo aliviaría de esta extraña situación. :)

Si tiene algún comportamiento que está tratando de capturar (por ejemplo, condiciones de contorno permitidas) solo necesita probarlos, y realmente nada más. Por lo general, tendrá constantes para las condiciones de contorno disponibles como parte del objeto. Considere usar esas constantes, +/- algún incremento apropiado.

Creo firmemente en que las pruebas unitarias sean pruebas de 'caja blanca', lo que significa que puede usar casos de esquina conocidos para elegir sus entradas de prueba. En este caso en particular, con una autopertura automática, la prueba es innecesaria si confía en su compilador. Si no puede confiar en el compilador para implementar una autopertura automática de la forma en que espera, entonces tampoco puede confiar en que ejecute la prueba como ha escrito.

Dicho esto, si tiene un setter más complejo, elegiría sus entradas en función de los posibles casos de falla. Algunos casos típicos:

  • Números negativos para propiedades que validan> = 0
  • Otras fallas de validación
  • Casos de límites extremos como Int.MaxValue, que a veces pueden desencadenar desbordamientos y un comportamiento inesperado en el setter
  • Un valor arbitrario que debería aprobar la validación (no hay una guía real sobre cómo elegir un valor aquí, siempre que sepa que está en su 'buen' caso).

Esto debería ayudar ...

[Fact]     
public void CanGetAndSetPartQuantity()     
{
    bool fail = false;
    int expected = 0;

    while (!fail && expected < int.MaxValue)
    {
        var target = new Bib() {PartQty = expected};          
        fail = expected != target.PartQty;
        expected++;
    }

    Assert.IsTrue(!fail);
} 

Wathed una presentación sobre buenas prácticas de prueba unitaria hace un tiempo (lo siento, pero el nombre del tipo escapó de mi memoria frágil). Él abogó por el uso de valores de almacenamiento como ese en constantes con nombres cuidadosamente seleccionados.

En tu caso, usaría un nombre como

const int SomeRandomValidPartQuantity=3;

Con esto, señala la intención de usar exactamente este valor, y en este caso está justo después de cualquier cantidad válida.

La prueba debe derivarse de algún tipo de caso de uso. Lo curioso es que primero presentó su clase, luego habló sobre escribir una prueba, que está al revés a TDD.

El caso de uso informa la prueba, que informa el código. Dudo mucho que su caso de uso sea "el usuario de mi API puede establecer una propiedad llamada PartQty a cualquier número entero y siempre recupere el entero que establezca ". Si ese fuera el caso de uso real, escribiría una prueba unitaria que verifica int.MaxValue y int.MinValue. Sin embargo, estos rara vez son valores del mundo real.

Un caso de uso del mundo real puede parecer: "El usuario de mis noticias de API Up a Bib inyectando un IFlugleBinder, establece el PartQty a 4 y luego llama al Execute método. Esto llama al Bind método en el IFlugleBinder instancia 4 veces. "Si ese fuera el caso de uso, su prueba se vería muy diferente.

Honestamente parece Bib es solo un DTO de algún tipo. En mi experiencia, la mayoría de los DTO son solo un artefacto de algún caso de uso de nivel superior. Si el DTO se devuelve como resultado de una llamada de función que proporciona su API, entonces realmente debería devolver una interfaz, y la clase DTO en sí misma debe ser privada, en cuyo caso no es necesario probarla explícitamente (solo pruebe las propiedades del resultado real que obtiene de la llamada del método). Del mismo modo, si se trata de un DTO interno que nunca está expuesto, entonces no lo haga público. Si su usuario tiene que proporcionar algún paquete de valores, entonces su API debería aceptar una interfaz. Deje que el usuario defina su propia clase que implementa la interfaz o proporcione una inmutable, como esta:

public class Bib : IBib
{
    public Bib(int partQty)
    {
        PartQty = partQty;
    }
    public int PartQty { get; private set; }
}

Luego puede escribir una prueba que verifica si su constructor funciona si desea ser pedante, pero no es tan importante.

Si bien también creo que esto se encuentra en la categoría "Prueba hasta aburrirse", si realmente siente que vale la pena probar, las pruebas de aprobación ofrecen una forma muy simple de probar. Adjunto hay una prueba simple para verificar las propiedades.

[TestMethod]
[UseReporter(typeof(DiffReporter))]
public void TestMethod1()
{
    var fred = new Person{
            Age = 35,
        FirstName = "fred",
        LastName = "Flintstone",
        Hair = Color.Black
           };
    Approvals.Verify(fred.WritePropertiesToString());
}

Esto producirá un archivo que lee:

Person
{
    Age: 35
    FirstName: fred
    LastName: Flintstone
    Hair: Color [Black]
}

Simplemente cambie el nombre de ese archivo a. Apropiado y termine.

Tenga en cuenta el uso del método de extensión: .writeProperTiDoString ()

Hay un video sobre los conceptos básicos de las pruebas de aprobación aquí para

MSTEST: http://www.youtube.com/watch?v=bg8gomlwqyy

Nunit: http://www.youtube.com/watch?v=ao_fyzbxafk

XUnit: http://www.youtube.com/watch?v=8wpx0o4gfzc

También puede usar el atributo Autodata de autofixture como este:

        [Theory]
        [AutoData]
        public void CanGetAndSetPartQuantity(int expected)
        {
            var target = new Bib() {PartQty = expected};

            Assert.Equal(expected, target.PartQty);
        }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top