c++ - framework - google test install
Cómo escribir buenas pruebas unitarias? (10)
Hoy en día, Test Driven Development es el enfoque para administrar grandes proyectos de software con facilidad.
Eso es porque TDD le permite asegurarse después de cada cambio que todo lo que funcionó antes del cambio aún funciona, y si no le permite identificar qué se rompió, mucho más fácil. (ver al final)
¿Qué es una prueba unitaria? ¿Es una lista completa de casos de prueba que deben analizarse?
Una prueba de unidad es una pieza de código que le pide a una "unidad" de su código que realice una operación, luego verifica que la operación efectivamente se realizó y el resultado es el esperado. Si el resultado no es correcto, aumenta / registra un error.
Así que digamos que tengo una clase llamada "Números complejos" con algunos métodos (permite encontrar un conjugado, un operador de asignación sobrecargado y un operador de multiplicación sobrecargado. ¿Cuáles deberían ser los casos típicos de prueba para una clase así? ¿Hay alguna metodología? para seleccionar casos de prueba?
Idealmente, probarías todo el código.
cuando crea una instancia de la clase, se crea con los valores predeterminados correctos
cuando le pide que encuentre los conjugados, encuentra los correctos (también prueba los casos de borde, como el conjugado para cero)
cuando asigna un valor, el valor se asigna y se muestra correctamente
cuando multiplicas un complejo por un valor, se multiplica correctamente
¿Hay marcos que puedan crear pruebas de unidad para mí o tengo que escribir mi propia clase para las pruebas?
Ver CppUnit
Veo una opción de "Prueba" en Visual Studio 2008, pero nunca funcionó.
No estoy seguro de eso. No utilicé VS 2008 pero puede estar disponible solo para .NET.
¿Cuál es el criterio para las pruebas de Unidades? ¿Debería haber una prueba unitaria para cada función en una clase? ¿Tiene sentido tener pruebas unitarias para cada clase?
Sí, lo hace. Si bien es una gran cantidad de código para escribir (y mantener con cada cambio) el precio vale la pena pagar por proyectos grandes: garantiza que sus cambios en la base de códigos hacen lo que usted quiere y nada más .
Además, cuando realiza un cambio, necesita actualizar las pruebas unitarias para ese cambio (para que pasen nuevamente).
En TDD, primero decides qué quieres que haga el código (digamos, tu clase de números complejos), luego escribes las pruebas que verifican esas operaciones y luego escribes la clase para que las pruebas se compilen y se ejecuten correctamente (y nada más).
Esto garantiza que escriba el código mínimo posible (y no complique demasiado el diseño de la clase compleja) y también asegura que su código haga lo que hace. Al final de escribir el código, tiene una forma de probar su funcionalidad y garantizar su corrección.
También tiene un ejemplo de usar el código al que podrá acceder en cualquier momento.
Para obtener más información / lectura, busque "inyecciones de dependencia" y resúmenes de métodos como se usan en pruebas unitarias y TDD.
¿Alguien podría sugerir libros o materiales para aprender la prueba unitaria?
Algunas personas consideran códigos sin pruebas unitarias como códigos heredados. Hoy en día, Test Driven Development es el enfoque para administrar grandes proyectos de software con facilidad. Me gusta mucho C ++, lo aprendí solo sin ninguna educación formal. Nunca examiné Unit Test antes, así que siéntete excluido. Creo que las pruebas unitarias son importantes y serían útiles a largo plazo. Agradecería cualquier ayuda sobre este tema.
Mis principales puntos de preocupación son:
¿Qué es una prueba unitaria? ¿Es una lista completa de casos de prueba que deben analizarse? Así que digamos que tengo una clase llamada "Números complejos" con algunos métodos (permite encontrar un conjugado, un operador de asignación sobrecargado y un operador de multiplicación sobrecargado. ¿Cuáles deberían ser los casos típicos de prueba para una clase así? ¿Hay alguna metodología? para seleccionar casos de prueba?
¿Hay algún marco que pueda crear pruebas unitarias para mí o tengo que escribir mi propia clase para las pruebas? Veo una opción de "Prueba" en Visual Studio 2008, pero nunca funcionó.
¿Cuál es el criterio para las pruebas de Unidades? ¿Debería haber una prueba unitaria para cada función en una clase? ¿Tiene sentido tener pruebas unitarias para cada clase?
Hoy en día, Test Driven Development es el enfoque para administrar grandes proyectos de software con facilidad.
TDD construido en pruebas unitarias, pero son diferentes. No necesita usar TDD para hacer uso de pruebas unitarias. Mi preferencia personal es escribir primero la prueba, pero no siento que haga todo el TDD.
¿Qué es una prueba unitaria?
Una prueba de unidad es un poco de código que prueba el comportamiento de una unidad. Cómo se define una unidad difiere entre las personas. Pero en general son:
- Rápido para correr
- Independiente el uno del otro
- Pruebe solo una pequeña parte (una unidad;) de su base de códigos.
- Resultado binario: es que pasa o falla.
- Solo debería probar un resultado de la unidad (para cada resultado crear una prueba de unidad diferente)
- Repetible
¿Son sus frameworks los que pueden crear pruebas unitarias
Para escribir las pruebas, sí, pero nunca he visto a nadie decir nada bueno sobre ellas.
Para ayudarlo a escribir y ejecutar pruebas, un montón de ellos.
¿Debería haber una prueba unitaria para cada función en una clase?
Tienes varios campamentos diferentes en esto: los 100% dirían que sí. Todos los métodos deben probarse y debe tener una cobertura de código del 100%. El otro extremo es que las pruebas unitarias solo deberían cubrir áreas en las que incluso has encontrado errores o esperas encontrar errores. El punto medio (y el soporte que tomo) es que la unidad prueba todo lo que no es "demasiado fácil de romper". Setters / getters y cualquier cosa que solo llame a un solo otro método. Mi objetivo es tener una cobertura de código del 80% y un factor de CRAP bajo (por lo que hay pocas posibilidades de que haya sido malo y decidí no probar algo, ya que era "demasiado complejo para probar").
El libro que me ayudó a "obtener" pruebas unitarias JUnit en acción . Lo siento, no hago mucho en el mundo C ++, así que no puedo sugerir una alternativa basada en C ++.
Con el diseño basado en pruebas, normalmente desea escribir las pruebas primero. Deben cubrir las operaciones que realmente usa / va a usar. Es decir, a menos que sean necesarios para que el código del cliente haga su trabajo, no deberían existir. Seleccionar casos de prueba es algo así como un arte. Hay cosas obvias como probar las condiciones de frontera, pero al final, nadie ha encontrado una manera realmente confiable y sistemática de garantizar que las pruebas (de unidad u otras) cubran todas las condiciones que importan.
Sí, hay marcos. Un par de los más conocidos son:
Boost Unit Test Framework
CppUnitCPPUnit es un puerto de JUnit, por lo que aquellos que usaron JUnit anteriormente probablemente lo encuentren cómodo. De lo contrario, tendería a recomendar Boost, sino que también tienen una biblioteca de pruebas para ayudar a escribir las pruebas individuales, algo bastante útil.
Las pruebas unitarias deben ser suficientes para garantizar que el código funcione. Si (por ejemplo) tiene una función privada que se usa internamente, generalmente no necesita probarla directamente. En cambio, prueba lo que proporciona la interfaz pública. Mientras eso funcione correctamente, no es asunto del mundo exterior cómo hace su trabajo. Por supuesto, en algunos casos es más fácil probar pequeñas piezas, y cuando lo es, eso es perfectamente legítimo, pero en última instancia te importa la interfaz visible, no las partes internas. Ciertamente, se debe ejercer toda la interfaz externa, y los casos de prueba generalmente elegidos para ejercer las rutas a través del código. Una vez más, no hay nada masivamente diferente sobre las pruebas unitarias versus otros tipos. Es principalmente una forma más sistemática de aplicar técnicas de prueba normales.
Aquí hay algo sobre cuándo no escribir pruebas unitarias (es decir, cuándo es viable e incluso preferible omitir las pruebas unitarias): ¿Debería uno probar la implementación interna o solo probar el comportamiento público?
La respuesta corta es:
- Cuando puede automatizar las pruebas de integración (porque es importante tener pruebas automatizadas, pero esas pruebas no tienen que ser pruebas unitarias)
- Cuando es barato ejecutar el paquete de prueba de integración (no es bueno si se tarda dos días en ejecutarse, o si no puede permitirse que todos los desarrolladores tengan acceso a un equipo de prueba de integración)
- Cuando no es necesario encontrar errores antes de la prueba de integración (que depende en parte de si los componentes se desarrollan por separado o de forma incremental)
Compre el libro "xUnit Test Patterns: Refactoring Test Code". Es muy excelente. Abarca decisiones de estrategia de alto nivel, así como patrones de prueba de bajo nivel.
En .NET recomiendo encarecidamente "The Art of Unit Testing" de Roy Osherove, es muy completo y está lleno de buenos consejos.
Las pruebas unitarias son simplemente una forma de ejercitar un cuerpo de código dado para garantizar que un conjunto definido de condiciones conduzca al conjunto esperado de salidas. Como Steven señala, estos "ejercicios" deben verificar a través de un rango de criterios ("BICEP"). Sí, idealmente debería probar todas sus clases y todos los métodos de estas clases, aunque siempre hay margen de apreciación: las pruebas no deberían ser un fin en sí mismas, sino que deberían respaldar los objetivos más amplios del proyecto.
Ok, entonces ... la teoría es buena, pero para realmente entender Unit Testing, mi recomendación sería juntar las herramientas apropiadas y comenzar. Como la mayoría de las cosas en programación, si tiene las herramientas adecuadas, es fácil aprender haciendo.
Primero, toma una copia de NUnit . Es gratis, fácil de instalar y fácil de usar. Si desea alguna documentación, consulte Pruebas de unidades pragmáticas en C # con NUnit.
Luego, vaya a http://www.testdriven.net/ y obtenga una copia de TestDriven.net. Se instala en Visual Studio 2008 y le da acceso con un clic derecho a una gama completa de herramientas de prueba, incluida la capacidad de ejecutar pruebas NUnit contra un archivo, directorio o proyecto (por lo general, las pruebas se escriben en un proyecto separado). También puede ejecutar pruebas con la depuración o, lo mejor de todo, ejecutar todas las pruebas en una copia de NCover. NCover le mostrará exactamente qué código se está ejerciendo para que pueda averiguar dónde necesita mejorar su cobertura de prueba. TestDriven.net cuesta $ 170 por una licencia profesional pero, si eres como yo, se convertirá muy rápidamente en una herramienta integral en tu caja de herramientas. De todos modos, he encontrado que es una excelente inversión profesional.
¡Buena suerte!
No puedo responder su pregunta para Visual Studio 2008, pero sé que Netbeans tiene algunas herramientas integradas para que pueda usar.
- La cobertura de código dos le permite ver qué rutas se han verificado y qué parte del código está cubierto por las pruebas unitarias.
- Tiene el soporte para las pruebas unitarias incorporadas.
En cuanto a la calidad de las pruebas, tomo prestado un poco de las " Pruebas unitarias pragmáticas en Java con JUnit " de Andrew Hunt y David Thomas:
Las pruebas unitarias deben verificar BICEP : B límite, I relaciones inversas, C ross-checking, E rror conditions y P erformance.
También la calidad de las pruebas está determinada por A-TRIP : A utomatic, T horough, R epeatable, I ndependent y P rofessional.
Si bien ya has aceptado una respuesta a tu pregunta, me gustaría recomendar algunos otros libros que aún no se mencionaron:
- Trabajando eficazmente con el código heredado: Michael Feathers: Hasta donde yo sé, este es el único libro que aborda adecuadamente el tema de convertir el código existente que no fue diseñado para la prueba en un código comprobable. Escrito como más un manual de referencia, se divide en tres secciones: una visión general de las herramientas y técnicas, una serie de guías tópicas para bloques de ruta comunes en código heredado, un conjunto de técnicas específicas de interrupción de dependencia referenciadas en el resto del libro .
- Principios, patrones y prácticas ágiles - Robert C. Martin - Ejemplos en java, hay una secuela con ejemplos en C #. Ambos son fáciles de adaptar a C ++
- Código de limpieza: un manual de artesanía de software ágil - Robert C. Martin - Martin describe esto como una precuela de sus libros de APPP y estoy de acuerdo. Este libro justifica el profesionalismo y la autodisciplina, dos cualidades esenciales en cualquier desarrollador serio de software.
Los dos libros de Robert (Uncle Bob) Martin cubren mucho más material que las pruebas unitarias, pero nos llevan a casa lo beneficiosas que pueden ser las pruebas unitarias para codificar la calidad y la productividad. Me refiero a referirme a estos tres libros de forma regular.
Un punto importante (que no me di cuenta al principio) es que Unit Testing es una técnica de prueba que puede usarse por sí misma, sin la necesidad de aplicar la metodología Test Driven completa.
Por ejemplo, tiene una aplicación heredada que desea mejorar agregando pruebas unitarias a las áreas problemáticas, o si desea encontrar errores en una aplicación existente. Ahora escribe una prueba unitaria para exponer el código del problema y luego arreglarlo. Se basan en pruebas semi, pero pueden integrarse completamente con su proceso de desarrollo actual (que no es TDD).
Dos libros que he encontrado útiles son:
Desarrollo impulsado por prueba en Microsoft .NET
Una mirada muy práctica al desarrollo de Test Driven, continuación del libro original de TDD de Kent Becks.
Pruebas unitarias pragmáticas con C # y nUnit
Llega directamente al punto de qué son las pruebas unitarias y cómo aplicarlas.
En respuesta a tus puntos:
Una prueba de unidad, en términos prácticos es un método único en una clase que contiene el código justo para probar un aspecto / comportamiento de su aplicación. Por lo tanto, a menudo tendrá muchas pruebas de unidad muy simples, cada una probando una pequeña parte de su código de aplicación. En nUnit, por ejemplo, creas una clase TestFixture que contiene cualquier cantidad de métodos de prueba. El punto clave es que las pruebas "prueban una unidad" de su código, es decir, una unidad (sensible) lo más pequeña posible. No prueba las API subyacentes que usa, solo el código que ha escrito.
Hay marcos que pueden quitar parte del trabajo pesado de crear clases de prueba, sin embargo, no los recomiendo. Para crear pruebas de unidad útiles que en realidad proporcionan una red de seguridad para la refactorización, no hay otra alternativa más que que un desarrollador piense qué y cómo probar su código. Si comienza a depender de la generación de pruebas unitarias, es muy fácil verlas como una tarea más que debe hacerse. Si te encuentras en esta situación lo estás haciendo completamente mal.
No hay reglas simples sobre cuántas pruebas unitarias por clase, método, etc. Necesita ver su código de aplicación y hacer una evaluación educada de dónde existe la complejidad y escribir más pruebas para estas áreas. La mayoría de las personas comienza probando métodos públicos solo porque estos a su vez suelen usar el resto de los métodos privados. Sin embargo, este no es siempre el caso y, en ocasiones, es necesario probar métodos privados.
En resumen, incluso los probadores de unidades experimentados comienzan escribiendo pruebas unitarias obvias, luego buscan pruebas más sutiles que se vuelven más claras una vez que han escrito las pruebas obvias. No esperan obtener todas las pruebas por adelantado, sino que las agregan a medida que vienen a su mente.