WEB3 폴더에 작성했다.
테스팅 환경을 구축해놓으면 개발하기가 무척 편하다.
지난 시간까지 만들었던 mux를 만들어내는 코드들을 새로운 패키지로 만들 것이다.
WEB3 경로안에 myapp이라는 폴더를 하나 만들고 그 안에 app.go
라는 파일을 만들어준다.
main.go 내용을 app.go로 옮겨주고 메인 함수 부분을 NewHttpHandler() 함수로 변경해준다.
app.gofunc NewHttpHandler() http.Handler { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello World") }) mux.HandleFunc("/bar", barHandler) mux.Handle("/foo", &fooHandler{}) http.ListenAndServe(":3000", mux) return mux }
http.Handler라는 리턴값으로 mux를 내보내고
메인 문에서는 mux를 리턴해주는 app.go의 메소드를 넣어준다.
main.gofunc main() { http.ListenAndServe(":3000", myapp.NewHttpHandler()) }
app.go
에 옮겨주는 작업은 끝났고 이제 테스팅 코드를 만들거다.
WEB3 폴더에 app_test.go
파일을 만들어주는데 Go는 뒤에 _를 붙이고 test라고 하면 test코드로 작동한다.
테스트 코드는 함수명 앞에 Test라고 시작해야한다.
양식이 정해져있는데 t *testing.T
-> testing 패키지에 T 포인터를 인자로 받아야한다.
func TestIndexPathHandler(t *testing.T) {
}
이제 패키지 하나를 설치해야한다.
goconvey : 백그라운드로 돌면서 파일이 갱신될 때마다 자동으로 테스트를 해준다.
설치법은 링크홈페이지에 나와있듯이 cmd로 들어가서
go get github.com/smartystreets/goconvey
를 입력해주면 된다.
그 후에 자신의 WEB3의 디렉토리로 들어가서 goconvey
를 입력해주면 실행이 된다.
그럼 goconvey가 웹 서버를 하나 돌려준다.(cmd를 끄면 안됨)
localhost:8080번에서 돌아간다.
TestIndexHandler가 성공했다고 나와있다.
func TestIndexPathHandler(t *testing.T) {
res := httptest.NewRecorder() // 실제 네트워크를 사용하지않고 실행가능
req := httptest.NewRequest("GET", "/", nil)
indexHandler(res, req) // app.go에서 핸들러를 분리해줌
if res.Code != http.StatusOK {
t.Fatal("Failed!!", res.Code)
}
}
마찬가지로 PASS된다.
if res.Code != http.StatusBadRequest {
t.Fatal("Failed!!", res.Code)
}
코드를 변경하고 기다려보면
fail되는 것을 볼 수 있다.
stretchr에 testify에서 assert파일만 가져올 것이다.
다른 cmd를 열어서
go get github.com/stretchr/testify/assert
를 입력하면 다운받을 수 있다.
import 부분에
"github.com/stretchr/testify/assert"
를 추가하고func TestIndexPathHandler(t *testing.T) { assert := assert.New(t) res := httptest.NewRecorder() // 실제 네트워크를 사용하지않고 실행가능 req := httptest.NewRequest("GET", "/", nil) indexHandler(res, req) assert.Equal(http.StatusOK, res.Code) // 잘 돌아가는지 아닌지 검사 }
로 코드를 변경해준다.
assert 패키지를 가져와서 사용하면 알아서 매번 검사해준다.
실제 Body를 비교해보자
실제 Body값은 res.Body에 들어있다. 하지만 버퍼 클래스라 바로 가져올 수 없어서 ioutil.ReadAll()
을 이용해서 버퍼 값을 읽어오자.
TestIndexPathHandler
메소드에 추가data, _ := ioutil.ReadAll(res.Body) assert.Equal("Hello World", string(data))
마찬가지로 저장하면 알아서 확인해준다.(PASS뜸)
barHandler도 똑같이 추가해보자.
func TestBarPathHandler_WithoutName(t *testing.T) {
assert := assert.New(t)
res := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/bar", nil)
barHandler(res, req)
assert.Equal(http.StatusOK, res.Code)
data, _ := ioutil.ReadAll(res.Body)
assert.Equal("Hello World!", string(data))
}
func TestIndexPathHandler(t *testing.T) {
assert := assert.New(t)
res := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/", nil)
mux := NewHttpHandler()
mux.ServeHTTP(res, req)
assert.Equal(http.StatusOK, res.Code)
data, _ := ioutil.ReadAll(res.Body)
assert.Equal("Hello World", string(data))
}
func TestBarPathHandler_WithoutName(t *testing.T) {
assert := assert.New(t)
res := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/bar", nil)
mux := NewHttpHandler()
mux.ServeHTTP(res, req)
assert.Equal(http.StatusOK, res.Code)
data, _ := ioutil.ReadAll(res.Body)
assert.Equal("Hello World!", string(data))
}
name과 함께 넣기
func TestBarPathHandler_WithName(t *testing.T) {
assert := assert.New(t)
res := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/bar?name=tucker", nil)
mux := NewHttpHandler()
mux.ServeHTTP(res, req)
assert.Equal(http.StatusOK, res.Code)
data, _ := ioutil.ReadAll(res.Body)
assert.Equal("Hello tucker!", string(data))
}
전부 PASS되는 것을 볼 수 있다.
Json도 해주자
func TestFooHandler_WithJson(t *testing.T) {
assert := assert.New(t)
res := httptest.NewRecorder()
req := httptest.NewRequest("POST", "/foo",
strings.NewReader(`{"first_name":"tucker", "last_name":"kim", "email":"tucker@naver.com"}`))
// 인자로 ioreader가 들어와야함. 따라서 string을 reader로 변경해서 넣어준다.
mux := NewHttpHandler()
mux.ServeHTTP(res, req)
assert.Equal(http.StatusCreated, res.Code)
}
string을 reader로 변경해서 넣어줄 때 ""를 써야하므로 인자 전체를 ``로 묶어준다.
// 실제로 데이터가 잘 왔는지 검사해보자
user := new(User)
err := json.NewDecoder(res.Body).Decode(user) // decoder되었으므로 값이 들어와있음
assert.Nil(err) // 에러가 없어야한다.
assert.Equal("tucker", user.FirstName)
assert.Equal("kim", user.LastName)
전부 pass되는 것을 볼 수 있다.
혹시 디버깅에서는 문자열이 틀렸다고 에러가 뜨는데 고컨베이에서는 pass가 나는 부분 어떻게 해결할수 있는지 아시는지요?