Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Moch. Lutfi
Moch. Lutfi

Posted on • Originally published atlumochift.org on

     

Tips dan trik unit test di Go

Unit Test memang tidak bisa dilepaskan dari proses pengembangansoftware. Namun seringkali dalam pembuatanUnit Test di Go terjadi banyak repetisi yang tidak perlu danUnit Test yang tidak dikelola dengan baik. Salah satu contoh kasus yang paling banyak ditemui dalam pembuatanUnit Test yaitu tidak dipisahkannyalogic dan data sehingga ketika penambahan data test terdapat penambahan pulalogic.

Contoh Kode

Sebelum memulai lebih lanjut berikut adalah contoh kode untuk membantu memahami tulisan ini.

  • Struktur direktori
$ tree .├── add.go└── add_test.go
  • Fileadd.go
packagemain//TambahmerupakanfungsisederhanapenjumlahanfuncTambah(a,bint)int{returna+b}
  • Fileadd_test.go
packagemainimport"testing"funcTestBasic(t*testing.T){ifTambah(1,1)!= 2{t.Error("seharusnya 2")}ifTambah(1,2)!= 3{t.Error("seharusnya 3")}//kodeberulangsebanyakjumlahdatatest}
$ go test -v=== RUN TestBasic--- PASS: TestBasic (0.00s)PASSok github.com/h4ckm03d/blog-codes/golang101/6-tips-trik-unit-test 0.002s

Memanfaatkanarray of struct

ContohUnit Test diatas merupakan contoh paling sederhana, jika yang sederhana saja sudah terlalu verbose dan susah dikelola bagaimana jika kode dalam suatupackage semakin besar? Salah satu cara untuk memisahkanlogic unit test dengan data yaitu menggunakan unit testarray of struct untuk data dan tinggal menambahkan looping data ketika pengecekan. Tambahkan fungsi dibawah ini ke dalamadd_test.go

func TestB(t *testing.T) {    testData := []struct {        name string        inputA int        inputB int        result int    }{        {"1+1", 1, 1, 2},        {"1+2", 1, 2, 3},        {"1+3", 1, 3, 4},    }    for _, tc := range testData {        t.Run(tc.name, func(t *testing.T) {            if Tambah(tc.inputA, tc.inputB) != tc.result {                t.Errorf("Seharusnya %d", tc.result)            }        })    }}

JikaUnit Test dijalankan maka hasilnya seperti berikut:

$ go test -v=== RUN TestBasic--- PASS: TestBasic (0.00s)=== RUN TestB=== RUN TestB/1+1=== RUN TestB/1+2=== RUN TestB/1+3--- PASS: TestB (0.00s)    --- PASS: TestB/1+1 (0.00s)    --- PASS: TestB/1+2 (0.00s)    --- PASS: TestB/1+3 (0.00s)PASSok github.com/h4ckm03d/blog-codes/golang101/6-tips-trik-unit-test 0.002s

DalamTestB diatas ketika data test bertambah, kita hanya perlu menambahkan kedalamarraytestData tanpa perlu merubahlogic sehingga kode lebih mudah dibaca dan dimodifikasi.struct dalam peubahtestData terdiri dari 3 bagian label test(name), input data (inputA,inputB), dan output dari fungsi (result). Untuk input data dan output bisa diganti sesuai dengan fungsi yang ditest. Hasil running dari unit test juga lebih jelas jika menggunakan metode ini karena penggunaan label membantu tracking ketika ada kesalahan. MisalkantestData 1 ditambah 1 diubah menjadi 7 untuk mengetahui contoh jika unit test menghasilkan error, hasilnya sebagai berikut:

$ go test -v=== RUN TestBasic--- PASS: TestBasic (0.00s)=== RUN TestB=== RUN TestB/1+1=== RUN TestB/1+2=== RUN TestB/1+3--- FAIL: TestB (0.00s)    --- FAIL: TestB/1+1 (0.00s)        add_test.go:34: Seharusnya 7    --- PASS: TestB/1+2 (0.00s)    --- PASS: TestB/1+3 (0.00s)FAILexit status 1FAIL github.com/h4ckm03d/blog-codes/golang101/6-tips-trik-unit-test 0.005s

Karena output diubah menjadi 7 sehingga unit testnya fail, akan tetapi karena menggunakan label kita segera mengetahui data apa yang salah sehingga bug fix lebih mudah.

Fatal VS Error

Pada fungsiTestBasic diatas menggunakant.Error("seharusnya 2"), kenapa menggunakant.Error bukan menggunakant.Fatal ? Penggunaanerror diatas karena ketika terjadi kesalahan misalkan output salah atau tidak sesuai maka unit test tidak akan berhenti tetapi melanjutkan sampai semua proses dalam fungsi tersebut selesai. Jika menggunakanfatal maka ketikat.Fatal ataut.Fatalf dipanggil maka proses dihentikan. Dalam hal ini ketika 1 + 1 terjadi error maka proses berhenti dan tidak dilanjutkan pengecekan 1 + 2. Berikut contoh perbedaan penggunaanfatal danerror.

func TestBasicFatal(t *testing.T) {    if Tambah(1, 1) != 3 {        t.Error("seharusnya 2")    }    if Tambah(1, 2) != 4 {        t.Error("seharusnya 3")    }    // kode berulang sebanyak jumlah data test}func TestBasicError(t *testing.T) {    if Tambah(1, 1) != 3 {        t.Error("seharusnya 2")    }    if Tambah(1, 2) != 4 {        t.Error("seharusnya 3")    }    // kode berulang sebanyak jumlah data test}

Hasilgo test -v sebagai berikut

$ go test -v=== RUN TestBasic--- PASS: TestBasic (0.00s)=== RUN TestBasicFatal--- FAIL: TestBasicFatal (0.00s)        add_test.go:21: seharusnya 2=== RUN TestBasicError--- FAIL: TestBasicError (0.00s)        add_test.go:33: seharusnya 2        add_test.go:37: seharusnya 3=== RUN TestB=== RUN TestB/1+1=== RUN TestB/1+2=== RUN TestB/1+3--- PASS: TestB (0.00s)    --- PASS: TestB/1+1 (0.00s)    --- PASS: TestB/1+2 (0.00s)    --- PASS: TestB/1+3 (0.00s)FAILexit status 1FAIL github.com/h4ckm03d/blog-codes/golang101/6-tips-trik-unit-test 0.004s

KetikaTestBasicFatal dijalankan maka ketika ada error proses berhenti berbeda denganTestBasicError, meskipun ada error proses dilanjutkan sampai selesai.

Dengan pemisahan kodeUnit Test dan penggunaan error/fatal yang tepat kita bisa lebih optimal memanfaatkan unit test. Semoga bermanfaat dan sampai jumpa lagi di tulisan selanjutnya.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

gopher
  • Location
    Malang
  • Joined

More fromMoch. Lutfi

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp