Belajar Melakukan Unit Testing dengan Benar

Disclaimer: tulisan ini murni pendapat dan unek-unek pribadi berdasarkan apa yang pernah saya alami sewaktu kuliah mata kuliah rekayasa perangkat lunak (terutama pada waktu pelaksanaan praktikumnya).

Sekilas tentang basis path testing

Pada mata kuliah RPL, teknik pengujian whitebox yang diajarkan adalah basis path testing testing. Teknik ini digunakan untuk mencari semua independent path yang ada dalam sebuah kode program, lalu menghitung cyclomatic complexity yang mana ia menandakan kompleksitas sebuah kode program juga menandakan jumlah independent path yang ada. Lalu, kita dapat membuat testcase sesuai dengan independent path yang telah ditemukan sebelumnya. Setelah mendapatkan testcase baru kita jalankan testnya. Referensi lengkap tentang basis path testing/structured testing dapat diakses disini.

Permasalahannya

Konsep basis path testing sebenarnya tidak ada yang salah. Menurut saya, memang melalui cara itu untuk dapat merumuskan testcase yang nantinya akan digunakan dalam menjalankan testing.
Namun, yang menjadi masalah ketika pada waktu praktikum adalah, pada saat melakukan testingnya masih manual dengan cara menjalankan aplikasinya secara langsung. Pada perkuliahan, kita memang tidak dikenalkan dengan apa yang bernama test framework macam Jest, JUnit, XCTest, RSpec, dan lain-lain, beserta cara pakainya (ok, ini harusnya kita belajar sendiri, kalau mau belajar). Dan, yang membuat geli adalah, di penulisan laporan praktikumnya untuk menyatakan bahwa hasil testingnya valid tidaknya seperti ini.
laporan praktikum punya saya
laporan praktikum punya senior
Sekilas terlihat benar, namun pertanyaannya adalah, dari mana bisa tahu kalau itu valid apa tidak sedangkan bukti valid atau tidaknya tidak disertakan.
Mengapa melakukan unit testing dengan cara menjalankan aplikasinya secara langsung/manual, lalu melakukan komparasi expected result dan actual result secara manual. Padahal banyak test framework yang bisa dipakai untuk mempermudah proses unit testing (karena automated), jadi tidak perlu repot dengan cara manual seperti itu. Selain repot juga sangat memakan waktu jika masih dengan cara manual.
Dan, saya baru menyadari bahwa yang seperti itu salah setelah semester 5 telah berlalu, setelah belajar bagaimana cara melakukan unit testing dan TDD.
Hingga sekarang, kesalahan ini masih berlangsung dan masih dibiarkan.

Jadi, yang benar harusnya bagaimana?

Singkatnya, pakai test framework untuk mempermudah menjalankan testing. Konsep basis path testing masih bisa dipakai untuk mempermudah kita untuk membuat testcase.
Saya akan berikan contoh, bagaimana cara melakukan unit testing dengan bantuan test framework, tanpa melupakan konsep basis path testing yang telah diajarkan di kuliah. Untuk implementasinya saya akan contohkan dengan Javascript+Jest.
PS: test framework yang dipakai harus sesuai dengan bahasa pemrograman yang kita pakai.
Dalam test coding calon engineer, ada soal yang bernama Fizzbuzz. Soal ini sangat sederhana, kita disuruh untuk membuat suatu function yang mengembalikan nilai Fizz jika inputan adalah kelipatan 3, Buzz jika kelipatan 5, Woof jika kelipatan 7. Selain kelipatan 3, 5 maupun 7 maka harus mengembalikan nilai aslinya.
Pseudocodenya seperti ini
1  function fizzbuzz(val) {
2    if (val % 3 == 0) {
3      return 'fizz'
4    } else if (val % 5 == 0) {
5      return 'buzz'
6    } else if (val % 7 == 0) {
7      return 'woof'
8    } else {
9      return val
10   }
11  }
Baru kita gambar flowgraphnya
Independent pathnya sebagai berikut:
  1. 2,3,10
  2. 2,4,5,10
  3. 2,4,6,7,10
  4. 2,4,6,8,9,10
Ok, sekarang hitung berapa cyclomatic complexitynya…
V(G) = E - N + 2
V(G) = 11 - 9 + 2
V(G) = 11 - 7
V(G) = 4 
Berarti kita akan butuh minimal 4 testcase.
Untuk implementasi dalam Javascript seperti ini…
Karena butuh 4 testcase, maka tiap path testcasenya, misalkan seperti ini:
  1. 2,3,10 testcase_val = 6
  2. 2,4,5,10 testcase_val = 25
  3. 2,4,6,7,10 testcase_val = 49
  4. 2,4,6,8,9,10 testcase_val = 11
Nah, sekarang bagaimana cara nulis test kalau pakai Jest?
Ketika file test tadi dijalankan, maka Jest akan menjalankan blok pada line 4–18. Line 4–18 tadi itulah yang disebut testcase. Nanti akan menghasilkan output seperti ini (jika testnya passed semua)
hasil jest assertion
Kode diatas bisa dicoba pada repl dibawah.
Jadi, pada dasarnya, ketika akan melakukan unit testing, terdapat pattern yang disebut sebagai Arrange-Act-Assert, atau 3A.
Arrange, adalah mempersiapkan semua precondition dan input yang akan digunakan untuk melakukan testing.
Act, lakukan testing pada kode yang akan dites.
Assert, bandingkan antara expected result dengan actual result yang didapat setelah proses eksekusi testing.

Apakah hanya sesederhana itu melakukan unit testing?

Belum tentu, pada suatu kasus lain kita harus melakukan mocking pada system under test, seperti contoh untuk melakukan unit testing pada sebuah function yang melakukan parsing JSON ke objek dari sebuah REST API endpoint atau data source lain.
Dalam system under test, REST API endpoint atau data source lain harus di mock. Kenapa? Karena pada testing, khususnya unit testing, harus terisolasi dari pengaruh eksternal. Sedangkan, penggunaan REST API memiliki banyak pengaruh yang dapat memengaruhi jalannya testing, seperti masalah koneksi internet.
Selain itu pula, kualitas kode program juga memengaruhi mudah/sulitnya dalam melakukan testing.

Kembali lagi….

Kembali lagi bahasan mengapa di kuliah, khususnya pada praktikum RPL yang kalau saya lihat masih banyak yang salah dalam mengeksekusi unit testnya, karena tidak ada ceritanya melakukan unit testing dengan menjalankan aplikasinya secara manual, input data manual, lalu compare hasilnya manual.
Saya beri contoh bagaimana engineer Microsoft menulis test untuk melakukan testing pada editor Visual Studio Code mereka, tinggal buka link disini untuk melihat test scriptnya.
Mereka melakukan testnya secara automated, seperti pada guidenya disini.
Tidak dengan cara manual seperti yang teman-teman (termasuk saya) yang dulu pada waktu praktikum RPL lakukan dengan cara yang salah dan sangat tidak efisien.