Tests d'intégration dans les projets OSS - comment gérer les tiers avec authentification?

10

L' un de mes projets de passe - temps (open source) est un outil de sauvegarde qui fait des sauvegardes hors ligne des dépôts de GitHub, Bitbucket etc.
Il appelle l'API du Hébergeurs pour obtenir une liste des dépôts, puis il utilise Git / Mercurial / whatever pour clone / tirez les référentiels vers l'ordinateur local.

J'ai donc des tests d'intégration où j'appelle l'API GitHub, avec authentification.
(et lorsque la fonction de clonage / extraction sera terminée, il y aura probablement des tests qui cloneront les référentiels de GitHub, et devront également s'authentifier)

J'ai créé un utilisateur et une organisation spécialement pour une utilisation dans ces tests d'intégration.

Problème: je ne peux pas simplement coder en dur les mots de passe quelque part dans le code source car il est open source et le code est public sur GitHub.


Ce que je fais maintenant

Dans les tests, j'obtiens tous les noms d'utilisateur, mots de passe et noms de référentiel des variables d'environnement.
Voici un exemple :

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

( TestHelper.EnvVarest une méthode d'assistance qui obtient la valeur d'une variable d'environnement et lève une exception lorsqu'elle n'existe pas)

Ensuite, j'ai un fichier batch qui définit ces variables d'environnement.
Le vrai ( environment-variables.bat) est appelé dans mon script de construction et avant d'exécuter les tests, mais ignoré dans le contrôle de code source, il n'est donc pas réellement dans mon référentiel.

Ce qui est dans le contrôle de code source environment-variables.bat.sample, qui définit les mêmes variables d'environnement, mais avec de faux mots de passe:

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

Je peux donc cloner le référentiel sur ma machine, renommer ce fichier en environment-variables.bat, remplacer le faux mot de passe par le vrai, et tous les tests d'intégration fonctionneront.

Cela fonctionne également avec l'intégration continue - j'utilise AppVeyor, et là, je peux définir ces variables d'environnement dans l'interface utilisateur Web .


Ce que je n'aime pas

Je pense que ce n'est pas une bonne solution pour un projet OSS, et surtout pas pour ce projet:

En théorie, un contributeur à mon projet serait en mesure d'exécuter les tests d'intégration dès maintenant en:

  • création de son propre utilisateur de test et organisation de test sur GitHub
  • création de référentiels de test
  • créer sa propre version de environment-variables.batavec des valeurs différentes

Le problème est que mon application pourra sauvegarder plusieurs hébergeurs de code source.
Pour le moment, il ne prend en charge que GitHub, mais il sera facile d'ajouter la prise en charge de plus d'hôtes en ajoutant quelques classes qui implémentent les bonnes interfaces.

Ainsi, lorsque j'implémenterai la prise en charge de plusieurs hôtes plus tard, le nombre de variables d'environnement augmentera.
Pour pouvoir exécuter tous les tests d'intégration, un contributeur potentiel créerait ses propres utilisateurs, organisations et référentiels de test sur GitHub, Bitbucket, GitLab, ... et qui sait combien de plus, et les ajouterait tous à sa environment-variables.batversion.

Existe-t-il une meilleure solution pour le faire sur un projet où le code est public?

Je sais que d'autres projets font quelque chose de similaire à ce que je fais actuellement.
Octokit.net , par exemple, dispose d' un script pour configurer les variables d'environnement pour les tests d'intégration qui appellent l'API GitHub.
Mais ils n'ont besoin que d'un utilisateur et d'une organisation, et j'en aurai besoin de beaucoup plus.

Peut-être que je n'ai pas besoin d'une solution qui permette à un contributeur d'exécuter réellement tous les tests d'intégration.
Par exemple, si quelqu'un souhaite contribuer au support GitHub de mon projet, il n'aura besoin que de pouvoir exécuter les tests d'intégration GitHub.
Alors peut-être que j'ai juste besoin d'un moyen sensé pour pouvoir diviser mes tests d'intégration en un nombre infini de "groupes" (?) Puis dire "et maintenant exécuter tous les tests qui appartiennent au groupe 'Github'".

Christian Specht
la source

Réponses:

2

Je pense que votre configuration actuelle est très bien, mais je ferais quelques ajustements.

Pour pouvoir exécuter tous les tests d'intégration, un contributeur potentiel créerait ses propres utilisateurs, organisations et référentiels de test sur GitHub, Bitbucket, GitLab, .... et qui sait combien de plus, et les ajouterait tous à ses variables d'environnement Version .bat.

Oui, c'est vrai, mais les contributeurs ne doivent pas nécessairement exécuter tous les tests d'intégration avant de créer un PR sur votre projet. Une fois le PR créé, le CI exécutera la suite complète de tests.

Il est courant d'avoir une suite de tests qui n'est pas possible de s'exécuter facilement. Pour de nombreuses organisations, ils maintiennent des suites de tests qui prennent des jours à s'exécuter - par conséquent, les développeurs doivent exécuter de manière sélective des tests faciles à exécuter et faire avancer le code pour des tests plus rigoureux. Je propose la même approche.

Pour les contributeurs réguliers / de confiance, vous pouvez en faire des contributeurs réels sur votre projet, ce qui devrait leur permettre d'exécuter CI sur leur branche avant de faire un PR.

Cela dit, vous n'empêchez pas les contributeurs d'exécuter la suite complète de tests. Ils peuvent fournir leurs propres informations d'identification GitHub ou créer leurs propres comptes de test, et les contributeurs réguliers le feront probablement.

Les ajustements que je propose sont les suivants:

Tout d'abord, faites la plupart de vos tests unitaires de couverture de test. Ceux-ci devraient couvrir toutes les branches de votre base de code.

Deuxièmement, écrivez des tests d'intégration où le point de terminaison est simulé. Vous pouvez même simuler la couche de transport de ces API et simuler des flux de demande / réponse HTTP en démarrant un faux service GitHub Rest. Par exemple (en pseudo code):

// 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()

Ces tests seront plus complexes, mais vous permettront de

  1. Testez sans créer de faux comptes et référentiels
  2. Testez les conditions d'échec qui seraient difficiles à simuler avec un vrai GitHub. Par exemple, 502 réponses, délais de connexion, corps de réponse inhabituels / non analysables.

Troisièmement, désactivez tous les tests qui nécessitent des connaissances spéciales pour s'exécuter sous une version normale. Dans la plupart des outils de gestion de build, il existe un moyen de séparer les tests d'intégration, ou de tester les tests, et de les exécuter de manière sélective. Les contributeurs doivent pouvoir créer et tester le logiciel sans aucune configuration préalable. La suite de tests complète doit s'exécuter après chaque build dans CI.

Enfin, documentez les tests et comment les exécuter dans votre documentation de test afin que les contributeurs puissent choisir de les exécuter.

Samuel
la source