Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
30 Oct 2022 · 7 mnt baca ·Artikel 19 / 119
Go

Cara Membuat Unit Test Pada Golang

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

Unit Testing Menggunakan Library Go

Pemrograman tidak mudah bahkan programmer terbaik tidak mampu menulis program yang bekerja persis seperti yang diinginkan setiap saat. Oleh karena itu bagian penting dari proses pengembangan perangkat lunak adalah pengujian (testing). Menulis test untuk kode kita adalah cara yang baik untuk memastikan kualitas dan meningkatkan keandalan.

Go menyediakan package testing, berisikan banyak sekali tools untuk keperluan unit test. Pada chapter ini kita akan belajar mengenai testing, benchmark, dan juga testing menggunakan testify.

Go menyertakan program khusus yang membuat tes menulis lebih mudah, jadi mari kita buat beberapa test untuk paket yang kita buat di sesi ini. Di folder 01-math buat file baru bernama math_test.go yang berisi ini.

Sebelumnya kita telah buat suatu function sebagai berikut ini.

go
1package main
2
3func Average(xs []float64) float64 {
4	total := float64(0)
5	for _, x := range xs {
6		total += x
7	}
8	return total / float64(len(xs))
9}
agar kita bisa membuat unit test maka kita generate menggunakan vscode, maka akan membuat file baru math_test.go dan men-generate fungsi TestAverage dengan isi dibawah ini.
go
 1func TestAverageGenerate(t *testing.T) {
 2	type args struct {
 3		xs []float64
 4	}
 5	tests := []struct {
 6		name string
 7		args args
 8		want float64
 9	}{
10		{
11			name: "must 10",
12			args: args{
13				xs: []float64{10.0, 10.0},
14			},
15			want: float64(10),
16		},
17	}
18	for _, tt := range tests {
19		t.Run(tt.name, func(t *testing.T) {
20			if got := Average(tt.args.xs); got != tt.want {
21				t.Errorf("Average() = %v, want %v", got, tt.want)
22			}
23		})
24	}
25}

Unit Test Program Ganjil Genap

Buat fungsi untuk menentukan bahwa program tersebut mengeluarkan informasi yang diinput terkait angka ganjil dan genap.

go
1func GanjilGenap(angka int) string {
2	if angka%2 == 0 {
3		return "genap"
4	}
5	return "ganjil"
6}
Maka kita akan buat unit test-nya seperti ini:
go
 1package math
 2
 3import (
 4	"testing"
 5)
 6
 7func TestAverageGenerate(t *testing.T) {
 8	type args struct {
 9		xs []float64
10	}
11	tests := []struct {
12		name string
13		args args
14		want float64
15	}{
16		{
17			name: "must 10",
18			args: args{
19				xs: []float64{10.0, 10.0},
20			},
21			want: float64(10),
22		},
23	}
24	for _, tt := range tests {
25		t.Run(tt.name, func(t *testing.T) {
26			if got := Average(tt.args.xs); got != tt.want {
27				t.Errorf("Average() = %v, want %v", got, tt.want)
28			}
29		})
30	}
31}
32
33type testpair struct {
34	values  []float64
35	average float64
36}
37
38var tests = []testpair{
39	{[]float64{1, 2}, 1.5},
40	{[]float64{1, 1, 1, 1, 1, 1}, 1},
41	{[]float64{-1, 1}, 0},
42}
43
44func TestAverage(t *testing.T) {
45	for _, pair := range tests {
46		v := Average(pair.values)
47		if v != pair.average {
48		}
49	}
50}
51
52func TestGanjilGenap(t *testing.T) {
53	type args struct {
54		angka int
55	}
56	tests := []struct {
57		name string
58		args args
59		want string
60	}{
61		{
62			name: "test case mengeluarkan ganjil",
63			args: args{
64				angka: 1,
65			},
66			want: "ganjil",
67		},
68		{
69			name: "test case mengeluarkan genap",
70			args: args{
71				angka: 2,
72			},
73			want: "genap",
74		},
75		{
76			name: "test case mengeluarkan -1",
77			args: args{
78				angka: -1,
79			},
80			want: "ganjil",
81		},
82	}
83	for _, tt := range tests {
84		t.Run(tt.name, func(t *testing.T) {
85			if got := GanjilGenap(tt.args.angka); got != tt.want {
86				t.Errorf("GanjilGenap() = %v, want %v", got, tt.want)
87			}
88		})
89	}
90}

Testing Tabung

Pertama siapkan terlebih dahulu sebuah struct Tabung. Variabel object hasil struct ini nantinya kita gunakan sebagai bahan testing.

go
 1package math
 2
 3import "math"
 4
 5type Tabung struct {
 6	Jarijari, Tinggi float64
 7}
 8
 9func (t Tabung) Volume() float64 {
10	return math.Phi * math.Pow(t.Jarijari, 2) * t.Tinggi
11}
12
13func (t Tabung) Luas() float64 {
14	return 2 * math.Phi * t.Jarijari * (t.Jarijari + t.Tinggi)
15}
16
17func (t Tabung) KelilingAlas() float64 {
18	return 2 * math.Phi * t.Jarijari
19}
Maka kita akan membuat unit test satu-satu dari fungsi yang sudah kita buat. Bisa dilihat sebagai berikut.

Unit Test untuk fungsi Volume

