Membuat Alur Kerja Pengujian Integrasi Berkelanjutan Menggunakan Tindakan GitHub
Diterbitkan: 2022-03-10Saat berkontribusi pada proyek pada platform kontrol versi seperti GitHub dan Bitbucket, konvensinya adalah bahwa ada cabang utama yang berisi basis kode fungsional. Kemudian, ada cabang lain di mana beberapa pengembang dapat mengerjakan salinan utama untuk menambahkan fitur baru, memperbaiki bug, dan sebagainya. Sangat masuk akal karena menjadi lebih mudah untuk memantau jenis efek perubahan yang masuk pada kode yang ada. Jika ada kesalahan, itu dapat dengan mudah dilacak dan diperbaiki sebelum mengintegrasikan perubahan ke cabang utama. Mungkin memakan waktu untuk menelusuri setiap baris kode secara manual mencari kesalahan atau bug — bahkan untuk proyek kecil. Di situlah integrasi berkelanjutan masuk.
Apa itu Continuous Integration (CI)?
“Integrasi berkelanjutan (CI) adalah praktik mengotomatiskan integrasi perubahan kode dari banyak kontributor ke dalam satu proyek perangkat lunak.”
— Atlassian.com
Gagasan umum di balik integrasi berkelanjutan (CI) adalah untuk memastikan perubahan yang dibuat pada proyek tidak "merusak pembangunan", yaitu, merusak basis kode yang ada. Menerapkan integrasi berkelanjutan dalam proyek Anda, bergantung pada cara Anda menyiapkan alur kerja, akan membuat build setiap kali ada orang yang membuat perubahan pada repositori.
Jadi, Apa Itu Bangun?
Build — dalam konteks ini — adalah kompilasi kode sumber ke dalam format yang dapat dieksekusi. Jika berhasil, itu berarti perubahan yang masuk tidak akan berdampak negatif pada basis kode, dan siap untuk digunakan. Namun, jika build gagal, perubahan harus dievaluasi ulang. Itulah mengapa disarankan untuk membuat perubahan pada proyek dengan mengerjakan salinan proyek di cabang yang berbeda sebelum memasukkannya ke dalam basis kode utama. Dengan cara ini, jika build rusak, akan lebih mudah untuk mengetahui dari mana kesalahan itu berasal, dan itu juga tidak memengaruhi kode sumber utama Anda.
“Semakin dini Anda menemukan cacat, semakin murah untuk memperbaikinya.”
— David Farley, Pengiriman Berkelanjutan: Rilis Perangkat Lunak yang Andal melalui Build, Test, dan Deployment Automation
Ada beberapa alat yang tersedia untuk membantu menciptakan integrasi berkelanjutan untuk proyek Anda. Ini termasuk Jenkins, TravisCI, CircleCI, GitLab CI, GitHub Actions, dll. Untuk tutorial ini, saya akan menggunakan GitHub Actions.
Tindakan GitHub Untuk Integrasi Berkelanjutan
CI Actions adalah fitur yang cukup baru di GitHub dan memungkinkan pembuatan alur kerja yang secara otomatis menjalankan pembangunan dan pengujian proyek Anda. Alur kerja berisi satu atau beberapa pekerjaan yang dapat diaktifkan saat suatu peristiwa terjadi. Acara ini bisa berupa push ke salah satu cabang di repo atau pembuatan pull request. Saya akan menjelaskan istilah-istilah ini secara rinci saat kita melanjutkan.
Ayo Mulai!
Prasyarat
Ini adalah tutorial untuk pemula jadi saya kebanyakan akan berbicara tentang GitHub Actions CI di tingkat permukaan. Pembaca seharusnya sudah terbiasa membuat Node JS REST API menggunakan database PostgreSQL, Sequelize ORM, dan menulis tes dengan Mocha dan Chai.
Anda juga harus menginstal yang berikut di mesin Anda:
- NodeJS,
- PostgreSQL,
- NPM,
- VSCode (atau editor dan terminal pilihan Anda).
Saya akan menggunakan REST API yang sudah saya buat bernama countries-info-api
. Ini adalah api sederhana tanpa otorisasi berbasis peran (seperti pada saat menulis tutorial ini). Ini berarti siapa pun dapat menambahkan, menghapus, dan/atau memperbarui detail negara. Setiap negara akan memiliki id (auto-generated UUID), nama, modal, dan populasi. Untuk mencapai ini, saya menggunakan Node js, express js framework, dan Postgresql untuk database.
Saya akan menjelaskan secara singkat bagaimana saya mengatur server, database sebelum saya mulai dengan menulis tes untuk cakupan tes dan file alur kerja untuk integrasi berkelanjutan.
Anda dapat mengkloning repo countries-info-api
untuk menindaklanjuti atau membuat API Anda sendiri.
Teknologi yang digunakan : Node Js, NPM (pengelola paket untuk Javascript), database Postgresql, sekuel ORM, Babel.
Menyiapkan Server
Sebelum mengatur server, saya menginstal beberapa dependensi dari npm.
npm install express dotenv cors npm install --save-dev @babel/core @babel/cli @babel/preset-env nodemon
Saya menggunakan kerangka kerja ekspres dan menulis dalam format ES6, jadi saya memerlukan Babeljs untuk mengkompilasi kode saya. Anda dapat membaca dokumentasi resmi untuk mengetahui lebih banyak tentang cara kerjanya dan cara mengonfigurasinya untuk proyek Anda. Nodemon akan mendeteksi setiap perubahan yang dibuat pada kode dan secara otomatis me-restart server.
Catatan : Paket Npm yang diinstal menggunakan flag --save-dev
hanya diperlukan selama tahap pengembangan dan terlihat di bawah devDependencies dalam file package.json
.
Saya menambahkan yang berikut ini ke file index.js
saya:
import express from "express"; import bodyParser from "body-parser"; import cors from "cors"; import "dotenv/config"; const app = express(); const port = process.env.PORT; app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(cors()); app.get("/", (req, res) => { res.send({message: "Welcome to the homepage!"}) }) app.listen(port, () => { console.log(`Server is running on ${port}...`) })
Ini mengatur api kita untuk dijalankan pada apa pun yang ditetapkan ke variabel PORT
dalam file .env
. Ini juga di mana kita akan mendeklarasikan variabel yang kita tidak ingin orang lain akses dengan mudah. Paket dotenv
npm memuat variabel lingkungan kita dari .env
.
Sekarang ketika saya menjalankan npm run start
di terminal saya, saya mendapatkan ini:
Seperti yang Anda lihat, server kami aktif dan berjalan. Ya!
Tautan ini https://127.0.0.1:your_port_number/
di browser web Anda akan mengembalikan pesan selamat datang. Artinya, selama server berjalan.
Selanjutnya, Database dan Model.
Saya membuat model negara menggunakan Sequelize dan saya terhubung ke database Postgres saya. Sequelize adalah ORM untuk Nodejs. Keuntungan utama adalah menghemat waktu kita menulis kueri SQL mentah.
Karena kita menggunakan Postgresql, database dapat dibuat melalui baris perintah psql menggunakan perintah CREATE DATABASE database_name
. Ini juga dapat dilakukan di terminal Anda, tetapi saya lebih suka PSQL Shell.
Dalam file env, kami akan mengatur string koneksi database kami, mengikuti format di bawah ini.
TEST_DATABASE_URL = postgres://<db_username>:<db_password>@127.0.0.1:5432/<database_name>
Untuk model saya, saya mengikuti tutorial sekuel ini. Sangat mudah untuk mengikuti dan menjelaskan segala sesuatu tentang pengaturan Sequelize.
Selanjutnya, saya akan menulis tes untuk model yang baru saja saya buat dan mengatur cakupan di Coverall.
Tes Menulis Dan Pelaporan Liputan
Mengapa menulis tes? Secara pribadi, saya percaya bahwa tes menulis membantu Anda sebagai pengembang untuk lebih memahami bagaimana kinerja perangkat lunak Anda di tangan pengguna Anda karena ini adalah proses brainstorming. Ini juga membantu Anda menemukan bug tepat waktu.
Tes:
Ada metode pengujian perangkat lunak yang berbeda, namun, Untuk tutorial ini, saya menggunakan pengujian unit dan ujung ke ujung.
Saya menulis pengujian saya menggunakan kerangka pengujian Mocha dan pustaka pernyataan Chai. Saya juga menginstal sequelize-test-helpers
untuk membantu menguji model yang saya buat menggunakan sequelize.define
.
Cakupan tes:
Disarankan untuk memeriksa cakupan pengujian Anda karena hasilnya menunjukkan apakah kasus pengujian kami benar-benar mencakup kode dan juga berapa banyak kode yang digunakan saat kami menjalankan kasus pengujian kami.
Saya menggunakan Istanbul (alat cakupan pengujian), nyc (klien CLI Instabul), dan Baju.
Menurut dokumen, Istanbul melengkapi kode JavaScript ES5 dan ES2015+ Anda dengan penghitung baris, sehingga Anda dapat melacak seberapa baik pengujian unit Anda menggunakan basis kode Anda.
Dalam file package.json
saya, skrip pengujian menjalankan pengujian dan menghasilkan laporan.
{ "scripts": { "test": "nyc --reporter=lcov --reporter=text mocha -r @babel/register ./src/test/index.js" } }
Dalam prosesnya, itu akan membuat folder .nyc_output
yang berisi informasi cakupan mentah dan folder coverage
yang berisi file laporan cakupan. Kedua file tidak diperlukan di repo saya, jadi saya menempatkannya di file .gitignore
.
Sekarang setelah kami membuat laporan, kami harus mengirimkannya ke Coveralls. Satu hal keren tentang Coverall (dan alat cakupan lainnya, saya asumsikan) adalah bagaimana ia melaporkan cakupan pengujian Anda. Cakupan dipecah berdasarkan file demi file dan Anda dapat melihat cakupan yang relevan, garis tertutup dan tidak terjawab, dan apa yang berubah dalam cakupan build.
Untuk memulai, instal paket coveralls npm. Anda juga perlu masuk ke baju dan menambahkan repo ke dalamnya.
Kemudian atur baju untuk proyek javascript Anda dengan membuat file coveralls.yml
di direktori root Anda. File ini akan menyimpan repo-token
Anda yang didapat dari bagian pengaturan untuk repo Anda di baju.
Skrip lain yang diperlukan dalam file package.json adalah skrip cakupan. Skrip ini akan berguna saat kita membuat build melalui Actions.
{ "scripts": { "coverage": "nyc npm run test && nyc report --reporter=text-lcov --reporter=lcov | node ./node_modules/coveralls/bin/coveralls.js --verbose" } }
Pada dasarnya, itu akan menjalankan tes, mendapatkan laporan, dan mengirimkannya ke baju untuk dianalisis.
Sekarang ke poin utama dari tutorial ini.
Buat File Alur Kerja Node JS
Pada titik ini, kami telah menyiapkan pekerjaan yang diperlukan yang akan kami jalankan di GitHub Action kami. (Bertanya-tanya apa arti "pekerjaan"? Teruslah membaca.)
GitHub telah mempermudah pembuatan file alur kerja dengan menyediakan template starter. Seperti yang terlihat di halaman Tindakan, ada beberapa templat alur kerja yang melayani tujuan berbeda. Untuk tutorial ini, kita akan menggunakan alur kerja Node.js (yang sudah disarankan oleh GitHub).
Anda dapat mengedit file secara langsung di GitHub tetapi saya akan membuat file secara manual di repo lokal saya. Folder .github/workflows
yang berisi file node.js.yml
akan berada di direktori root.
File ini sudah berisi beberapa perintah dasar dan komentar pertama menjelaskan apa yang mereka lakukan.
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
Saya akan membuat beberapa perubahan sehingga selain komentar di atas, itu juga menjalankan liputan.
File .node.js.yml
saya:
name: NodeJS CI on: ["push"] jobs: build: name: Build runs-on: windows-latest strategy: matrix: node-version: [12.x, 14.x] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: npm install - run: npm run build --if-present - run: npm run coverage - name: Coveralls uses: coverallsapp/github-action@master env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} COVERALLS_GIT_BRANCH: ${{ github.ref }} with: github-token: ${{ secrets.GITHUB_TOKEN }}
Apa artinya ini?
Mari kita hancurkan.
-
name
Ini akan menjadi nama alur kerja Anda (NodeJS CI) atau pekerjaan (build) dan GitHub akan menampilkannya di halaman tindakan repositori Anda. -
on
Ini adalah peristiwa yang memicu alur kerja. Baris di file saya pada dasarnya memberi tahu GitHub untuk memicu alur kerja setiap kali Push dilakukan ke repo saya. -
jobs
Alur kerja dapat berisi setidaknya satu atau lebih pekerjaan dan setiap pekerjaan berjalan di lingkungan yang ditentukan olehruns-on
. Dalam contoh file di atas, hanya ada satu pekerjaan yang menjalankan build dan juga menjalankan coverage, dan itu berjalan di lingkungan windows. Saya juga dapat memisahkannya menjadi dua pekerjaan berbeda seperti ini:
File Node.yml yang diperbarui
name: NodeJS CI on: [push] jobs: build: name: Build runs-on: windows-latest strategy: matrix: node-version: [12.x, 14.x] steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: npm install - run: npm run build --if-present - run: npm run test coverage: name: Coveralls runs-on: windows-latest strategy: matrix: node-version: [12.x, 14.x] steps: - uses: coverallsapp/github-action@master env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} with: github-token: ${{ secrets.GITHUB_TOKEN }}
-
env
Ini berisi variabel lingkungan yang tersedia untuk semua atau pekerjaan tertentu dan langkah-langkah dalam alur kerja. Dalam pekerjaan cakupan, Anda dapat melihat bahwa variabel lingkungan telah "tersembunyi". Mereka dapat ditemukan di halaman rahasia repo Anda di bawah pengaturan. -
steps
Ini pada dasarnya adalah daftar langkah-langkah yang harus diambil ketika menjalankan pekerjaan itu. - Pekerjaan
build
melakukan beberapa hal:- Ini menggunakan tindakan checkout (v2 menandakan versi) yang benar-benar memeriksa repositori Anda sehingga dapat diakses oleh alur kerja Anda;
- Ini menggunakan tindakan setup-node yang mengatur lingkungan node yang akan digunakan;
- Ini menjalankan skrip instal, bangun, dan uji yang ditemukan di file package.json kami.
-
coverage
Ini menggunakan tindakan coverallsapp yang memposting data cakupan LCOV suite pengujian Anda ke coveralls.io untuk dianalisis.
Saya awalnya membuat push ke cabang feat-add-controllers-and-route
saya dan lupa menambahkan repo_token dari Coveralls ke file .coveralls.yml
saya, jadi saya mendapatkan kesalahan yang dapat Anda lihat di baris 132.
Bad response: 422 {"message":"Couldn't find a repository matching this job.","error":true}
Setelah saya menambahkan repo_token
, build saya berhasil dijalankan. Tanpa token ini, baju tidak akan dapat melaporkan analisis cakupan pengujian saya dengan benar. Untung GitHub Actions CI kami menunjukkan kesalahan sebelum didorong ke cabang utama.
NB: Ini diambil sebelum saya memisahkan pekerjaan menjadi dua pekerjaan. Juga, saya dapat melihat ringkasan cakupan-dan pesan kesalahan-pada terminal saya karena saya menambahkan flag --verbose
di akhir skrip cakupan saya
Kesimpulan
Kami dapat melihat cara menyiapkan integrasi berkelanjutan untuk proyek kami dan juga mengintegrasikan cakupan pengujian menggunakan Tindakan yang disediakan oleh GitHub. Ada begitu banyak cara lain yang dapat disesuaikan agar sesuai dengan kebutuhan proyek Anda. Meskipun contoh repo yang digunakan dalam tutorial ini adalah proyek yang sangat kecil, Anda dapat melihat betapa pentingnya integrasi berkelanjutan bahkan dalam proyek yang lebih besar. Sekarang pekerjaan saya telah berjalan dengan sukses, saya yakin menggabungkan cabang dengan cabang utama saya. Saya tetap menyarankan agar Anda juga membaca hasil langkah-langkah setelah setiap kali dijalankan untuk melihat bahwa itu benar-benar berhasil.