Make Simple Testing on Golang App

Image by Ildefonso Polo

Assalamu’alaikum Warahmatullah Wabarakatuh,

Oke kita lanjut di part4, sekarang kita coba bikin simple testing pada aplikasi Golang kita.

Okeh langsung aja kita masuk ke kodingan, Yeaay~. Tapi sebelum kita menulis sebuah testing, ada beberapa aturan yang harus kita ikuti untuk menulis sebuah testing di Golang.

  1. nama file yang akan digunakan harus diberikan suffix _test, contoh : main.go → main_test.go, gimana udah paham?
  2. kemudian untuk nama fungsi yang ingin kita buat harus diberikan prefix Test_, contoh : func Test_APIFunctionRoot

Okeh kita lanjut bahas kodingan testing ini.

// Package mainpackage main// Library yang digunakanimport ("io/ioutil""log""net/http""net/http/httptest""testing""github.com/go-chi/chi/v5")// Function Testing Pertamafunc Test_APIFunctionRoot(t *testing.T) {r := chi.NewRouter()r.Get("/", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusOK)w.Write([]byte(`{"status":"root"}`))})ts := httptest.NewServer(r)defer ts.Close()res, err := http.Get(ts.URL + "/")if err != nil {t.Errorf("Expected nil, received %s", err.Error())}if res.StatusCode != http.StatusOK {t.Errorf("Expected %d, received %d", http.StatusOK, res.StatusCode)}}// Function Testing Keduafunc Test_APIFunctionPing(t *testing.T) {r := chi.NewRouter()r.Get("/ping", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusOK)w.Write([]byte(`{"status":"pong"}`))})ts := httptest.NewServer(r)defer ts.Close()res, err := http.Get(ts.URL + "/ping")if err != nil {t.Errorf("Expected nil, received %s", err.Error())}if res.StatusCode != http.StatusOK {t.Errorf("Expected %d, received %d", http.StatusOK, res.StatusCode)}}// Function Testing Ketigafunc Test_APIFunctionPanic(t *testing.T) {r := chi.NewRouter()r.Get("/panic", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusBadRequest)w.Write([]byte(`{"status":"error"}`))})ts := httptest.NewServer(r)defer ts.Close()res, err := http.Get(ts.URL + "/panic")if err != nil {t.Errorf("Expected nil, received %s", err.Error())}if res.StatusCode == http.StatusOK {t.Errorf("Expected %d, received %d", http.StatusBadRequest, res.StatusCode)}}// Function Testing Keempatfunc Test_APIFunctionQuotes(t *testing.T) {r := chi.NewRouter()r.Get("/quotes", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")resp, err := http.Get("https://api.quotable.io/random")if err != nil {log.Fatalln(err)}body, err := ioutil.ReadAll(resp.Body)if err != nil {log.Fatalln(err)}sb := string(body)w.WriteHeader(http.StatusOK)w.Write([]byte(sb))})ts := httptest.NewServer(r)defer ts.Close()res, err := http.Get(ts.URL + "/quotes")if err != nil {t.Errorf("Expected nil, received %s", err.Error())}if res.StatusCode != http.StatusOK {t.Errorf("Expected %d, received %d", http.StatusOK, res.StatusCode)}}

Penjelasan :

Dalam melakukan testing, ada beberapa library yang digunakan, tergantung studi kasus yang kita miliki. Karena ini testing yang simple, kita hanya menggunakan library testing, yaitu library default yang ada pada installasi Golang.

Function Testing Pertama

Kalo kita lihat pada part2, disana saya sudah melampirkan result/hasil dari aplikasi yang kita buat. Pada testing ini saya ingin membuat sekenario apabila kita mengakses routing / maka response yang saya inginkan dari testing ini adalah responsenya tidak null dan http response codenya adalah 200OK

Code:

// root routingr.Get("/", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json") // Content type JSONw.WriteHeader(http.StatusOK) // Response 200OKlog.Println(w.Write([]byte(`{"status":"root"}`)))})

Testing:

// Function Testing Pertamafunc Test_APIFunctionRoot(t *testing.T) {r := chi.NewRouter()r.Get("/", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusOK)w.Write([]byte(`{"status":"root"}`))})ts := httptest.NewServer(r)defer ts.Close()res, err := http.Get(ts.URL + "/")if err != nil {t.Errorf("Expected nil, received %s", err.Error())}if res.StatusCode != http.StatusOK {t.Errorf("Expected %d, received %d", http.StatusOK, res.StatusCode)}}

Function Testing Kedua

Okeh pada testing kedua, kurang lebih sama seperti pada testing yang pertama, apabila kita mengakses routing /ping maka response yang saya inginkan dari testing ini adalah responsenya tidak null dan http response codenya adalah 200 OK