go
 1func TestTabung_Volume(t *testing.T) {
 2	type fields struct {
 3		Jarijari float64
 4		Tinggi   float64
 5	}
 6	tests := []struct {
 7		name   string
 8		fields fields
 9		want   float64
10	}{
11		{
12			name: "testing hitung volume",
13			fields: fields{
14				Jarijari: 7, Tinggi: 10,
15			},
16			want: float64(792.8366544874485),
17		},
18	}
19	for _, tt := range tests {
20		t.Run(tt.name, func(t *testing.T) {
21			tr := Tabung{
22				Jarijari: tt.fields.Jarijari,
23				Tinggi:   tt.fields.Tinggi,
24			}
25			if got := tr.Volume(); got != tt.want {
26				t.Errorf("Tabung.Volume() = %v, want %v", got, tt.want)
27			}
28		})
29	}
30}

Unit Test untuk fungsi Luas Permukaan

go
 1func TestTabung_Luas(t *testing.T) {
 2	type fields struct {
 3		Jarijari float64
 4		Tinggi   float64
 5	}
 6	tests := []struct {
 7		name   string
 8		fields fields
 9		want   float64
10	}{
11		{
12			name: "testing hitung luas permukaan",
13			fields: fields{
14				Jarijari: 7, Tinggi: 10,
15			},
16			want: float64(385.092089322475),
17		},
18	}
19	for _, tt := range tests {
20		t.Run(tt.name, func(t *testing.T) {
21			tr := Tabung{
22				Jarijari: tt.fields.Jarijari,
23				Tinggi:   tt.fields.Tinggi,
24			}
25			if got := tr.Luas(); got != tt.want {
26				t.Errorf("Tabung.Luas() = %v, want %v", got, tt.want)
27			}
28		})
29	}
30}

Unit test untuk Keliling Alas

go
 1func TestTabung_KelilingAlas(t *testing.T) {
 2	type fields struct {
 3		Jarijari float64
 4		Tinggi   float64
 5	}
 6	tests := []struct {
 7		name   string
 8		fields fields
 9		want   float64
10	}{
11		{
12			name: "testing hitung keliling alas",
13			fields: fields{
14				Jarijari: 7, Tinggi: 10,
15			},
16			want: float64(22.65247584249853),
17		},
18	}
19	for _, tt := range tests {
20		t.Run(tt.name, func(t *testing.T) {
21			tr := Tabung{
22				Jarijari: tt.fields.Jarijari,
23				Tinggi:   tt.fields.Tinggi,
24			}
25			if got := tr.KelilingAlas(); got != tt.want {
26				t.Errorf("Tabung.KelilingAlas() = %v, want %v", got, tt.want)
27			}
28		})
29	}
30}
Cara eksekusi testing adalah menggunakan command go test. Argument -v atau verbose digunakan menampilkan semua output log pada saat pengujian.

Jalankan program seperti di bawah ini, terlihat bahwa tidak ada test yang fail.

bash
 1➜  tabung git:(main) ✗ go test -v
 2=== RUN   TestTabung_Volume
 3=== RUN   TestTabung_Volume/testing_hitung_volume
 4--- PASS: TestTabung_Volume (0.00s)
 5    --- PASS: TestTabung_Volume/testing_hitung_volume (0.00s)
 6=== RUN   TestTabung_Luas
 7=== RUN   TestTabung_Luas/testing_hitung_luas_permukaan
 8--- PASS: TestTabung_Luas (0.00s)
 9    --- PASS: TestTabung_Luas/testing_hitung_luas_permukaan (0.00s)
10=== RUN   TestTabung_KelilingAlas
11=== RUN   TestTabung_KelilingAlas/testing_hitung_keliling_alas
12--- PASS: TestTabung_KelilingAlas (0.00s)
13    --- PASS: TestTabung_KelilingAlas/testing_hitung_keliling_alas (0.00s)
14PASS
15ok      github.com/santekno/tabung      0.486s

Method Test

MethodKegunaan
Log()Menampilkan log
Logf()Menampilkan log menggunakan format
Fail()Menandakan terjadi Fail() dan proses testing fungsi tetap diteruskan
FailNow()Menandakan terjadi Fail() dan proses testing fungsi dihentikan
Failed()Menampilkan laporan fail
Error()Log() diikuti dengan Fail()
Errorf()Logf() diikuti dengan Fail()
Fatal()Log() diikuti dengan failNow()
Fatalf()Logf() diikuti dengan failNow()
Skip()Log() diikuti dengan SkipNow()
Skipf()Logf() diikuti dengan SkipNow()
SkipNow()Menghentikan proses testing fungsi, dilanjutkan ke testing fungsi
Skiped()Menampilkan laporan skip
Parallel()Menge-set bahwa eksekusi testing adalah parallel

Catatan Perintah Test

Perintah untuk melihat coverage dari unit test dalam projek

bash
1➜  tabung git:(main) ✗ go test -coverprofile=coverage.out
2PASS
3coverage: 100.0% of statements
4ok      github.com/santekno/tabung      0.750s

Perintah untuk melihat code mana saja yang sudah cover unit test

bash
1➜  tabung git:(main) ✗ go tool cover -html=coverage.out
Maka hasilnya akan generate html yang berupa visualiasi dari unit test yg sudah tercover ataupun yang belum

Perintah untuk melakukan generate ulang menggunakan moq

bash
1$ cd <folder-yang-akan-di-generate>
2$ go generate ./...
Pastikan juga pada fungsi interface ditambahkan paling atas struct seperti ini
go
1// go:generate moq -out main_mock_test.go . UserRepositoryInterface
dengan aturan seperti ini go:generate moq -out <nama-file-mock-test> . <struct-interface-yang-akan-dibuat-mock>

Artikel Terkait

💬 Komentar