Di artikel ini akan dibahas tentang automation testing di pengembangan suatu aplikasi. Mungkin kalian sering mendengar istilah-istilah black-box-testing, white-box-testing, unit-test, coverage-test, snapshot-test, & visual-regression-test. Disini akan dicoba dibahas satu persatu sesuai pengalaman saya. Kalau ada yang salah silakan comment π
Untuk memudahkan memahami kita akan membuat satu project supaya bisa lebih dipahami tentang teknik-teknik testing tersebut. OK, kita mulai saja y π
Note:
Goal artikel ini adalah supaya bisa dimengerti automation testing dengan unit-test, coverage-test, snapshot-test, & visual-regression-test di suatu function & component suatu aplikasi web. Tetapi, sepertinya pembahasannya terlalu panjang. Jadi, di artikel ini hanya dijelaskan tentang unit-test & coverage-test beserta contoh implementasinya di suatu function. Lanjutan testing di component akan dibuat di artikel selanjutnya.

Dalam pengembangan sebuah aplikasi ada suatu tahapan yang wajib, harus, dan tidak boleh tidak dilakukan sebelum me-release aplikasi ke tahap production, yaitu Testing. Tahapan ini dilakukan untuk meminimalisir segala jenis bug yang mungkin akan terjadi. Tujuan akhirnya adalah untuk meyakinkan seluruh pihak bahwa aplikasi yang telah dikembangkan terbebas dari bug dan aman untuk digunakan oleh user/customer.
Pada pendekatan jaman dahulu β mungkin sekarang juga masih π β biasanya semua testing diserahkan kepada Tim QA Engineer. Sebelum diserahkan ke QA Engineer, developer juga tentu saja sudah memastikan pekerjaannya terbebas dari bug.
Kekurangan model testing ini adalah:
- Hanya si developer yang tau bagaimana untuk memastikan source code terbebas dari bug
- Ketika ada developer lain yang bermaksud merubah source code tersebut, akan lebih susah memastikan perubahannya masih terbebas dari bug
- Dalam jangka waktu yang lama, semua developer akan lupa bagaimana cara untuk memastikan source code lama mereka terbebas dari bug

