Un poco de contexto: hoy tuve que actualizar un código SQL que otro colega mío proporcionó, y dado que es un script bastante grande, se almacena como un archivo separado (que luego se lee y se ejecuta en tiempo de ejecución). Mientras hacía esto, accidentalmente reintroduje dos errores que tuvimos hace unos meses, a saber:
- Por alguna razón, el archivo ASCII fue codificado en UTF-16 (el colega me envió el archivo por correo electrónico, lo que podría haberlo causado).
- Al script le faltaban las
SET
declaraciones iniciales (requeridas debido a algunos elementos del controlador en producción, pero no en una instalación limpia localmente).
Después de depurar esto durante aproximadamente una hora (nuevamente) decidí escribir algunas pruebas unitarias para asegurar que esto nunca vuelva a suceder (e incluir una forma rápida de solucionarlo en el mensaje de afirmación para proporcionar una solución fácil para futuros desarrolladores).
Sin embargo, cuando introduje este código, otro colega (que también es el líder de nuestro equipo) se me acercó y me dijo que no debería volver a hacer estas cosas porque:
"Estas cosas no pertenecen a las pruebas unitarias"
"Las pruebas unitarias solo deben usarse para verificar el flujo de su código"
Ahora estoy bastante en conflicto ya que sigo pensando que lo que estoy haciendo no está mal, ya que este error no se reintroducirá en el futuro, sin embargo, este colega trabaja como senior y al final del día decide qué pasamos nuestro tiempo en ¿Qué tengo que hacer? ¿Me equivoco por hacerlo de esta manera? ¿Se considera una mala práctica?
fuente
Respuestas:
Lo más probable es que las pruebas que escribió estén más cerca de las pruebas de integración o regresión que las pruebas unitarias. Si bien la línea puede ser muy difusa y a veces se convierte en pedantería sobre lo que es o no una prueba unitaria, volvería a su colega y le preguntaría dónde deberían estar las pruebas que escribió, ya que agregan valor y garantizan la corrección del código.
No me enfocaría demasiado en lo que es o no es una prueba unitaria y me doy cuenta de que incluso si se trata de una prueba de integración, aún podría haber valor en la prueba.
fuente
Técnicamente, no es una prueba unitaria, y más bien un paso de validación. El enfoque adecuado realmente depende de cuál sea su flujo de trabajo. El líder de su equipo tiene razón sobre cuál es el propósito de las pruebas unitarias. Mi sensación es que este es un caso de usar la herramienta incorrecta para un trabajo que todavía debe hacerse. Entonces comience con esto:
Según la descripción, debe validar que cualquier script de base de datos cumpla con algunos estándares.
La calidad del código fuente generalmente se verifica mediante herramientas de análisis estático . Si no tiene una herramienta de análisis estático para validar su SQL, puede crear una herramienta rápida y sucia que realice la verificación de cualquier archivo SQL que se le pase. No está de más comprobar si hay herramientas de análisis estático que puedan manejar los problemas de los que está hablando.
Si integra esa infraestructura de compilación, como incorporarla a Jenkins o algo así, se puede aplicar a todos los archivos SQL de su proyecto.
Las pruebas unitarias solo resuelven el problema de su archivo actual.
Esto es bastante fácil, hablas con el líder de tu equipo. Él puede trabajar con el propietario del producto y con usted para determinar el riesgo / recompensa de invertir en las herramientas. Si es probable que sea un problema único, entonces las herramientas probablemente serían excesivas. Si las herramientas para atrapar los problemas más grandes son fáciles, puede valer la pena solo por el control de la cordura.
El líder de su equipo puede tener algunas ideas que usted (o yo) no hemos considerado, que pueden abordar el problema más correctamente.
fuente
Es una mala práctica llamar a las pruebas que acceden a los archivos "Pruebas unitarias".
Desafortunadamente, qué tipo de pruebas existen y cómo se organizan es completamente específico de la compañía. Por lo tanto, deberá averiguar cómo maneja su empresa estas pruebas.
Si aún no tiene una forma de ejecutar pruebas automáticas que no sean Pruebas unitarias, el enfoque pragmático es marcar las Pruebas unitarias que en realidad no son Pruebas unitarias con un prefijo, hasta que tenga suficientes para comenzar a averiguar qué tipo de pruebas que realmente tiene / necesita. Después de eso puedes comenzar a organizar.
fuente
Michael Feathers dice esto en su libro Working Effectively With Legacy Code:
¿Su prueba ayudará a localizar errores rápidamente y a ejecutarse rápidamente? Si es así, ¡hazlo! Si no, ¡no lo hagas! ¡Es tan simple como eso!
Dicho esto, estás trabajando en un entorno con otras personas y tienes que llevarte bien con ellas. Puede que tengas que terminar haciéndolo a su manera, incluso si no estás de acuerdo en privado.
fuente
He escrito pruebas similares, en ocasiones, contra archivos de código fuente, archivos de configuración, etc. No los llamaría pruebas unitarias porque (a) están accediendo al sistema de archivos y pueden no ser ultrarrápidos (b) No me importa si se ejecutan en cada check-in (en lugar de todas las noches en un Servidor CI).
Puede llamarlos pruebas de integración; ciertamente, están más cerca de esa perspectiva que las pruebas unitarias.
Mi propio término para ellos es pruebas de recursos . En mi humilde opinión, están completamente justificados si se ejecutan todas las noches en un servidor de CI: hay un costo mínimo y, cuando se usan con prudencia, claramente agregan valor. Una definición de juicioso : si la prueba está verificando un problema que causó un problema (como la codificación que usted menciona).
fuente
Una prueba unitaria se trata de probar un método o 'unidad' de código. Estás probando el grupo más pequeño de lógica y código en tu software.
Más tarde, cuando se una a otras unidades, realizará pruebas de integración.
Espero que el líder de su equipo haya alentado su iniciativa y debería haberle ofrecido sugerencias alternativas. Definitivamente tienes la idea correcta.
Su SQL es un código como cualquier lenguaje de generación inferior como C # o Java y debe probarse como tal. Y la verificación y validación pertenecen a todos los niveles de prueba. Por lo tanto, las instrucciones de codificación y SET están incluidas, pero no necesariamente se prueban exclusivamente. Por lo general, como terminaciones de línea o cerramientos, generalmente puede usar un gancho o función SCM.
La mejor práctica es tener pruebas de regresión para garantizar que los errores pasados no se reintroduzcan. En general, las pruebas se crean junto con cualquier resolución del error. Si estos errores no están cubiertos por las pruebas de regresión a nivel de unidad / integración o sistema y luego se reintroducen, es un problema de equipo, un problema de proceso, no individual.
La cuestión es ... los errores de sintaxis, las declaraciones que faltan o los bloques lógicos dentro de una 'unidad' generalmente no se prueban. Está probando las entradas y salidas de la unidad en diferentes combinaciones, probando las muchas posibilidades que podrían generarse.
Volviendo a las declaraciones SET perdidas: ayudan a informar las muchas posibilidades de entrada y salida para probar. ¿Qué prueba escribirías que FALLARÍA si te faltara un SET elegido?
fuente
Si tiene archivos que se convierten en parte de su producto, entonces su contenido debe ser correcto. No hay razón por la que no verifiques esto. Por ejemplo, si necesita seis imágenes de 1024x 1024 en alguna carpeta, escriba una prueba unitaria que compruebe que tiene exactamente eso.
Pero probablemente no solo tenga los archivos, también tiene un código que lee los archivos. Podrías escribir una prueba unitaria para ese código. En el ejemplo anterior, la función para leer una de las seis imágenes devuelve una imagen de 1024 x 1024 en la memoria (o lo que se suponía que debía producir).
De todos modos, puede que no sea una prueba unitaria, pero es una prueba útil. Y si usa un marco de prueba de unidad que le permite hacer una prueba útil (que no es una prueba de unidad), ¿por qué no usar el marco de prueba de unidad?
fuente
Quizás estoy malinterpretando su problema, pero para mí esto suena como un problema que no debería necesitar ser capturado por ningún tipo de prueba dedicada, sino simplemente por el sistema de control de versiones . Cualquier cambio en una base de código debe revisarse parche por parche antes de comprometerse. Una forma simple de hacer esto en git es agregar los cambios con
Para cada cambio en un archivo de texto, el directorio de trabajo le preguntará si realmente desea conservarlo. Eso le permitiría ver, por ejemplo, la eliminación de esas "
SET
declaraciones iniciales ".En caso de que la codificación de un archivo completo cambiara, sucedería algo diferente: el algoritmo no lograría diferenciar el archivo antiguo y el nuevo y, por
git add -p
lo tanto , no agregaría nada en absoluto. Esto sería visible en el otro comando que haría antes de cualquier confirmación, a saberAquí te gustaría ver el archivo resaltado en rojo, indicando que no son cambios. Investigar por qué estos no lo lograron
git add -p
rápidamente haría obvio el problema.fuente
git
es el mejor ejemplo de eso: una gran herramienta, pero apenas inutilizable para simples mortales .Otro ángulo a considerar: dado que esas dos condiciones son requisitos para que su programa se ejecute, ¿no debería incrustar la lógica cerca de la lógica de ejecución? Quiero decir: prueba la existencia de un archivo antes de leerlo y / o valida su contenido, ¿verdad? Entonces, ¿cómo es esto diferente? Creo que, dado que se trata de un recurso externo de código, debe validarse en tiempo de ejecución, antes de que se use realmente. Resultado: aplicación más fuerte, no es necesario escribir pruebas adicionales.
fuente
Las pruebas son el mismo código que cualquier otro y, si son lo suficientemente complejas, también se benefician de ... pruebas unitarias. Parece más simple agregar tales verificaciones de precondición directamente en la prueba.
La mayoría de las pruebas son lo suficientemente simples como para no requerir esto, pero si algunas son lo suficientemente complejas, no veo nada fundamentalmente incorrecto con estas comprobaciones previas. Por supuesto, la prueba también debería fallar sin ellos, pero una buena prueba de unidad también indica qué unidad está fallando.
Un script que se usa como parte de la prueba y debe tener cierto contenido y codificación es probablemente una unidad. Puede tener mucho más código y lógica que el resto de la prueba. Una prueba con dicho script no es el mejor diseño de la historia y, si es posible, debe refactorizarse en algo más directo (a menos que sea una prueba de integración).
fuente
En primer lugar, uno de los propósitos de las pruebas es evitar que los problemas se repitan en su código, por lo que absolutamente debe seguir escribiendo pruebas de esta naturaleza.
En segundo lugar, nombrar es difícil. Sí, claramente estas no son "pruebas unitarias", pero pueden ser partes deseables y necesarias del proceso de compilación, porque lo protegen de errores obvios y porque le brindan retroalimentación sobre los errores antes (especialmente dado que no ve el consecuencias en una caja de desarrollo).
Por lo tanto, la pregunta realmente es (debería estar en su contexto) más sobre cuándo y cómo se ejecutan estas pruebas de lo que son.
He utilizado este tipo de prueba ampliamente en el pasado, nos han ahorrado una buena cantidad de dolor.
fuente
Las pruebas unitarias consisten en ejecutar una unidad de código aisladamente para confirmar que está produciendo el resultado correcto para la entrada correcta. El aislamiento debe hacer que tanto la unidad bajo prueba como la prueba en sí sean repetibles, es decir, no deben depender ni introducir efectos secundarios.
SQL no es exactamente algo que se pueda probar de forma aislada, por lo que cualquier prueba de SQL no es exactamente una prueba unitaria y, salvo las declaraciones SELECT, es casi seguro que tendrá un efecto secundario. Podemos llamarlo una prueba de integración en lugar de una prueba unitaria.
Siempre es aconsejable asegurarse de que cualquier defecto que pueda introducirse pueda detectarse lo antes posible en el ciclo de desarrollo, y sea beneficioso hacerlo de una manera que facilite la identificación de la fuente del defecto para que pueda ser rápidamente corregido
Las pruebas en cuestión pueden reubicarse más apropiadamente fuera del cuerpo de las "pruebas unitarias" y ubicarse en otro lugar, pero no deben eliminarse por completo si están haciendo algo útil como evitar la posible introducción de un defecto que podría llevar horas rastrear abajo.
fuente