Integrationstests in OSS-Projekten - Wie gehe ich mit Authentifizierung durch Dritte um?


10

Eines meiner (Open Source) Hobbyprojekte ist ein Backup-Tool, das Offline-Backups von Repositorys von GitHub, Bitbucket usw. erstellt.
Es ruft die Host-API auf, um eine Liste der Repositorys abzurufen, und verwendet dann Git / Mercurial / was auch immer zum Klonen / Ziehen Sie die Repositorys auf den lokalen Computer.

Ich habe also Integrationstests, bei denen ich die GitHub-API mit Authentifizierung aufrufe.
(und wenn die Klon- / Pull-Funktion abgeschlossen ist, wird es wahrscheinlich Tests geben, die Repositorys von GitHub klonen und sich ebenfalls authentifizieren müssen)

Ich habe einen Benutzer und eine Organisation speziell für diese Integrationstests erstellt.

Problem: Ich kann die Passwörter nicht einfach irgendwo im Quellcode fest codieren, da es sich um Open Source handelt und der Code auf GitHub öffentlich ist.


Was ich jetzt mache

In den Tests erhalte ich alle Benutzernamen, Kennwörter und Repository-Namen von Umgebungsvariablen.
Hier ist ein Beispiel :

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

( TestHelper.EnvVarist eine Hilfsmethode, die den Wert einer Umgebungsvariablen abruft und eine Ausnahme auslöst, wenn sie nicht vorhanden ist.)

Dann habe ich eine Batch-Datei, die diese Umgebungsvariablen festlegt.
Das echte ( environment-variables.bat) wird in meinem Build-Skript und vor dem Ausführen der Tests aufgerufen, aber in der Quellcodeverwaltung ignoriert, sodass es sich nicht in meinem Repository befindet.

Was ist in der Quellcodeverwaltung ist environment-variables.bat.sample, die die gleichen Umgebungsvariablen setzen, aber mit gefälschten Passwörtern:

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

So kann ich das Repository auf meinen Computer klonen, diese Datei in umbenennen environment-variables.bat, das gefälschte Kennwort durch das echte ersetzen, und alle Integrationstests funktionieren.

Dies funktioniert auch mit Continuous Integration - ich verwende AppVeyor und kann dort diese Umgebungsvariablen in der Web-Benutzeroberfläche festlegen .


Was ich daran nicht mag

Ich denke, es ist keine gute Lösung für ein OSS-Projekt und insbesondere nicht für dieses Projekt:

Theoretisch könnte ein Mitwirkender an meinem Projekt die Integrationstests jetzt ausführen, indem er:

  • Erstellen eines eigenen Testbenutzers und einer eigenen Testorganisation auf GitHub
  • Erstellen einiger Test-Repositorys
  • Erstellen seiner eigenen Version von environment-variables.batmit verschiedenen Werten

Das Problem ist, dass meine Anwendung mehrere Quellcode-Hoster sichern kann.
Im Moment unterstützt es nur GitHub, aber es wird einfach sein, Unterstützung für mehr Hoster hinzuzufügen, indem einige Klassen hinzugefügt werden, die die richtigen Schnittstellen implementieren.

Wenn ich später die Unterstützung für mehr Hoster implementiere, wächst die Anzahl der Umgebungsvariablen.
Um alle Integrationstests ausführen zu können, würde ein potenzieller Mitwirkender seine eigenen Benutzer, Organisationen und Test-Repositorys bei GitHub, Bitbucket, GitLab usw. erstellen und wer weiß, wie viele weitere, und alle zu seiner environment-variables.batVersion hinzufügen .

Gibt es eine bessere Lösung für ein Projekt, bei dem der Code öffentlich ist?

Ich weiß, dass andere Projekte etwas Ähnliches tun wie das, was ich gerade mache.
Octokit.net verfügt beispielsweise über ein Skript zum Einrichten von Umgebungsvariablen für Integrationstests, die die GitHub-API aufrufen.
Aber sie brauchen nur einen Benutzer und eine Organisation, und ich werde viel mehr brauchen.

