unit-testing - pruebas - unit test android
¿Cómo pruebas unidades de aplicaciones comerciales? (6)
Depende de lo que estás probando. Si está probando un componente de lógica de negocios, entonces es inmaterial de dónde provienen los datos y probablemente usaría un simulacro o una clase de stub enrollada a mano que simula la rutina de acceso a datos que el componente habría llamado en la naturaleza. La única vez que me meto con el acceso a los datos es cuando en realidad estoy probando los componentes de acceso a los datos por sí mismos.
Incluso entonces tiendo a abrir una transacción de base de datos en el método TestFixtureSetUp (obviamente esto depende de qué marco de prueba de unidad pueda estar usando) y retrotraer la transacción al final del conjunto de pruebas TestFixtureTeardown.
¿Cómo evalúan las personas las pruebas de sus aplicaciones comerciales? He visto muchos ejemplos de pruebas unitarias con ejemplos "simples para probar". Ex. una calculadora. ¿Cómo son las pruebas unitarias de unidades de aplicaciones pesadas? ¿Cómo estás reuniendo tus datos de muestra? En muchos casos, los datos de una prueba pueden no funcionar en absoluto para otra prueba que hace que sea difícil tener una sola base de datos de prueba.
Probar la parte de acceso a datos del código es bastante sencillo. Está probando todos los métodos que funcionan contra los datos que parecen ser difíciles de probar. Por ejemplo, imagina un proceso de publicación donde hay un gran acceso a datos para determinar lo que se publica, se ajustan los números, etc. Hay una serie de pasos intermedios que se producen (y deben probarse) junto con pruebas posteriores que aseguran que la publicación fue exitoso. Algunos de esos pasos en realidad pueden ser procedimientos almacenados.
En el pasado intenté insertar los datos de prueba en una base de datos de prueba y luego ejecutar la prueba, pero sinceramente es bastante doloroso escribir este tipo de código (y propenso a errores). También intenté construir una base de datos de prueba por adelantado y deshacer los cambios. Eso funciona bien, pero en varios lugares no puedes hacer esto fácilmente (y mucha gente diría que eso es una prueba de integración, así que, aún así, tengo que ser capaz de probar esto de alguna manera).
Si la respuesta es que no hay una buena manera de manejar esto y que actualmente solo es una mierda, sería útil saberlo también.
Cualquier pensamiento, idea, sugerencia o sugerencia es apreciada.
Mocking Frameworks le permite probar sus objetos comerciales. Las pruebas basadas en datos a menudo terminan convirtiéndose en una prueba de integración más que en una unidad, también llevan consigo la carga de administrar el estado de un almacén de datos antes y después de la ejecución de la prueba y el tiempo necesario para conectar y ejecutar consultas.
En general, evitaría hacer pruebas unitarias que toquen la base de datos de sus objetos comerciales. En cuanto a la prueba de su base de datos necesita una estrategia diferente.
Dicho esto, nunca puede alejarse totalmente de las pruebas basadas en datos, solo limitando la cantidad de pruebas que realmente necesitan invocar sus sistemas de back-end.
Para muchas ejecuciones diferentes en la misma lógica pero con datos diferentes, puede usar CSV, tantas columnas como desee para la entrada y la última para la salida, etc.
Parece que podría estar probando sistemas basados en mensajes, o sistemas con interfaces altamente parametrizadas, donde hay un gran número de permutaciones de datos de entrada.
En general, todas las reglas de las pruebas unti estándar aún se mantienen:
- Intenta hacer que las unidades sean probadas de la manera más pequeña y discreta posible.
- Intenta hacer las pruebas de forma independiente.
- Código de factor para desacoplar dependencias.
- Utilice simulaciones y resguardos para reemplazar dependencias (como acceso a datos)
Una vez hecho esto, habrá eliminado gran parte de la complejidad de las pruebas, con suerte revelando buenos conjuntos de pruebas unitarias y simplificando los datos de muestra.
Una buena metodología para compilar datos de muestra para pruebas que aún requieren datos de entrada complejos es la prueba ortogonal , o vea aquí .
He usado ese tipo de método para generar planes de prueba para las soluciones WCF y BizTalk, donde las permutaciones de los mensajes de entrada pueden crear múltiples rutas de ejecución posibles.
Mis pruebas funcionales automatizadas generalmente siguen uno de dos patrones:
- Pruebas conectadas a base de datos
- Pruebas de capa de persistencia falsa
Pruebas conectadas a base de datos
Cuando tengo pruebas automáticas que están conectadas a la base de datos, generalmente hago una sola plantilla de base de datos de prueba que tiene suficientes datos para todas las pruebas. Cuando se ejecutan las pruebas automatizadas, se genera una nueva base de datos de prueba a partir de la plantilla para cada prueba. La base de datos de prueba se debe volver a generar constantemente porque la prueba a menudo cambiará los datos. A medida que se agregan las pruebas, generalmente agrego más datos a la plantilla de la base de datos de prueba.
Hay algunas buenas ventajas para este método de prueba. La ventaja obvia es que las pruebas también ejercen su esquema. Otra ventaja es que después de configurar las pruebas iniciales, la mayoría de las pruebas nuevas podrán reutilizar los datos de prueba existentes. Esto hace que sea más fácil agregar más pruebas.
El inconveniente es que la base de datos de prueba se volverá difícil de manejar. Debido a que los datos generalmente se agregarán una prueba cada vez, serán inconsistentes e incluso poco realistas. También terminará maldiciendo a la persona que configuró la base de datos de prueba cuando hay un cambio significativo en el esquema de la base de datos (lo cual para mí significa que termino maldiciéndome).
Evidentemente, este estilo de prueba no funciona si no puede generar nuevas bases de datos de prueba a voluntad.
Pruebas de capa de persistencia falsa
Para este patrón, crea objetos simulados que viven con los casos de prueba. Estos objetos falsos interceptan las llamadas a la base de datos para que pueda proporcionar los resultados apropiados mediante programación. Básicamente, cuando el código que está probando llama al método findCustomerByName()
, se llama a su objeto simulado en lugar de a la capa de persistencia.
Lo bueno de usar pruebas de objetos simulados es que puedes ser muy específico. Muchas veces, hay rutas de ejecución que simplemente no puede alcanzar en pruebas automatizadas sin objetos simulados. También lo liberan de mantener un conjunto grande y monolítico de datos de prueba.
Otro beneficio es la falta de dependencias externas. Debido a que los objetos simulados simulan la capa de persistencia, sus pruebas ya no dependen de la base de datos. Este es a menudo el factor decisivo al elegir qué patrón elegir. Los objetos simulados parecen obtener más tracción cuando se trata de sistemas de bases de datos heredados o bases de datos con términos de licencia estrictos.
La desventaja de los objetos falsos es que a menudo dan como resultado una gran cantidad de código de prueba adicional. Esto no es horrible porque casi cualquier cantidad de código de prueba es barato cuando se amortiza sobre la cantidad de veces que ejecuta la prueba, pero puede ser molesto tener más código de prueba que código de producción.
Tengo que secundar el comentario de @Phil Bennett mientras intento acercarme a estas pruebas de integración con una solución de reversión.
Tengo una publicación muy detallada sobre la integración de pruebas de su capa de acceso a datos aquí
Muestro no solo la clase de acceso de datos de muestra, la clase base y la clase de dispositivo de transacción DB de muestra, sino también una prueba de integración completa de CRUD con los datos de muestra mostrados. Con este enfoque, no necesita múltiples bases de datos de prueba, ya que puede controlar los datos que entran con cada prueba y, una vez finalizada la prueba, todas las transacciones se cancelan, por lo que su base de datos está limpia.
Acerca de la lógica empresarial de las pruebas de unidad dentro de su aplicación, también secundo los comentarios de @Phil y @Mark porque si se burlan de todas las dependencias que tiene su objeto comercial, es muy simple probar la lógica de la aplicación una entidad a la vez;)
Edición: ¿Está buscando una prueba de integración enorme que verifique todo, desde la base de datos previa lógica / procedimiento almacenado ejecute w / logic y finalmente una verificación en el camino de regreso? Si es así, puedes dividir esto en 2 pasos:
1 - Prueba de la unidad la lógica que ocurre antes de que los datos se inserten en su código de acceso a datos. Por ejemplo, si tiene algún código que calcule algunos números en función de algunas propiedades, escriba una prueba que solo verifique si la lógica de esta función 1 hace lo que le pidió que hiciera. Cree una dependencia de la clase de acceso a los datos para que pueda ignorarla solo para esta prueba de la lógica de la aplicación.
2 - Prueba de integración la lógica que ocurre una vez que toma sus datos manipulados (del método anterior que probamos en la unidad) y llama al procedimiento almacenado apropiado. Haga esto dentro de una clase de prueba específica de datos para que pueda deshacerla después de que se complete. Después de que se haya ejecutado su procedimiento almacenado, haga una consulta en la base de datos para obtener su objeto ahora que hemos hecho algo de lógica contra los datos y verifique que tenga los valores que esperaba (lógica de procedimiento almacenada posteriormente / etc)
Si necesita una entrada en su base de datos para que se ejecute el procedimiento almacenado, simplemente inserte esa información antes de ejecutar el sproc que tiene su lógica dentro de él. Por ejemplo, si tiene un producto que necesita probar, puede ser necesario insertar un proveedor y una categoría para insertarlo, por lo que antes de insertar el producto, haga una inserción rápida y sucia para un proveedor y categoría para que su inserción de producto funcione según lo planeado.