Pregunta

Usando C#, necesito una clase llamada User que tenga un nombre de usuario, contraseña, bandera activa, nombre, apellido, nombre completo, etc.

Debería haber métodos para autenticar y ahorrar un usuario.¿Simplemente escribo una prueba para los métodos?¿Y tengo que preocuparme siquiera por probar las propiedades, ya que son los captadores y definidores de .Net?

¿Fue útil?

Solución

Muchas respuestas excelentes a esto también están en mi pregunta:"Inicio de TDD: ¿Desafíos?¿Soluciones?¿Recomendaciones?"

¿Puedo recomendar también echar un vistazo a mi entrada en el blog (que se inspiró en parte en mi pregunta), recibí buenos comentarios al respecto.A saber:

¿No sé por dónde empezar?

  • Comenzar de nuevo.Solo piense en escribir pruebas cuando esté escribiendo un nuevo código.Esto puede ser la reelaboración del código antiguo, o una característica completamente nueva.
  • Empiece de forma sencilla.No salga corriendo e intente hacer que su cabeza redondee un marco de prueba, además de ser un estilo TDD.Debug.Assert funciona bien.Úselo como punto de partida.No se meta con su proyecto ni crea dependencias.
  • Empiece positivo.Estás tratando de mejorar tu oficio, siéntete bien al respecto.He visto muchos desarrolladores que están felices de estancarse y no probar cosas nuevas para mejorar.Estás haciendo lo correcto, recuerda esto y te ayudará a evitar que te rindas.
  • Empiece a prepararse para un desafío.Es bastante difícil comenzar a entrar en las pruebas.Espere un desafío, pero recuerde: se pueden superar los desafíos.

Sólo prueba lo que esperas

Tuve problemas reales cuando comencé porque estaba constantemente sentado allí tratando de descubrir todos los problemas posibles que pudieran ocurrir y luego tratando de probarlo y solucionarlo.Esta es una forma rápida de sufrir dolor de cabeza.Las pruebas deben ser un verdadero proceso de Yagni.Si sabe que hay un problema, escriba una prueba para él.De lo contrario, no te molestes.

Sólo prueba una cosa

Cada caso de prueba solo debe probar una cosa.Si alguna vez te encuentras poniendo "y" en el nombre del caso de prueba, estás haciendo algo mal.

Espero que esto signifique que podamos pasar de "captadores y definidores" :)

Otros consejos

Pruebe su código, no el idioma.

Una prueba unitaria como:

Integer i = new Integer(7);
assert (i.instanceOf(integer));

sólo es útil si está escribiendo un compilador y existe una posibilidad distinta de cero de que su instanceof El método no funciona.

No pruebes cosas que puedas confiar en el lenguaje para aplicar.En su caso, me centraría en sus métodos de autenticación y guardado, y escribiría pruebas que aseguraran que pudieran manejar valores nulos en cualquiera o todos esos campos con elegancia.

Esto me llevó a las pruebas unitarias y me hizo muy feliz.

Acabamos de empezar a hacer pruebas unitarias.Durante mucho tiempo supe que sería bueno empezar a hacerlo, pero no tenía idea de cómo empezar y, lo que es más importante, qué probar.

Luego tuvimos que reescribir un código importante en nuestro programa de contabilidad.Esta parte fue muy compleja ya que involucraba muchos escenarios diferentes.La parte a la que me refiero es un método para pagar facturas de ventas y/o compras ya ingresadas en el sistema contable.

Simplemente no sabía cómo empezar a codificarlo, ya que había tantas opciones de pago diferentes.Una factura podría ser de $100 pero el cliente solo transfirió $99.Quizás haya enviado facturas de ventas a un cliente pero también le haya comprado a ese cliente.Entonces lo vendiste por $300 pero lo compraste por $100.Puede esperar que su cliente le pague $200 para liquidar el saldo.¿Y qué pasa si vendiste por $500 pero el cliente te paga solo $250?

Así que tenía un problema muy complejo que resolver con muchas posibilidades de que un escenario funcionara perfectamente pero fuera incorrecto en otro tipo de combinación de factura/pago.

Aquí es donde las pruebas unitarias vinieron al rescate.

Comencé a escribir (dentro del código de prueba) un método para crear una lista de facturas, tanto de ventas como de compras.Luego escribí un segundo método para crear el pago real.Normalmente, un usuario ingresaría esa información a través de una interfaz de usuario.

