Pruebas de integración en proyectos OSS: ¿cómo manejar a terceros con autenticación?

10

Uno de mis proyectos de pasatiempos (de código abierto) es una herramienta de copia de seguridad que realiza copias de seguridad fuera de línea de repositorios desde GitHub, Bitbucket, etc.
Llama a la API de los anfitriones para obtener una lista de repositorios, y luego usa Git / Mercurial / lo que sea para clonar / tire de los repositorios a la computadora local.

Así que tengo pruebas de integración donde llamo a la API de GitHub, con autenticación.
(y cuando finalice la función de clonación / extracción, probablemente habrá pruebas de los repositorios de clonación de GitHub y también deberá autenticarse)

Creé un usuario y una organización especialmente para usar en estas pruebas de integración.

Problema: no puedo codificar las contraseñas en algún lugar del código fuente porque es de código abierto y el código es público en GitHub.


Lo que estoy haciendo ahora

En las pruebas, obtengo todos los nombres de usuario, contraseñas y nombres de repositorio de variables de entorno.
Aquí hay un ejemplo :

config.Name = TestHelper.EnvVar("GithubApiTests_Name");
config.Password = TestHelper.EnvVar("GithubApiTests_PW");

( TestHelper.EnvVares un método auxiliar que obtiene el valor de una variable de entorno y genera una excepción cuando no existe)

Luego, tengo un archivo por lotes que establece esas variables de entorno.
El real ( environment-variables.bat) se llama en mi script de compilación y antes de ejecutar las pruebas, pero se ignora en el control de origen, por lo que no está realmente en mi repositorio.

Lo que está en el control de origen es environment-variables.bat.sample, que establece las mismas variables de entorno, pero con contraseñas falsas:

rem copy/rename this file to environment-variables.bat

echo Setting environment variables for integration tests...

set GithubApiTests_Name=scm-backup-testuser
set GithubApiTests_OrgName=scm-backup-testorg
set GithubApiTests_PW=not-the-real-password
set GithubApiTests_Repo=scm-backup

Entonces puedo clonar el repositorio en mi máquina, cambiar el nombre de este archivo environment-variables.bat, reemplazar la contraseña falsa por la real y todas las pruebas de integración funcionarán.

Esto también funciona con la integración continua: estoy usando AppVeyor y allí puedo configurar estas variables de entorno en la interfaz de usuario web .


Lo que no me gusta de eso

Creo que no es una buena solución para un proyecto OSS, y especialmente no para este proyecto:

En teoría, un contribuyente a mi proyecto podría ejecutar las pruebas de integración en este momento:

  • creando su propio usuario de prueba y organización de prueba en GitHub
  • creando algunos repositorios de prueba
  • creando su propia versión de environment-variables.batcon diferentes valores

El problema es que mi aplicación podrá hacer una copia de seguridad de múltiples proveedores de código fuente.
En este momento, solo admite GitHub, pero será fácil agregar soporte para más servidores agregando algunas clases que implementan las interfaces correctas.

Entonces, cuando implemente soporte para más hosts más tarde, la cantidad de variables de entorno crecerá.
Para poder ejecutar todas las pruebas de integración, un contribuyente potencial crearía sus propios usuarios, organizaciones y repositorios de prueba en GitHub, Bitbucket, GitLab, ... y quién sabe cuántos más, y los agregaría a su environment-variables.batversión.

¿Existe una mejor solución para hacer esto en un proyecto donde el código es público?

Sé que otros proyectos hacen algo similar a lo que estoy haciendo actualmente.
Octokit.net , por ejemplo, tiene un script para configurar variables de entorno para pruebas de integración que están llamando a la API de GitHub.
Pero solo necesitan un usuario y una organización, y yo necesitaré mucho más.

Tal vez no necesito una solución que permita a un contribuyente ejecutar realmente todas las pruebas de integración.
Por ejemplo, si alguien quisiera contribuir al soporte de GitHub de mi proyecto, solo necesitaría poder ejecutar las pruebas de integración de GitHub.
Entonces, tal vez solo necesito una forma sensata de poder dividir mis pruebas de integración en un número infinito de "grupos" (?) Y luego decir "y ahora ejecutar todas las pruebas que pertenecen al grupo 'Github'".

Christian Specht
fuente

Respuestas:

2

Creo que su configuración actual está bien, pero haría algunos ajustes.

Para poder ejecutar todas las pruebas de integración, un contribuyente potencial crearía sus propios usuarios, organizaciones y repositorios de pruebas en GitHub, Bitbucket, GitLab, ... y quién sabe cuánto más, y los agregaría a sus variables de entorno. versión .bat.

Sí, eso es cierto, pero los contribuyentes no necesariamente tienen que ejecutar todas las pruebas de integración antes de crear un RP en su proyecto. Una vez que se crea un RP, el CI ejecutará el conjunto completo de pruebas.

Es común tener un conjunto de pruebas que de alguna manera no es posible ejecutar fácilmente. Para muchas organizaciones, mantienen conjuntos de pruebas que tardan días en ejecutarse; por lo tanto, los desarrolladores deben ejecutar selectivamente pruebas que sean fáciles de ejecutar e impulsar el código para pruebas más rigurosas. Estoy sugiriendo el mismo enfoque.

Para los contribuyentes regulares / de confianza, puede convertirlos en contribuyentes reales en su proyecto, lo que debería permitirles ejecutar CI en su sucursal antes de realizar un RP.

Dicho esto, no estás evitando que los contribuyentes ejecuten el conjunto completo de pruebas. Pueden proporcionar sus propias credenciales de GitHub o crear sus propias cuentas de prueba, y los contribuyentes habituales probablemente lo harán.

Los ajustes que sugiero son:

Primero, aproveche al máximo sus pruebas de unidad de cobertura de prueba. Deben cubrir todas las ramas de su código base.

En segundo lugar, escriba pruebas de integración donde se burla el punto final. Incluso puede burlarse de la capa de transporte de estas API y simular flujos de solicitud / respuesta HTTP iniciando un servicio falso GitHub Rest. Por ejemplo (en pseudocódigo):

// Test failed authentication to GitHub
val server = new WebServer("localhost", 9453, { request =>
    return Response(401, "unauthenticated")
})
server.start()
val backupService = new GitHubBackupService("http://localhost:9453")
backupService.backup must throw UnauthenticatedException()
server.stop()

Estas pruebas serán más complejas, pero le permitirán

  1. Pruebe sin crear cuentas y repositorios falsos
  2. Pruebe las condiciones de falla que serían difíciles de simular con GitHub real. Por ejemplo, 502 respuestas, tiempos de espera de conexión, cuerpos de respuesta inusuales / no analizables.

Tercero, deshabilite cualquier prueba que necesite un conocimiento especial para ejecutarse bajo una compilación normal. En la mayoría de las herramientas de administración de compilación, hay una manera de separar las pruebas de integración, o etiquetar las pruebas y ejecutarlas selectivamente. Los contribuyentes deberían poder construir y probar el software sin ninguna configuración previa. El conjunto de pruebas completo debe ejecutarse después de cada compilación en CI.

Finalmente, documente las pruebas y cómo ejecutarlas en su documentación de prueba para que los contribuyentes puedan elegir ejecutarlas.

Samuel
fuente