Solusi untuk kekurangan diatas adalah developer wajib, harus, dan tidak boleh tidak melakukan testing secara tertulis sebelum pekerjaannya diserahkan ke tim QA Engineer untuk diuji. Dengan cara ini seluruh tim developer bisa melihat testing baik dari proses ataupun hasilnya. Hal ini akan sangat berguna untuk memastikan source code yang dibuat sudah bug free, dan juga ketika melakukan refactor, source code yang diubah oleh seorang developer tidak merusak code yang telah dibuat sebelumnya. Jadi, sebagai developer kita bisa memiliki ketenangan batin ketika harus melakukan refactor.
Nah, sebenarnya testing yang seperti apa sih yang bisa dibuat oleh seorang developer?
Dalam dunia per-testing-an dikenal istilah White-Box-Testing & Black-Box-Testing. Makin aneh aja nih ya. heheβ¦
Black-Box-Testing
Pada teknik ini dilakukan testing berdasarkan fungsionalitas suatu aplikasi tanpa perlu mengetahui detail logic ataupun source code yang dipakai. Testing ini berfokus pada kesesuaian antara input & output dari aplikasi yang dibangun.
Pada aplikasi web, biasanya testing ini dilakukan secara manual di browser oleh QA Engineer untuk memastikan aplikasi web yang dibangun sudah terbebas dari bug dan juga sesuai secara UI & fungsionalitasnya. Namun sebenarnya hal ini bisa dibuat secara otomatis yang idealnya dilakukan oleh QA Automation Engineer dengan metode end-to-end-testing dengan tools yang ada dipasaran seperti selenium, cypress, dll.
White-Box-Testing
Pada teknik ini dilakukan testing berdasarkan detail logic dan source code suatu aplikasi. Di teknik ini, developer akan menuliskan testing script terhadap setiap baris code suatu aplikasi yang biasa disebut dengan unit-test.
Unit-test adalah jenis automated-software-testing yang dipakai untuk menguji unit-unit kecil yang menyusun sebuah aplikasi. Unit ini sendiri bisa berupa sebuah function, class ataupun component. Unit-test yang dibuat harus efektif bisa memastikan semua baris & kondisi yang ada di unit tersebut telah diuji dengan baik. Semakin banyak baris & rumitnya kompleksitas suatu unit, tentu saja akan membuat testing yang dibuat juga menjadi lebih banyak & kompleks. Pada akhirnya developer akan bertanya-tanya:
Apakah unit-test yang dibuat sudah cukup efektif?
Apakah unit-test yang dibuat sudah bisa digunakan untuk memastikan aplikasi terbebas dari bug?β
Nah, untuk menjawab pertanyaan-pertanyaain tersebut kita perlu mengetahui tingkat coverage dari unit-test yang dibuat. Untungnya, diluar sana sudah ada tools yang bisa digunakan untuk melakukan coverage-test secara otomatis.
Coverage-test adalah cara untuk mengetahui prosentase pencapaian testing berdasarkan unit-test yang telah dibuat. Digunakan untuk melihat apakah unit-test yang kita buat sudah bisa meng-cover seluruh baris & kemungkinan proses yang ada di suatu unit. Coverage-test dikategorikan menjadi beberapa hal: Lines, Statements, Branch, dan Functions.
- Lines
Merepresentasikan baris-baris di source code yang harus dieksekusi di proses unit-testing. - Statements
Merepresentasikan tindakan di source code yang harus dieksekusi minimal sekali di proses unit-testing. biasanya dipisahkan oleh β;β tergantung bahasa pemrograman yang digunakan.
Misal:
var x= 10; console.log(x);
syntax diatas memiliki 1 line & 2 statement.
Statements coverage berkaitan dengan Lines coverage. Ketika Statement coverage memiliki 100% coverage, berarti bisa dipastikan Lines coverage juga 100%, tetapi tidak berlaku kebalikannya. - Branch
Merepresentasikan keseluruhan kondisi-kondisi di source code yang harus dieksekusi di proses unit-testing. Misal untuk kondisi if-else, dua kondisi tersebut harus ada di unit-test yang dibuat.
Branch coverage berkaitan dengan Statement coverage. Ketika Branch coverage memiliki 100% coverage, berarti bisa dipastikan Statements coverage juga 100%, tetapi tidak berlaku kebalikannya. - Functions
Merepresentasikan keseluruhan function di source code yang harus dieksekusi di proses unit-testing.
Sebagai tambahan, ketika kita membahas testing di aplikasi web, testing untuk bagian UI juga sangat diperlukan untuk menjaga integritas UI tersebut. Apalagi ketika kita membangun aplikasi web dengan konsep atomic component. Kesalahan di atom component bisa berakibat menjalar ke molecule component. Untuk menghindari kesalahan-kesalahan tersebut kita bisa melakukan testing terkait UI ini, yaitu dengan teknik snapshot-test & visual-regression-test.
Snapshot-Test adalah teknik testing yang sangat berguna untuk memastikan UI yang kita buat tidak berubah secara tiba-tiba tanpa kita harapkan. Dengan snapshot-test ini kita bisa mengetahui secara keseluruhan UI mana saja yang berubah ketika kita merubah UI di suatu component. Ketika perubahan itu memang sesuai yang diharapkan, kita bisa meng-update snapshot yang ada. Namun ketika perubahan itu tidak diharapkan, bisa digunakan sebagai acuan untuk perbaikan.
Visual-Regression-Test adalah teknik testing yang hampir sama dengan snapshot-test, yaitu untuk melakukan verifikasi aspek visual dari suatu aplikasi. Perbedaannya adalah dengan visual-regression-test kita bisa melihat perbedaan langsung dengan mata kita karena bisa ditampilkan melalui browser. 3 hal yang akan diinformasikan dengan visual-regression-test ini adalah kondisi awal, perubahan, dan hasil akhirnya. Jadi kita bisa mengetahui hal yang berubah secara detail. Hal ini membantu kita untuk mengidentifikasi perubahan walaupun perubahan tersebut sangat kecil. Misal, terjadi perubahan style di bagian padding sebesar 1px. Dengan hanya penglihatan visual manusia tentu akan sulit mendeteksi perubahan tersebut.