Luego creé el primer TestMethod, probando un pago muy simple de una sola factura sin ningún descuento en el pago.Toda la acción en el sistema ocurriría cuando un pago bancario se guardara en la base de datos.Como puede ver, creé una factura, creé un pago (una transacción bancaria) y guardé la transacción en el disco.En mis afirmaciones pongo cuáles deberían ser los números correctos que terminan en la transacción bancaria y en la factura vinculada.Verifico el número de pagos, los montos de los pagos, el monto del descuento y el saldo de la factura después de la transacción.

Después de ejecutar la prueba, iría a la base de datos y verificaría si lo que esperaba estaba allí.

Después Escribí la prueba, comencé a codificar el método de pago (parte de la clase BankHeader).En la codificación solo me molesté con el código para pasar la primera prueba.Todavía no pensé en los otros escenarios, más complejos.

Ejecuté la primera prueba, solucioné un pequeño error hasta que pasó la prueba.

Luego comencé a escribir la segunda prueba, esta vez trabajando con un descuento en el pago.Después de escribir la prueba, modifiqué el método de pago para admitir descuentos.

Mientras probaba la corrección con un descuento por pago, también probé el pago simple.Por supuesto, ambas pruebas deberían pasar.

Luego fui bajando a los escenarios más complejos.

1) Piensa en un nuevo escenario

2) Escribe una prueba para ese escenario.

3) Ejecute esa única prueba para ver si pasa

4) Si no fuera así, depuraría y modificaría el código hasta que se aprobara.

5) Mientras modificaba el código, seguí ejecutando todas las pruebas.

Así logré crear mi método de pago muy complejo.Sin pruebas unitarias no sabía cómo empezar a codificar, el problema parecía abrumador.Con las pruebas pude comenzar con un método simple y extenderlo paso a paso con la seguridad de que los escenarios más simples seguirían funcionando.

Estoy seguro de que el uso de pruebas unitarias me ahorró unos días (o semanas) de codificación y garantiza más o menos la corrección de mi método.

Si luego pienso en un nuevo escenario, puedo agregarlo a las pruebas para ver si funciona o no.De lo contrario, puedo modificar el código pero aún así asegurarme de que los otros escenarios sigan funcionando correctamente.Esto ahorrará días y días en la fase de mantenimiento y corrección de errores.

Sí, incluso el código probado puede tener errores si un usuario hace cosas que usted no pensó o le impidió hacer.

A continuación se muestran solo algunas de las pruebas que creé para probar mi método de pago.

public class TestPayments
{
    InvoiceDiaryHeader invoiceHeader = null;
    InvoiceDiaryDetail invoiceDetail = null;
    BankCashDiaryHeader bankHeader = null;
    BankCashDiaryDetail bankDetail = null;



    public InvoiceDiaryHeader CreateSales(string amountIncVat, bool sales, int invoiceNumber, string date)
    {
        ......
        ......
    }

    public BankCashDiaryHeader CreateMultiplePayments(IList<InvoiceDiaryHeader> invoices, int headerNumber, decimal amount, decimal discount)
    {
       ......
       ......
       ......
    }


