Menggunakan Direktori testdata

Jika kita periksa coverage test, pada file handlers_test.go, masih ada yang tercover, yaitu bagian render. Kita akan buat test untuk melakukan rendering bad template dengan menggunakan testdata.

Dengan menggunakan testdata, akan memudahkan melakukan testing tanpa harus menyentuh realdata.

Pertama kita perlu pindahkan dulu variable templatePath dari file handlers_test.go pada fungsi Test_application_handlers ke file setup_test.go

package main

import (
	"os"
	"testing"
)

var app application

func TestMain(m *testing.M) {
	templatePath = "./../../templates/"
	app.Session = getSession() //tambahkan session pada modul test
	os.Exit(m.Run())
}

Buat direktori testdata didalam cmd/web.

Perhatian: nama folder harus testdata. Dengan menggunakan folder khusus ini, saat build aplikasi akan diabaikan.

Kemudian buat file templates cmd/web/testdata/bad.page.gohtml, yang isinya dicopy dari home.page.gohtml dengan sedikit modifikasi.

{{template "base" .}}

{{define "content"}}
    <div class="container">
        <div class="row">
            <div class="col">
                <h1 class="mt-3">Home Page</h1>
                <hr>
                <form action="/login" method="post">
                <div class="mb-3">
                    <label for="email" class="form-label">Email address</label>
                    <input type="email" class="form-control" id="email" name="email">
                </div>
                <div class="mb-3">
                    <label for="password" class="form-label">Password</label>
                    <input type="password" class="form-control" id="password" name="password">
                </div>
                <button type="submit" class="btn btn-primary">Submit</button>
                </form>                
                <hr>
                <small>{{$nonExistVar}}</small>
            </div>
        </div>
    </div>
{{end}}

Karena kita menggunakan base template, buat juga file cmd/web/testdata/base.layout.gohtml, yang isinya persis sama dengan templates/base.layout.gohtml.

Langkah terakhir adalah membuat fungsi test, buka file cmd/web/handlers_test.go, lalu tambahkan fungsi untuk test bad template, pada tutorial digunakan nama fungsi TestApp_renderWBadTemplate.

package main

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

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

	routes := app.routes()

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

	//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)
		}
	}

}

func TestAppHome(t *testing.T) {
	var tests = []struct {
		name         string
		putInSession string
		expctedHTML  string
	}{
		{"First Visit", "", "<small>Session:"},
		{"Second Visit", "skillplus", "<small>Session: skillplus"},
	}

	for _, e := range tests {
		req, _ := http.NewRequest("GET", "/", nil)

		req = addCtxSessToReq(req, app)
		_ = app.Session.Destroy(req.Context())

		if e.putInSession != "" {
			app.Session.Put(req.Context(), "test", e.putInSession)
		}

		rr := httptest.NewRecorder()

		handler := http.HandlerFunc(app.Home)
		handler.ServeHTTP(rr, req)

		//check status code
		if rr.Code != http.StatusOK {
			t.Errorf("TestAppHome: returned wrong status code, expected 200 but got %d", rr.Code)
		}

		body, _ := io.ReadAll(rr.Body)
		if !strings.Contains(string(body), e.expctedHTML) {
			t.Errorf("%s: did not find %s in response body", e.name, e.expctedHTML)
		}
	}
}

func TestApp_renderWBadTemplate(t *testing.T) {
	templatePath = "./testdata/"

	req, _ := http.NewRequest("GET", "/", nil)
	req = addCtxSessToReq(req, app)
	rr := httptest.NewRecorder()

	err := app.render(rr, req, "bad.page.gohtml", &TemplateData{})

	if err == nil {
		t.Error("Expected error from bad template, but did not")
	}

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

func addCtxSessToReq(req *http.Request, app application) *http.Request {
	req = req.WithContext(context.WithValue(req.Context(), contextUserKey, "unknown"))
	ctx, _ := app.Session.Load(req.Context(), req.Header.Get("X-Session"))

	return req.WithContext(ctx)
}

Sampai disini kita sudah mempelajari cara melakukan testing untuk session. Pada modul selanjutnya kita akan mempelajari post testing.

Sharing is caring:

Leave a Comment