Vielleicht brauche ich keine Lösung, mit der ein Mitwirkender tatsächlich alle Integrationstests ausführen kann.
Wenn beispielsweise jemand zur GitHub-Unterstützung meines Projekts beitragen möchte, muss er nur die GitHub-Integrationstests ausführen können.
Vielleicht brauche ich nur einen vernünftigen Weg, um meine Integrationstests in eine unendliche Anzahl von "Gruppen" (?) Aufzuteilen und dann zu sagen "und jetzt alle Tests auszuführen, die zur Gruppe 'Github' gehören".

Antworten:


2

Ich denke, Ihr aktuelles Setup ist in Ordnung, aber ich würde ein paar Anpassungen vornehmen.

Um alle Integrationstests ausführen zu können, würde ein potenzieller Mitwirkender seine eigenen Benutzer, Organisationen und Testrepositorys bei GitHub, Bitbucket, GitLab usw. erstellen und wer weiß wie viel mehr und alle zu seinen Umgebungsvariablen hinzufügen .bat Version.

Ja, das stimmt, aber die Mitwirkenden müssen nicht unbedingt alle Integrationstests ausführen, bevor sie eine PR für Ihr Projekt erstellen. Sobald eine PR erstellt wurde, führt das CI die gesamte Testsuite aus.

Es ist üblich, eine Testsuite zu haben, die sich nicht einfach ausführen lässt. Für viele Unternehmen unterhalten sie Testsuiten, deren Ausführung Tage in Anspruch nimmt. Daher müssen Entwickler selektiv Tests ausführen, die einfach auszuführen sind, und den Code für strengere Tests vorantreiben. Ich schlage den gleichen Ansatz vor.

Für reguläre / vertrauenswürdige Mitwirkende können Sie sie zu tatsächlichen Mitwirkenden für Ihr Projekt machen, damit sie CI in ihrer Niederlassung ausführen können, bevor sie eine PR erstellen.

Sie hindern die Mitwirkenden jedoch nicht daran , die gesamte Testsuite auszuführen. Sie können ihre eigenen GitHub-Anmeldeinformationen bereitstellen oder ihre eigenen Testkonten erstellen, und regelmäßige Mitwirkende werden dies wahrscheinlich tun.

Die von mir vorgeschlagenen Anpassungen sind:

Führen Sie zunächst die meisten Tests für Testabdeckungseinheiten durch. Diese sollten alle Zweige Ihrer Codebasis abdecken.

Zweitens schreiben Sie Integrationstests, bei denen der Endpunkt verspottet wird. Sie können sogar die Transportschicht dieser API verspotten und HTTP-Anforderungs- / Antwortflüsse simulieren, indem Sie einen gefälschten GitHub Rest-Dienst starten. Zum Beispiel (im Pseudocode):

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

Diese Tests sind komplexer, ermöglichen es Ihnen jedoch

  1. Testen Sie, ohne gefälschte Konten und Repositorys zu erstellen
  2. Testen Sie Fehlerbedingungen, die mit echtem GitHub nur schwer zu simulieren sind. Zum Beispiel 502 Antworten, Verbindungszeitüberschreitungen, ungewöhnliche / nicht analysierbare Antwortkörper.

Drittens deaktivieren Sie alle Tests, für die spezielle Kenntnisse erforderlich sind, um unter einem normalen Build ausgeführt zu werden. In den meisten Build-Management-Tools gibt es eine Möglichkeit, Integrationstests oder Tag-Tests zu trennen und selektiv auszuführen. Mitwirkende sollten in der Lage sein, die Software ohne vorherige Konfiguration zu erstellen und zu testen . Die vollständige Testsuite sollte nach jedem Build in CI ausgeführt werden.

Dokumentieren Sie abschließend die Tests und deren Ausführung in Ihrer Testdokumentation, damit die Mitwirkenden sie ausführen können.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.