    [TestMethod]
    public void TestSingleSalesPaymentNoDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 1, "01-09-2008"));
        bankHeader = CreateMultiplePayments(list, 1, 119.00M, 0);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(119M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(0M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
    }

    [TestMethod]
    public void TestSingleSalesPaymentDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 2, "01-09-2008"));
        bankHeader = CreateMultiplePayments(list, 2, 118.00M, 1M);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(118M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(1M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
    }

    [TestMethod]
    [ExpectedException(typeof(ApplicationException))]
    public void TestDuplicateInvoiceNumber()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("100", true, 2, "01-09-2008"));
        list.Add(CreateSales("200", true, 2, "01-09-2008"));

        bankHeader = CreateMultiplePayments(list, 3, 300, 0);
        bankHeader.Save();
        Assert.Fail("expected an ApplicationException");
    }

    [TestMethod]
    public void TestMultipleSalesPaymentWithPaymentDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 11, "01-09-2008"));
        list.Add(CreateSales("400", true, 12, "02-09-2008"));
        list.Add(CreateSales("600", true, 13, "03-09-2008"));
        list.Add(CreateSales("25,40", true, 14, "04-09-2008"));

        bankHeader = CreateMultiplePayments(list, 5, 1144.00M, 0.40M);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(4, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(118.60M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(400, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
        Assert.AreEqual(600, bankHeader.BankCashDetails[0].Payments[2].PaymentAmount);
        Assert.AreEqual(25.40M, bankHeader.BankCashDetails[0].Payments[3].PaymentAmount);

        Assert.AreEqual(0.40M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].PaymentDiscount);

        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance);
    }

    [TestMethod]
    public void TestSettlement()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("300", true, 43, "01-09-2008")); //Sales
        list.Add(CreateSales("100", false, 6453, "02-09-2008")); //Purchase

        bankHeader = CreateMultiplePayments(list, 22, 200, 0);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(2, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(300, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(-100, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
    }

Si realmente son triviales, entonces no se moleste en realizar pruebas.Por ejemplo, si se implementan así;

public class User
{
    public string Username { get; set; }
    public string Password { get; set; }
}

Si, por otro lado, está haciendo algo inteligente (como cifrar y descifrar la contraseña en el getter/setter), pruébelo.

La regla es que debes probar cada pieza de lógica que escribas.Si implementó alguna funcionalidad específica en los captadores y definidores, creo que vale la pena probarla.Si sólo asignan valores a algunos campos privados, no te molestes.

Esta pregunta parece ser una cuestión de dónde trazar el límite entre qué métodos se prueban y cuáles no.

Los fijadores y captadores para la asignación de valor se han creado teniendo en cuenta la coherencia y el crecimiento futuro, y previendo que en algún momento el fijador/obtenedor pueda evolucionar hacia operaciones más complejas.Tendría sentido implementar pruebas unitarias de esos métodos, también en aras de la coherencia y el crecimiento futuro.

El objetivo principal es la confiabilidad del código, especialmente cuando se realizan cambios para agregar funcionalidad adicional.No tengo conocimiento de que nadie haya sido despedido por incluir setters/getters en la metodología de prueba, pero estoy seguro de que existen personas que desearían haber probado métodos que los últimos que conocían o podían recordar eran simples envoltorios set/get, pero eso no fue así. Ya el caso.

Quizás otro miembro del equipo amplió los métodos set/get para incluir lógica que ahora necesita ser probada pero que luego no creó las pruebas.Pero ahora su código llama a estos métodos y no sabe que cambiaron y necesitan pruebas en profundidad, y las pruebas que realiza en desarrollo y control de calidad no desencadenan el defecto, pero los datos comerciales reales del primer día de lanzamiento sí lo hacen. desencadenarlo.

Los dos compañeros de equipo ahora debatirán sobre quién dejó caer la pelota y no realizó las pruebas unitarias cuando el conjunto se transforme para incluir una lógica que puede fallar pero que no está cubierta por una prueba unitaria.Al compañero de equipo que originalmente escribió los set/gets le resultará más fácil salir limpio de esto si las pruebas se implementaron desde el primer día en los set/gets simples.

Mi opinión es que unos minutos de tiempo "desperdiciado" cubriendo TODOS los métodos con pruebas unitarias, incluso las triviales, podrían ahorrar días de dolores de cabeza en el futuro y pérdida de dinero/reputación del negocio y pérdida del trabajo de alguien.

Y el hecho de que envolviste métodos triviales con pruebas unitarias podría ser visto por ese compañero de equipo junior cuando cambie los métodos triviales a métodos no triviales y les solicite que actualicen la prueba, y ahora nadie está en problemas porque el defecto estaba contenido. de llegar a producción.

La forma en que codificamos y la disciplina que se puede ver en nuestro código pueden ayudar a otros.

Otra respuesta canónica.Esto, creo, de Ron Jeffries:

Pruebe solo el código que desea trabajar.

Probar código repetitivo es una pérdida de tiempo, pero como dice Slavo, si agrega un efecto secundario a sus captadores/definidores, entonces debe escribir una prueba que acompañe esa funcionalidad.

Si está realizando un desarrollo basado en pruebas, primero debe escribir el contrato (por ejemplo, la interfaz) y luego escribir las pruebas para ejercitar esa interfaz que documenten los resultados/comportamiento esperados. Entonces escriba sus métodos ellos mismos, sin tocar el código en sus pruebas unitarias.Finalmente, tome una herramienta de cobertura de código y asegúrese de que sus pruebas ejerciten todas las rutas lógicas en su código.

Los códigos realmente triviales, como captadores y definidores, que no tienen ningún comportamiento adicional aparte de establecer un campo privado, son excesivos para probar.En 3.0 C# incluso tiene algo de azúcar sintáctico donde el compilador se encarga del campo privado para que no tengas que programarlo.

Normalmente escribo muchas pruebas muy simples que verifican el comportamiento que espero de mis clases.Incluso si se trata de cosas simples como sumar dos números.Cambio mucho entre escribir una prueba simple y escribir algunas líneas de código.La razón de esto es que luego puedo cambiar el código sin tener miedo de romper cosas en las que no pensé.

Deberías probarlo todo.En este momento tienes captadores y definidores, pero algún día es posible que los cambies un poco, tal vez para realizar una validación o algo más.Las pruebas que escriba hoy se utilizarán mañana para asegurarse de que todo siga funcionando como de costumbre.Cuando escribes una prueba, debes olvidar consideraciones como "en este momento es trivial".En un contexto ágil o basado en pruebas, debe realizar pruebas suponiendo una refactorización futura.Además, ¿intentaste poner valores realmente extraños, como cadenas extremadamente largas u otro contenido "malo"?Bueno deberías...Nunca asumas cuán mal se puede abusar de tu código en el futuro.

En general, encuentro que escribir pruebas de usuario extensas es, por un lado, agotador.Por otro lado, siempre le brinda información invaluable sobre cómo debería funcionar su aplicación y lo ayuda a descartar suposiciones fáciles (y falsas) (como:el nombre de usuario siempre tendrá menos de 1000 caracteres).

Para módulos simples que pueden terminar en un conjunto de herramientas o en un tipo de proyecto de código abierto, debe probar tanto como sea posible, incluidos los captadores y definidores triviales.Lo que debes tener en cuenta es que generar una prueba unitaria mientras escribes un módulo en particular es bastante simple y directo.Agregar captadores y definidores es un código mínimo y se puede manejar sin pensarlo mucho.Sin embargo, una vez que su código se coloca en un sistema más grande, este esfuerzo adicional puede protegerlo contra cambios en el sistema subyacente, como cambios de tipo en una clase base.Probar todo es la mejor manera de tener una regresión completa.

No está de más escribir pruebas unitarias para sus captadores y definidores.En este momento, es posible que solo estén haciendo conjuntos/obtenciones de campos bajo el capó, pero en el futuro es posible que tenga lógica de validación o dependencias entre propiedades que deban probarse.Es más fácil escribirlo ahora mientras piensas en ello y luego recordar actualizarlo si llega ese momento.

En general, cuando un método sólo está definido para ciertos valores, pruebe los valores en y más la frontera de lo aceptable.En otras palabras, asegúrese de que su método haga lo que se supone que debe hacer, pero nada más.Esto es importante, porque cuando vas a fracasar, quieres fracasar temprano.

En las jerarquías de herencia, asegúrese de realizar pruebas para LSP cumplimiento.

Probar los captadores y definidores predeterminados no me parece muy útil, a menos que planees hacer alguna validación más adelante.

Según tengo entendido, las pruebas unitarias en el contexto del desarrollo ágil, Mike, sí, es necesario probar los captadores y definidores (suponiendo que sean públicamente visibles).El concepto completo de prueba unitaria es probar la unidad de software, que es una clase en este caso, como un caja negra.Dado que los captadores y definidores son visibles externamente, debe probarlos junto con Autenticar y Guardar.

Si los métodos Autenticar y Guardar usan las propiedades, entonces sus pruebas tocarán indirectamente las propiedades.Siempre que las propiedades solo proporcionen acceso a los datos, no deberían ser necesarias pruebas explícitas (a menos que busque una cobertura del 100%).

Probaría tus captadores y definidores.Dependiendo de quién escribe el código, algunas personas cambian el significado de los métodos getter/setter.He visto la inicialización de variables y otras validaciones como parte de los métodos getter.Para probar este tipo de cosas, querrás pruebas unitarias que cubran ese código explícitamente.

Personalmente, "probaría cualquier cosa que pueda romperse" y un captador simple (o incluso mejores propiedades automáticas) no se romperá.Nunca he tenido fallas en una declaración de devolución simple y, por lo tanto, nunca he realizado pruebas para ellas.Si los captadores tienen cálculos o alguna otra forma de declaración, ciertamente les agregaría pruebas.

Personalmente uso Cantidad mínima de pedido como un marco de objeto simulado y luego verificar que mi objeto llame a los objetos circundantes como debería.

Debe cubrir la ejecución de cada método de la clase con UT y verificar el valor de retorno del método.Esto incluye captadores y definidores, especialmente en el caso de que los miembros (propiedades) sean clases complejas, lo que requiere una gran asignación de memoria durante su inicialización.Llame al configurador con una cadena muy grande, por ejemplo (o algo con símbolos griegos) y verifique que el resultado sea correcto (no truncado, la codificación es buena, etc.)

En el caso de números enteros simples, eso también se aplica: ¿qué sucede si pasa un número largo en lugar de un número entero?Esa es la razón por la que escribes UT :)

No probaría la configuración real de las propiedades.Me preocuparía más cómo el consumidor puebla esas propiedades y con qué las puebla.Con cualquier prueba, hay que sopesar los riesgos con el tiempo y el coste de la prueba.

Debe probar "cada bloque de código no trivial" utilizando pruebas unitarias en la medida de lo posible.

Si sus propiedades son triviales y es poco probable que alguien introduzca un error en ellas, entonces debería ser seguro no realizar pruebas unitarias.

Sus métodos Authenticate() y Save() parecen buenos candidatos para realizar pruebas.

Lo ideal sería que hubieras realizado las pruebas unitarias mientras escribías la clase.Así es como debe hacerlo cuando utiliza Test Driven Development.Agrega las pruebas a medida que implementa cada punto de función, asegurándose de cubrir también los casos extremos con la prueba.

Escribir los exámenes después es mucho más doloroso, pero factible.

Esto es lo que haría en tu posición:

  1. Escriba un conjunto básico de pruebas que prueben la función principal.
  2. Obtenga NCover y ejecútelo en sus pruebas.La cobertura de su prueba probablemente será de alrededor del 50% en este momento.
  3. Siga agregando pruebas que cubran sus casos extremos hasta que obtenga una cobertura de alrededor del 80%-90%

Esto debería brindarle un buen conjunto funcional de pruebas unitarias que actuarán como un buen amortiguador contra las regresiones.

El único problema con este enfoque es que el código tiene que ser diseñado ser comprobable de esta manera.Si cometió algún error de acoplamiento desde el principio, no podrá obtener una cobertura alta con mucha facilidad.

Por eso es realmente importante escribir las pruebas antes de escribir el código.Te obliga a escribir código débilmente acoplado.

No pruebe el código que obviamente funciona (repetitivo).Entonces, si sus definidores y captadores son simplemente "valor de propiedad = valor" y "valor de propiedad de retorno", no tiene sentido probarlo.

Incluso get/set puede tener consecuencias extrañas, dependiendo de cómo se hayan implementado, por lo que deben tratarse como métodos.

Cada prueba de estas deberá especificar conjuntos de parámetros para las propiedades, definiendo propiedades aceptables e inaceptables para garantizar que las llamadas regresen o fallen de la manera esperada.

También debe tener en cuenta los problemas de seguridad, como un ejemplo de inyección SQL, y probarlos.

Entonces sí, debes preocuparte por probar las propiedades.

Creo que es una tontería probar captadores y definidores cuando solo realizan una operación simple.Personalmente, no escribo pruebas unitarias complejas para cubrir ningún patrón de uso.Intento escribir suficientes pruebas para asegurarme de haber manejado el comportamiento de ejecución normal y todos los casos de error que se me ocurren.Escribiré más pruebas unitarias como respuesta a los informes de errores.Utilizo pruebas unitarias para garantizar que el código cumpla con los requisitos y facilitar futuras modificaciones.Me siento mucho más dispuesto a cambiar el código cuando sé que si rompo algo, la prueba fallará.

Escribiría una prueba para cualquier cosa para la que esté escribiendo código que se pueda probar fuera de la interfaz GUI.

Por lo general, cualquier lógica que escribo que tenga lógica de negocios la coloco dentro de otro nivel o capa de lógica de negocios.

Entonces escribir pruebas para cualquier cosa que haga algo es fácil de hacer.

Primer paso, escriba una prueba unitaria para cada método público en su "Capa de lógica empresarial".

Si tuviera una clase como esta:

   public class AccountService
    {
        public void DebitAccount(int accountNumber, double amount)
        {

        }

        public void CreditAccount(int accountNumber, double amount)
        {

        }

        public void CloseAccount(int accountNumber)
        {

        }
    }

Lo primero que haría antes de escribir cualquier código sabiendo que tenía que realizar estas acciones sería comenzar a escribir pruebas unitarias.

   [TestFixture]
    public class AccountServiceTests
    {
        [Test]
        public void DebitAccountTest()
        {

        }

        [Test]
        public void CreditAccountTest()
        {

        }

        [Test]
        public void CloseAccountTest()
        {

        }
    }

Escribe tus pruebas para validar el código que has escrito para hacer algo.Si itera sobre una colección de cosas y cambia algo sobre cada una de ellas, escriba una prueba que haga lo mismo y afirme que realmente sucedió.

Hay muchos otros enfoques que puede adoptar, a saber, el desarrollo impulsado por el comportamiento (BDD), que es más complicado y no es un buen lugar para comenzar con sus habilidades de prueba unitaria.

Entonces, la moraleja de la historia es: pruebe cualquier cosa que haga algo que le pueda preocupar, mantenga las pruebas unitarias probando cosas específicas que sean de tamaño pequeño, muchas pruebas son buenas.

Mantenga su lógica de negocios fuera de la capa de la interfaz de usuario para que pueda escribir pruebas fácilmente para ellos y todo estará bien.

recomiendo TestDriven.Net o ReSharper ya que ambos se integran fácilmente en Visual Studio.

Bueno, si crees que se puede romper, escribe una prueba.Por lo general, no pruebo setter/getter, pero digamos que haces uno para User.Name, que concatena el nombre y el apellido, escribiría una prueba para que si alguien cambia el orden del apellido y el nombre, al menos lo sepa. cambió algo que fue probado.

La respuesta canónica es "probar cualquier cosa que pueda romperse". Si está seguro de que las propiedades no se rompen, no las pruebe.

Y una vez que se descubre que algo se ha roto (encuentra un error), obviamente significa que necesita probarlo.Escriba una prueba para reproducir el error, observe cómo falla, luego corrija el error y luego observe cómo pasa la prueba.

Recomendaría escribir varias pruebas para sus métodos Autenticar y Guardar.Además del caso de éxito (donde se proporcionan todos los parámetros, todo está escrito correctamente, etc.), es bueno tener pruebas para varios casos de falla (parámetros incorrectos o faltantes, conexiones de bases de datos no disponibles, si corresponde, etc.).recomiendo Pruebas unitarias pragmáticas en C# con NUnit como una referencia.

Como han dicho otros, las pruebas unitarias para captadores y definidores son excesivas, a menos que haya lógica condicional en sus captadores y definidores.

Si bien es posible adivinar correctamente dónde necesita probar su código, generalmente creo que necesita métricas para respaldar esta suposición.En mi opinión, las pruebas unitarias van de la mano con las métricas de cobertura de código.

Código con muchas pruebas pero una pequeña cobertura no ha sido bien probada.Dicho esto, el código con una cobertura del 100% pero sin probar los límites y los casos de error tampoco es excelente.

Quiere un equilibrio entre una alta cobertura (90% mínimo) y datos de entrada variables.

¡Recuerde realizar una prueba de "basura adentro"!

Además, una prueba unitaria no es una prueba unitaria a menos que verifique si hay una falla.Las pruebas unitarias que no tienen afirmaciones o están marcadas con excepciones conocidas simplemente probarán que el código no muere cuando se ejecuta.

¡Debe diseñar sus pruebas para que siempre informen fallas o datos inesperados/no deseados!

Mejora nuestro código...¡período!

Una cosa que los desarrolladores de software olvidamos cuando realizamos un desarrollo basado en pruebas es el propósito detrás de nuestras acciones.Si se escribe una prueba unitaria después de que el código de producción ya está implementado, el valor de la prueba disminuye considerablemente (pero no se pierde por completo).

En el verdadero espíritu de las pruebas unitarias, estas pruebas son no principalmente para "probar" más de nuestro código;o para obtener una cobertura de código entre un 90 % y un 100 % mejor.estos son todos beneficios complementarios de escribir las pruebas primero.La gran recompensa es que nuestro código de producción termina escrito mucho mejor debido al proceso natural de TDD.

Para ayudar a comunicar mejor esta idea, la siguiente lectura puede resultar útil:

La teoría defectuosa de las pruebas unitarias
Desarrollo de software con propósito

Si sentimos que el acto de escribir más pruebas unitarias es lo que nos ayuda a obtener un producto de mayor calidad, entonces podemos estar sufriendo de un Culto a la carga de Desarrollo Dirigido por Pruebas.

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