Code:

r.Get("/ping", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json") // Content type JSONw.WriteHeader(http.StatusOK) // Response 200OKlog.Println(w.Write([]byte(`{"status":"pong"}`)))})

Testing:

func Test_APIFunctionPing(t *testing.T) {r := chi.NewRouter()r.Get("/ping", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusOK)w.Write([]byte(`{"status":"pong"}`))})ts := httptest.NewServer(r)defer ts.Close()res, err := http.Get(ts.URL + "/ping")if err != nil {t.Errorf("Expected nil, received %s", err.Error())}if res.StatusCode != http.StatusOK {t.Errorf("Expected %d, received %d", http.StatusOK, res.StatusCode)}}

Function Testing Ketiga

Okeh pada testing ketiga, kurang lebih sama seperti pada testing yang pertama, apabila kita mengakses routing /panic maka response yang saya inginkan dari testing ini adalah responsenya tidak null dan http response codenya adalah 400 Bad Request

Code:

r.Get("/panic", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json") // Content type JSONw.WriteHeader(http.StatusBadRequest) // Response 400 Bad Requestlog.Println(w.Write([]byte(`{"status":"error"}`)))})

Testing:

func Test_APIFunctionPanic(t *testing.T) {r := chi.NewRouter()r.Get("/panic", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusBadRequest)w.Write([]byte(`{"status":"error"}`))})ts := httptest.NewServer(r)defer ts.Close()res, err := http.Get(ts.URL + "/panic")if err != nil {t.Errorf("Expected nil, received %s", err.Error())}if res.StatusCode == http.StatusOK {t.Errorf("Expected %d, received %d", http.StatusBadRequest, res.StatusCode)}}

Function Testing Keempat

Okeh pada testing keempat, kurang lebih sama seperti pada testing yang pertama, apabila kita mengakses routing /quotes maka response yang saya inginkan dari testing ini adalah responsenya tidak null dan http response codenya adalah 200OK

Code:

r.Get("/quotes", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json") // Content type JSONresp, err := http.Get("https://api.quotable.io/random") // Fetch API// Mengecek apabila gagal melakukan fetch APIif err != nil {log.Fatalln(err)}// Mengambil response bodybody, err := ioutil.ReadAll(resp.Body)if err != nil {log.Fatalln(err)}// Mengubah response body menjadisb := string(body)w.WriteHeader(http.StatusOK) // Response 200 OKlog.Println(w.Write([]byte(sb))) // Mencetak response body})

Testing:

func Test_APIFunctionQuotes(t *testing.T) {r := chi.NewRouter()r.Get("/quotes", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")resp, err := http.Get("https://api.quotable.io/random")if err != nil {log.Fatalln(err)}body, err := ioutil.ReadAll(resp.Body)if err != nil {log.Fatalln(err)}sb := string(body)w.WriteHeader(http.StatusOK)w.Write([]byte(sb))})ts := httptest.NewServer(r)defer ts.Close()res, err := http.Get(ts.URL + "/quotes")if err != nil {t.Errorf("Expected nil, received %s", err.Error())}if res.StatusCode != http.StatusOK {t.Errorf("Expected %d, received %d", http.StatusOK, res.StatusCode)}}

Dan untuk melakukan testing, kita bisa menjalankan perintah go ./…

Output :

ok      simple  0.844s

Apabila kita mencoba mengubah studi kasus yang testing maka hasilnya akan seperti ini

Testing:

func Test_APIFunctionRoot(t *testing.T) {r := chi.NewRouter()r.Get("/", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusOK)w.Write([]byte(`{"status":"root"}`))})ts := httptest.NewServer(r)defer ts.Close()res, err := http.Get(ts.URL + "/")if err != nil {t.Errorf("Expected nil, received %s", err.Error())}if res.StatusCode != http.StatusBadRequest {t.Errorf("Expected %d, received %d", http.StatusBadRequest, res.StatusCode)}}

Output:

--- FAIL: Test_APIFunctionRoot (0.00s)main_test.go:27: Expected 400, received 200FAILFAIL    simple  0.859sFAIL

Oke proses testing yang sederhana selesai, terimakasih~

About me

I’m Muhammad Abdur Rofi Maulidin, a DevOps Engineer passionate about optimizing software development processes by supporting cloud infrastructure management like kubernetes orchestration, and automations. Dedicated to support the reliability, availability, and performance of systems by implementing SLI/SLO based on performance monitoring for business requirement.

Feel free to keep in touch with me:

Let’s go to the cloud 🚀

Free Palestine 🇵🇸

--

--