Notes:
Testing yang dilakukan ini tidak menjamin aplikasi yang dibangun benar-benar 100% terbebas dari Bug. Tetapi hal ini bisa digunakan untuk mengurangi resiko terjadinya bug yang sangat tidak kita inginkan.
OK, cukup teorinya. Sekarang kita coba lakukan percobaan untuk lebih memahami tentang unit-test & coverage-test. untuk melakukan teknik-teknik testing tersebut, kita akan membuat project dengan menggunakan jest.
Experiment
Kita akan coba setup suatu project dan melakukan percobaan-percobaan di project ini. Di awal percobaan ini kita akan mencoba-coba untuk lebih mendalami unit-test & coverage-test. Ikuti langkah-langkah di bawah ini:
- Buat suatu folder, misal dengan nama web-automation-testing
- Buat file dengan nama file bigger.js. Function isBigger adalah function untuk mengecek apakah parameter a lebih besar dari b.
//bigger.js
const isBigger = (a, b) => {
let big = true;
if (b > a) {
big = false;
}
if (b === a) { big = true }
return big;
}
module.exports = { isBigger };
- Buat file dengan nama package.json yang didalamnya terdapat dependency Jest untuk keperluan instalasi & script yang digunakan untuk menjalankan testing.
//package.json
{
"name": "web-automation-testing",
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "jest",
"test-cov": "jest --coverage"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"jest": "^24.9.0"
}
}
- Buat file dengan nama jest.config.js yang didalamnya terdapat configurasi Jest.
//jest.config.js
module.exports = {
bail: false,
verbose: true,
coverageReporters: ["json", "html", "text", "clover"],
}
- Lalu terakhir, buat file dengan nama index.js untuk memanggil function isBigger diatas.
//index.js
const { isBigger } = require('./bigger');const isbigger = isBigger(2,1)
console.log("is a bigger than b? ", isbigger)
untuk mengecek setup ini sudah berhasil atau belum, bisa dibuka terminal dan lakukan perintah:
npm i && npm start
Maka di terminal akan ditampilkan output:

Cukup mudah kan setup mini project ini? π
Sekarang kita siap untuk mencoba-coba sambil memahami unit-test & coverage-test di Jest.
Unit-Test Experiment
Buat file test dengan nama bigger.test.js yang akan digunakan untuk melakukan unit-testing terhadap file bigger.js
//bigger.test.js
const { isBigger } = require('./bigger');test('a is bigger than b', () => {
expect(isBigger(4, 1)).toBe(true);
});
Dengan contoh kasus diatas, maka ketika unit-test ini dilakukan dengan script npm run test, akan menghasilkan output console seperti berikut:

Dari hasil ini bisa disimpulkan testing untuk function isBigger dengan unit-test expect(isBigger(4, 1)).toBe(true) sudah bisa digunakan untuk memastikan hasil 4>1=true.
Pada unit-test diatas dilakukan hanya 1 kali pengecekan untuk kondisi a>b. Dengan hanya 1 pengecekan ini, apakah unit-test ini sudah cukup? atau kita harus menambahkan kondisi lain lagi? Untuk mengetahuinya kita bisa melakukan coverage-test.
Coverage-Test Experiment
Untuk menjalankan coverage-test cukup dengan mengeksekusi script npm run test-cov. Ketika kita jalankan coverage-test akan muncul result seperti ini:

Di hasil diatas bisa dilihat kalau unit-test yang kita buat belum bisa meng-cover seluruh Lines, Statement, Branch & Functions.
Untuk melihat baris yang belum ter-cover kita bisa lihat bagian Uncovered Lines. Tetapi data diatas belum bisa membantu kita untuk mengetahui sebenarnya bagian mana yang kurang . Untungnya di project ini sudah di-setup untuk configurasi output coverage yang dihasilkan dalam bentuk html. Report hasil coverage-test ini dikumpulkan di folder coverage di project ini. Di dalam folder coverage tersebut bisa dibuka file index.html di browser. Kurang lebih tampilannya akan seperti ini:

