¿Cuál es el punto de ejecutar pruebas de unidad en un servidor CI?

94

¿Por qué ejecutar pruebas de unidad en un servidor CI?

Seguramente, para cuando algo se comprometa a dominar, un desarrollador ya ha ejecutado todas las pruebas unitarias antes y ha solucionado cualquier error que pudiera haber ocurrido con su nuevo código. ¿No es ese el punto de las pruebas unitarias? De lo contrario, acaban de cometer un código roto.

    
pregunta Steve 27.01.2016 - 14:21
fuente

9 respuestas

219
  

Seguramente, para cuando algo se comprometa a dominar, un desarrollador ya ha ejecutado todas las pruebas unitarias antes y ha solucionado cualquier error que pudiera haber ocurrido con su nuevo código.

O no. Puede haber muchas razones por las que esto puede suceder:

  • El desarrollador no tiene la disciplina para hacerlo
  • Se han olvidado
  • No se comprometieron todo y enviaron un conjunto de confirmación incompleto (gracias Matthieu M.
  • Solo realizaron algunas pruebas, pero no toda la suite (gracias nhgrif )
  • Probaron en su rama antes de fusionarse (gracias nhgrif * 2)

Pero el punto real es ejecutar las pruebas en una máquina que no es la máquina del desarrollador. Una que se configura de manera diferente.

Esto ayuda a detectar problemas en los que las pruebas y / o el código dependen de algo específico de un cuadro de desarrollador (configuración, datos, zona horaria, configuración regional, lo que sea).

Otras buenas razones para que las compilaciones de CI ejecuten pruebas:

  • Pruebas en diferentes plataformas distintas de las plataformas de desarrollo principales, lo que puede ser difícil para un desarrollador. (gracias TZHX )
  • Las pruebas de aceptación / integración / de extremo a extremo / realmente largas se pueden ejecutar en el servidor de CI que normalmente no se ejecutaría en un cuadro de desarrollador. (gracias Ixrec )
  • Un desarrollador puede hacer un pequeño cambio antes de presionar / cometer (pensando que este es un cambio seguro y por lo tanto no ejecuta las pruebas). (gracias Ixrec * 2)
  • La configuración del servidor CI generalmente no incluye todas las herramientas y la configuración del desarrollador y, por lo tanto, está más cerca del sistema de producción
  • Los sistemas de CI construyen el proyecto desde cero cada vez, lo que significa que las construcciones son repetibles
  • Un cambio en la biblioteca podría causar problemas descendentes: un servidor de CI puede configurarse para crear todos los códigos de código dependientes, no solo la biblioteca uno
respondido por el Oded 27.01.2016 - 14:24
fuente
73

Como desarrollador que no ejecuta todas las pruebas de integración y unidades antes de comprometerse con el control de la fuente, ofreceré mi defensa aquí.

Tendría que compilar, probar y verificar que una aplicación se ejecuta correctamente en:

  • Microsoft Windows XP y Vista con compilador de Visual Studio 2008.
  • Microsoft Windows 7 con compilador de Visual Studio 2010.
    • Ah, y el MSI se construye para cada uno de ellos.
  • RHEL 5 y 6 con 4.1 y 4.4 respectivamente (similarmente CentOS)
    • 7 pronto. Woop-de-woop.
  • Estación de trabajo Fedora con GCC para las últimas tres versiones recientes.
  • Debian (y derivados como Ubuntu) para las últimas tres versiones recientes.
  • Mac OSX en las últimas tres versiones recientes.
    • Y los paquetes (rpm, dmg, etc.)

Agregue el Fortran (con compiladores tanto de Intel como de GNU), Python (y sus distintas versiones según el sistema operativo) y los componentes de guión de bash / bat y, bueno, creo que puede ver cómo se despliegan las cosas

Entonces, esas son dieciséis máquinas que tendría que tener, solo para realizar algunas pruebas un par de veces al día. Sería casi un trabajo de tiempo completo solo para administrar la infraestructura para eso. Creo que casi todos estarían de acuerdo en que no es razonable, especialmente si se multiplica por la cantidad de personas en el proyecto. Así que dejamos que nuestros servidores de CI hagan el trabajo.

Las pruebas unitarias no te impiden cometer un código roto, te dicen si saben que has roto algo. La gente puede decir "las pruebas unitarias deben ser rápidas" y seguir los principios y patrones de diseño y metodologías, pero en realidad a veces es mejor dejar que las computadoras que hemos diseñado para tareas repetitivas y monótonas hagan eso y solo se involucren si dinos que han encontrado algo.

    
respondido por el TZHX 27.01.2016 - 14:58
fuente
22

Pensarías que sí, pero los desarrolladores son humanos y a veces se olvidan.

Además, los desarrolladores a menudo no logran extraer el último código. Sus últimas pruebas podrían funcionar bien entonces, en el momento del registro, otra persona comete un cambio importante.

Sus pruebas también pueden depender de un recurso local (no verificado). Algo que tus pruebas de unidad locales no retomarían.

Si crees que todo lo anterior es fantasioso, hay un nivel por encima de CI (al menos en TFS) llamado Gated donde las compilaciones que tienen pruebas fallidas están archivadas y no están comprometidas con el código base .

    
respondido por el Robbie Dee 27.01.2016 - 14:23
fuente
22

Aparte de la excelente respuesta de Oded:

  • Pruebas el código desde el repositorio . Puede funcionar en su máquina con sus archivos ... que olvidó cometer. Puede depender de una nueva tabla que no tenga el script de creación (por ejemplo, en liquibase), algunos datos de configuración o archivos de propiedades.
  • Evita problemas de integración de código. Un desarrollador descarga la última versión, crea una unidad y prueba de integración, agrega código, pasa todas las pruebas en su máquina, confirma y presiona. Otro desarrollador acaba de hacer lo mismo. Ambos cambios son correctos por sí mismos, pero cuando se combinan causan un error. Esto podría ser la fusión del repositorio o simplemente que no se detecte como un conflicto. P.ej. Dev 1 elimina el archivo que no se utilizó en absoluto. Los códigos Dev 2 en este archivo y las pruebas sin cambios en Dev 1.
  • Desarrolla un script para implementarlo automáticamente desde el repositorio. Tener una construcción y despliegue universal resuelve muchos problemas. Algunos desarrolladores pueden haber agregado una opción de compilación o lib que no es compartida por todos. Esto no solo le ahorra tiempo, sino que, lo que es más importante, hace que la implementación sea segura y predecible. Además, puede volver en su repositorio a la versión 2.3.1 e implementar esta versión con un script que funcione con esta versión. Incluye objetos de base de datos como vistas, procedimientos almacenados, vistas y disparadores que deben ser versionados. (O no podrá volver a una versión viable).
  • Otras pruebas : Me gusta la integración, el rendimiento y las pruebas de extremo a extremo. Esto puede ser lento y podría incluir herramientas de prueba como Selenium. Es posible que necesite un conjunto completo de datos con una base de datos real en lugar de objetos simulados o HSQL.

Una vez trabajé en una empresa que tenía muchos errores en la implementación debido al proceso de fusión e implementación. Esto fue causado por un extraño marco propietario que dificultó las pruebas y el CI. No fue una experiencia feliz encontrar que el código que funcionó perfectamente en el desarrollo no llegó a la producción.

    
respondido por el Borjab 27.01.2016 - 16:13
fuente
14
  

para cuando algo se comprometa a dominar

Por lo general, configuro mi CI para que se ejecute en cada confirmación individual. Las ramas no se fusionan en el maestro hasta que la rama se ha probado. Si confías en ejecutar pruebas en el maestro, se abrirá una ventana para que la compilación se rompa.

La ejecución de las pruebas en una máquina CI se trata de resultados reproducibles. Debido a que el servidor CI tiene un entorno limpio conocido extraído de su VCS, usted sabe que los resultados de las pruebas son correctos. Cuando se ejecuta localmente, podría olvidarse de cometer algún código necesario para que pasen o tener un código no confirmado que los haga pasar cuando deberían estar fallando.

También puede ahorrarle tiempo a los desarrolladores ejecutando diferentes suites en paralelo, especialmente si algunas son pruebas lentas de varios minutos que probablemente no se ejecutarán localmente después de cada cambio.

En mi trabajo actual, nuestra implementación de producción está habilitada en CI que pasa todas las pruebas. Los scripts de implementación evitarán la implementación a menos que se estén aprobando. Esto hace que sea imposible olvidarse de ejecutarlos accidentalmente.

El hecho de que CI sea parte del flujo de trabajo también supone una carga para los desarrolladores. Como desarrollador, ¿suele ejecutar una impresora, un analizador estático, una prueba de unidad, una cobertura de código y una prueba de integración para cada cambio único? CI puede, de forma completamente automática y sin necesidad de pensarlo, reduciendo la fatiga de la decisión.

    
respondido por el Daenyth 27.01.2016 - 14:29
fuente
4

En el momento en que algo se comprometa a dominar, un desarrollador debería tener ya ejecutar todas las pruebas unitarias ... pero, ¿y si no lo han hecho? Si no ejecuta las pruebas unitarias en el servidor CI, no lo sabrá hasta que otra persona extraiga los cambios en su máquina y descubra que las pruebas simplemente se interrumpieron.

Además, el desarrollador puede haber cometido un error y hacer referencia a un recurso local específico de su máquina. Cuando comprueban el código y falla la ejecución de CI, el problema se identifica de inmediato y se puede corregir.

    
respondido por el David Arno 27.01.2016 - 14:24
fuente
3

Suponiendo (a diferencia de otras respuestas) que los desarrolladores son bastante disciplinados y realizan pruebas unitarias antes de comprometerse, puede haber varias razones:

  • las pruebas unitarias en ejecución pueden llevar mucho tiempo para algunas configuraciones especiales. Por ejemplo, la ejecución de pruebas unitarias con el comprobador de memoria (como valgrind) puede llevar mucho más tiempo. Aunque todas las pruebas de unidad pasan, la verificación de memoria puede fallar.
  • el resultado no es tan importante para algunas configuraciones especiales, por ejemplo, la ejecución de pruebas unitarias para verificar la cobertura del código requiere indicadores especiales de compilación. Para los desarrolladores normales, la cobertura del código no es tan importante, es más para las personas que cuidan que el código mantenga cierta calidad, como los jefes de equipo.
respondido por el BЈовић 27.01.2016 - 14:33
fuente
3

Es posible imaginar casos en que el cambio A no rompe la prueba, y el cambio B no rompe la prueba, pero A y B juntos sí lo hacen. Si A y B están hechos por diferentes desarrolladores, solo el servidor CI detectará el nuevo error. A y B pueden ser incluso dos partes de la misma oración más larga.

Imagina un tren conducido por las dos locomotoras A y B. Tal vez uno sea más que suficiente y esta es la solución a aplicar. Sin embargo, si se aplican los dos "arreglos" eliminando ambos, el tren no se moverá.

Además, no todos los desarrolladores ejecutan todas las pruebas de unidad, mientras que la mayoría de los desarrolladores buenos lo hacen.

    
respondido por el h22 28.01.2016 - 09:11
fuente
2

Hagamos una pregunta equivalente:

  

¿Por qué construiría el código en un servidor CI?

     

Seguramente, para cuando algo se comprometa a dominar, un desarrollador   ya ha creado el código anteriormente y ha solucionado cualquier error que pudiera haber   Ocurrió con su nuevo código. ¿No es ese el punto del código de construcción?   De lo contrario, acaban de cometer un código roto.

Hay varias razones para hacer CI, pero el punto principal de CI es tener una idea de cuál es el estado del código a lo largo del tiempo. El principal beneficio (de varios) que proporciona, es que podemos averiguar cuándo se rompe la compilación, averiguar qué lo rompió y luego arreglarlo.

Si el código nunca se rompe, ¿por qué usamos CI? Para entregar compilaciones para pruebas, las compilaciones nocturnas serían lo suficientemente buenas.

    
respondido por el Peter 29.01.2016 - 13:59
fuente

Lea otras preguntas en las etiquetas