Setup Test Environment Menggunakan testing.M

Sebelum kita melanjutkan ke modul web app testing menggunakan session. Pada modul ini kita akan sedikit membahas Test Environment.

Dapat kita lihat, fungsi test yang dibuat, menggunakan var app application dilakukan berulang kali pada fungsi dan file test yang berbeda.

Kita dapat menggunakan Test Environment untuk mendeklarasikannya secara global, sehingga dapat digunakan oleh masing-masing fungsi dan file test.

Untuk membuat test environment, buat file pada cmd/web/, dengan nama (wajib) setup_test.go

package main

import (
	"os"
	"testing"
)

var app application

// fungsi khusus, harus menggunakan nama fungsi seperti dibawah.
// fungsi ini akan selalu dijalankan diawal testing.
func TestMain(m *testing.M) {
	os.Exit(m.Run())
}

Saat ini test environment yang kita buat hanya mendeklarasikan var app application saja.

Berikutnya, kita buang semua deklarasi var app application pada file test.

File handlers_test.go

package main

import (
	"net/http"
	"net/http/httptest"
	"testing"
)

func Test_application_handlers(t *testing.T) {
	var theTests = []struct {
		name               string
		url                string
		expectedStatusCode int
	}{
		{"home", "/", http.StatusOK},
		{"404", "/qwerty", http.StatusNotFound},
	}

	//menggunakan environment variable
	//var app application

	routes := app.routes()

	//create a test server
	ts := httptest.NewTLSServer(routes)
	defer ts.Close()

	templatePath = "./../../templates/"

	//testing
	for _, e := range theTests {
		resp, err := ts.Client().Get(ts.URL + e.url)
		if err != nil {
			t.Log(err)
			t.Fatal(err)
		}

		if resp.StatusCode != e.expectedStatusCode {
			t.Errorf("for %s: expected status %d, but got %d", e.name, e.expectedStatusCode, resp.StatusCode)
		}
	}

}

File midlleware_test.go

package main

import (
	"context"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

func Test_application_addIPToContext(t *testing.T) {
	tests := []struct {
		headerName   string
		heaaderValue string
		addr         string
		emptyaddr    bool
	}{
		{"", "", "", false},
		{"", "", "", true},
		{"X-Forwarded-For", "192.163.1.3", "", false},
		{"", "", "hello:skillplus", false},
	}

	//menggunakan environment variable
	//var app application

	//create dummy handler
	nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		//check whether value exists in the context
		val := r.Context().Value(contextUserKey)
		if val == nil {
			t.Error(contextUserKey, "not present")
		}

		//make sure get the string back
		ip, ok := val.(string)
		if !ok {
			t.Error("not string")
		}
		t.Log(ip)
	})

	for _, e := range tests {
		//create handler for test
		handlerToTest := app.addIPToContext(nextHandler)

		req := httptest.NewRequest("GET", "http://testing/", nil)

		if e.emptyaddr {
			req.RemoteAddr = ""
		}

		if len(e.headerName) > 0 {
			req.Header.Add(e.headerName, e.heaaderValue)
		}

		if len(e.addr) > 0 {
			req.RemoteAddr = e.addr
		}

		handlerToTest.ServeHTTP(httptest.NewRecorder(), req)
	}
}

func Test_application_ipFromContext(t *testing.T) {
	//menggunakan environment variable
	//var app application

	//get a context
	ctx := context.Background()

	//put somtehing in the context
	ctx = context.WithValue(ctx, contextUserKey, "random")

	//call the function
	ip := app.ipFromContext(ctx)

	//perform test
	if !strings.EqualFold("random", ip) {
		t.Error("wrong value returned from context")
	}
}

File routes_test.go

package main

import (
	"net/http"
	"strings"
	"testing"

	"github.com/go-chi/chi/v5"
)

func Test_application_routes(t *testing.T) {
	var registered = []struct {
		route  string
		method string
	}{
		{"/", "GET"},
		{"/login", "POST"},
		{"/static/*", "GET"},
	}

	//menggunakan environment variable
	//var app application

	mux := app.routes()

	chiRoutes := mux.(chi.Routes)

	for _, route := range registered {
		//check if the route exists
		if !routeExists(route.route, route.method, chiRoutes) {
			t.Errorf("route %s is not registered", route.route)
		}
	}
}

func routeExists(testRoute, testMethod string, chiRoutes chi.Routes) bool {
	found := false

	_ = chi.Walk(chiRoutes, func(method string, route string, handler http.Handler, middleware ...func(http.Handler) http.Handler) error {
		if strings.EqualFold(method, testMethod) && strings.EqualFold(route, testRoute) {
			found = true
		}
		return nil
	})

	return found
}

Silakan jalankan test untuk memastikan modifikasi diatas tidak menyebabkan error.

$ go test ./...

ok      webapp/cmd/web  0.307s
Sharing is caring:

Leave a Comment