Di html report ini akan ditampilkan seluruh file/folder yang sudah diuji. Dan file-file tersebut bisa di-klik untuk melihat lebih detail lagi hasil coverage-test. Dalam testing kali ini akan ditampilkan hasil testing seperti berikut:

Berdasarkan output report tersebut bisa ditarik beberapa kesimpulan berdasarkan 4 kategori coverage:
- Lines
Lines Coverage belum bisa menghasilkan angka 100%, hanya di angka 85,71% (6/7) karena terdapat baris-baris yang belum pernah dieksekusi, yaitu baris 4. Kok bisa tau baris ke-4 yang belum ter-cover?
Cara membacanya bisa dilihat di report html ini pada bagian frekuensi eksekusinya berwarna pink, sedangkan yang lainnya sudah dieksekusi sebanyak 1x dan berwarna hijau.
Uncovered lines ini disebabkan karena di unit-test tidak melakukan pengecekan kondisi b>a. - Statements
Statements Coverage belum bisa menghasilkan angka 100%, hanya di angka 75% (6/8) karena terdapat statement yang belum pernah dieksekusi, yaitu di baris 4 & 6 (ditandai dengan highlight berwarna pink di statements yang belum tereksekusi).
Inilah contoh yang membedakan Lines & Statements. Pada Lines, baris ke 6 dianggap sudah masuk coverage, tetapi di baris ke 6 memiliki 2 statement, yaitu if (a===b) dan big=true, dimana big=true belum pernah dieksekusi. - Branch
Branch Coverage belum bisa menghasilkan angka 100%, hanya di angka 50% (2/4) karena terdapat kondisi yang belum dieksekusi, yaitu di kondisi di baris 3 & 6 (ditandai dengan I untuk If, E untuk Else, atau biasanya dengan highlight berwarna kuning) - Functions
Function Coverage sudah bisa menghasilkan angka 100% karena function isBigger sudah pernah dieksekusi di unit-test yang dibuat.
Solusi supaya coverage diatas bisa 100% semua adalah harus ditambahkan unit-test di file bigger.test.js
const { isBigger } = require('./bigger');test('a is bigger than b', () => {
expect(isBigger(4, 1)).toBe(true); // a>b=true
});test('a is not bigger than b', () => {
expect(isBigger(1, 4)).toBe(false); // a>b=false
});test('a is not bigger than b', () => {
expect(isBigger(1, 1)).toBe(false); // a>b=false
});
Dengan penambahan unit-test tersebut, ternyata bisa menghasilkan output report sebagai berikut:

Ternyata ada unit-test yang melaporkan hasil yang tidak sesuai dengan ekspektasi, yaitu di line 10 yang menguji 1>1=false. Issue ini bisa saja kesalahan dari unit-test nya, ataupun function yang sedang diuji. Setelah kita lihat kembali unit-test yang dibuat sudah benar. Berarti kesalahan ada di function yang sedang diuji. coba kita lihat kondisi a===b apakah sudah benar?
Di file bigger.js terdapat baris if (b === a) { big = true }. Ini adalah kondisi yang salah. Seharusnya if (b === a) { big = false }. Ok, mari kita koreksi code di file bigger.js
//bigger.js
const isBigger = (a, b) => {
let big = true;
if (b > a) {
big = false;
}
if (b === a) { big = false }
return big;
}
module.exports = { isBigger };
Ini adalah salah satu fungsi unit-test. Bisa melakukan pengecekan kesalahan yang tak sengaja kita buat. Sehingga pada akhirnya kita bisa lebih PeDe function isBigger ini sudah bug free.
Tanpa berlama-lama, mari kita coba eksekusi lagi npm run test, hasilnya adalah:

Berhasil!!!
OK, sekarang kita coba eksekusi coverage-test dengan npm run test-cov, hasilnya adalah:

Yeay, coverage-nya juga sudah 100% sekarang.
Gimana? sudah mengerti sekarang apa itu unit-test & coverage-test beserta implementasinya? Harusnya sudah y. Kalo masih bingung bisa dicoba-coba kembali instruksi sampai paham π¬
Berikutnya kita akan melakukan percobaan lebih jauh lagi, yaitu unit-test, coverage-test, snapshot-test & visual-regression-test di suatu component.
Source code bisa dilihat di sini.