Tes integrasi dalam proyek OSS - bagaimana menangani pihak ke-3 dengan otentikasi?

10

Salah satu proyek hobi saya (open source) adalah alat cadangan yang membuat cadangan offline dari repositori dari GitHub, Bitbucket dll.
Ia memanggil API hosters untuk mendapatkan daftar repositori, dan kemudian menggunakan Git / Mercurial / apa pun untuk dikloning / tarik repositori ke komputer lokal.

Jadi saya memiliki tes integrasi tempat saya memanggil API GitHub, dengan otentikasi.
(dan ketika fitur kloning / tarik selesai, mungkin akan ada tes yang mengkloning repositori dari GitHub, dan perlu untuk mengotentikasi juga)

Saya membuat pengguna dan organisasi khusus untuk digunakan dalam tes integrasi ini.

Masalah: Saya tidak bisa hanya membuat hard-sandi kata sandi di suatu tempat dalam kode sumber karena bersifat open source, dan kode ini bersifat publik di GitHub.


Apa yang saya lakukan sekarang

Dalam pengujian, saya mendapatkan semua nama pengguna, kata sandi, dan nama repositori dari variabel lingkungan.
Ini sebuah contoh :

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

( TestHelper.EnvVaradalah metode pembantu yang mendapatkan nilai dari variabel lingkungan dan melemparkan pengecualian ketika tidak ada)

Kemudian, saya memiliki file batch yang mengatur variabel lingkungan tersebut.
Yang asli ( environment-variables.bat) dipanggil dalam skrip build saya dan sebelum menjalankan tes, tetapi diabaikan dalam kontrol sumber, jadi sebenarnya tidak ada di repositori saya.

Apa yang ada dalam kontrol sumber adalah environment-variables.bat.sample, yang menetapkan variabel lingkungan yang sama, tetapi dengan kata sandi palsu:

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

Jadi saya bisa mengkloning repositori ke mesin saya, mengganti nama file ini environment-variables.bat, mengganti kata sandi palsu dengan yang asli, dan semua tes integrasi akan bekerja.

Ini berfungsi dengan Integrasi Berkelanjutan juga - Saya menggunakan AppVeyor, dan di sana saya dapat mengatur variabel lingkungan ini di web UI .


Apa yang saya tidak suka tentang itu

Saya pikir itu bukan solusi yang baik untuk proyek OSS, dan terutama bukan untuk proyek ini :

Secara teori, kontributor proyek saya akan dapat menjalankan tes integrasi sekarang dengan:

  • membuat pengguna uji sendiri dan organisasi pengujian di GitHub
  • membuat beberapa repositori tes
  • membuat versinya sendiri environment-variables.batdengan nilai yang berbeda

Masalahnya adalah aplikasi saya akan dapat membuat cadangan beberapa host kode sumber.
Saat ini, ini hanya mendukung GitHub, tetapi akan mudah untuk menambahkan dukungan untuk lebih banyak host dengan menambahkan beberapa kelas yang mengimplementasikan antarmuka yang tepat.

Jadi ketika saya menerapkan dukungan untuk hoster lebih banyak lagi, jumlah variabel lingkungan akan bertambah.
Untuk dapat menjalankan semua tes integrasi, kontributor potensial akan membuat pengguna, organisasi, dan repositori pengujian sendiri di GitHub, Bitbucket, GitLab, .... dan siapa yang tahu berapa banyak lagi, dan menambahkan semuanya ke environment-variables.batversinya.

Apakah ada solusi yang lebih baik bagaimana melakukan ini pada proyek di mana kodenya publik?

Saya tahu bahwa proyek lain melakukan sesuatu yang mirip dengan apa yang saya lakukan saat ini.
Octokit.net , misalnya, memiliki skrip untuk mengatur variabel lingkungan untuk pengujian integrasi yang memanggil API GitHub.
Tetapi mereka hanya membutuhkan satu pengguna dan satu organisasi, dan saya akan membutuhkan lebih banyak.

Mungkin saya tidak memerlukan solusi yang memungkinkan kontributor untuk benar-benar menjalankan semua tes integrasi.
Misalnya, jika seseorang ingin berkontribusi pada dukungan GitHub proyek saya, ia hanya perlu menjalankan tes integrasi GitHub.
Jadi mungkin saya hanya perlu cara yang waras untuk dapat membagi tes integrasi saya menjadi jumlah "grup" (?) Yang tak terbatas dan kemudian mengatakan "dan sekarang jalankan semua tes yang termasuk dalam grup 'Github'".

Christian Specht
sumber

Jawaban:

2

Saya pikir pengaturan Anda saat ini baik-baik saja, tetapi saya akan membuat beberapa penyesuaian.

Untuk dapat menjalankan semua tes integrasi, kontributor potensial akan membuat penggunanya, organisasi, dan repositori pengujian di GitHub, Bitbucket, GitLab, .... dan siapa yang tahu berapa banyak lagi, dan menambahkan semuanya ke variabel lingkungannya versi .bat.

Ya, itu benar, tetapi kontributor tidak harus menjalankan semua tes integrasi sebelum membuat PR pada proyek Anda. Setelah PR dibuat, CI akan menjalankan serangkaian uji lengkap.

Adalah umum untuk memiliki test suite yang entah bagaimana tidak mungkin dijalankan dengan mudah. Bagi banyak organisasi, mereka memelihara ruang uji yang membutuhkan waktu berhari-hari untuk dijalankan - oleh karena itu pengembang harus menjalankan tes secara selektif yang mudah dijalankan dan mendorong kode ke depan untuk pengujian yang lebih ketat. Saya menyarankan pendekatan yang sama.

Untuk kontributor reguler / tepercaya, Anda dapat menjadikan mereka kontributor aktual di proyek Anda yang memungkinkan mereka menjalankan CI di cabang mereka sebelum membuat PR.

Karena itu, Anda tidak mencegah kontributor menjalankan serangkaian uji lengkap. Mereka dapat memberikan kredensial GitHub mereka sendiri atau membuat akun pengujian mereka sendiri, dan kontributor reguler kemungkinan akan melakukan ini.

Penyesuaian yang saya sarankan adalah:

Pertama, manfaatkan sebagian besar unit tes cakupan Anda. Ini harus mencakup semua cabang basis kode Anda.

Kedua, tulis tes integrasi di mana titik akhir diejek. Anda bahkan dapat mengejek lapisan transport API ini dan mensimulasikan aliran permintaan / respons HTTP dengan memulai layanan GitHub Rest palsu. Misalnya (dalam kode pseudo):

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

Tes-tes ini akan lebih kompleks, tetapi akan memungkinkan Anda untuk melakukannya

  1. Uji tanpa membuat akun dan repositori palsu
  2. Uji kondisi kegagalan yang akan sulit untuk disimulasikan dengan GitHub nyata. Misalnya 502 respons, batas waktu koneksi, badan respons yang tidak biasa / tidak dapat dipecahkan.

Ketiga, nonaktifkan semua tes yang membutuhkan pengetahuan khusus agar tidak berjalan di bawah bangunan normal. Pada sebagian besar alat manajemen bangun ada cara untuk memisahkan tes integrasi, atau menandai tes dan menjalankannya secara selektif. Kontributor harus dapat membuat dan menguji perangkat lunak tanpa konfigurasi sebelumnya. Paket tes lengkap harus dijalankan setelah setiap pembangunan CI.

Terakhir, dokumentasikan tes dan cara menjalankannya dalam dokumentasi tes Anda sehingga kontributor dapat memilih untuk menjalankannya.

Samuel
sumber