- 서버의 코드를 Refactoring 하기 전에 먼저 테스트 코드를 작성하여, Refactoring 을 하는 중간 과정마다 제대로 작동하는지 체크할 것이다.
- 먼저 "/todos" 경로로 "name"에 값을 넣어 POST 요청을 보내어 값을 비교하는 테스트 케이스를 두 개 추가한다.
func TestTodos(t *testing.T) {
assert := assert.New(t)
// 테스트 서버 open
ts := httptest.NewServer(MakeHandler())
defer ts.Close()
// "/todos" 경로로 "name"에 값을 넣어 POST 요청
res, err := http.PostForm(ts.URL+"/todos", url.Values{"name": {"Test todo"}})
assert.NoError(err)
assert.Equal(http.StatusCreated, res.StatusCode)
// 응답 메시지의 Body 에서 값을 읽어와 todo 에 저장하여 비교
var todo Todo
err = json.NewDecoder(res.Body).Decode(&todo)
assert.NoError(err)
assert.Equal(todo.Name, "Test todo")
// id1 := todo.ID
res, err = http.PostForm(ts.URL+"/todos", url.Values{"name": {"Test todo 2"}})
assert.NoError(err)
assert.Equal(http.StatusCreated, res.StatusCode)
err = json.NewDecoder(res.Body).Decode(&todo)
assert.NoError(err)
assert.Equal(todo.Name, "Test todo 2")
// id2 := todo.ID
}

- 다음은 "/todos" 로 GET 요청을 보내 리스트 배열을 가져와 todos 에 저장하여 id와 내용을 비교하는 테스트 코드이다.
func TestTodos(t *testing.T) {
...
...
// "/todos" 로 GET 요청을 보내 리스트 배열을 가져와 todos 에 저장하여 id와 내용 비교
res, err = http.Get(ts.URL + "/todos")
assert.NoError(err)
assert.Equal(http.StatusOK, res.StatusCode)
todos := []*Todo{}
err = json.NewDecoder(res.Body).Decode(&todos)
assert.NoError(err)
assert.Equal(len(todos), 2)
for _, t := range todos {
if t.ID == id1 {
assert.Equal(t.Name, "Test todo")
} else if t.ID == id2 {
assert.Equal(t.Name, "Test todo 2")
} else {
assert.Error(fmt.Errorf("testID should be id1 or id2"))
}
}
}
- 다음은 id 를 query 에 넣어 "/complete-todo/" + id 의 체크박스 상태를 변경하고 비교하는 테스트 코드이다.
func TestTodos(t *testing.T) {
...
...
// "/complete-todo/" + id 의 체크박스 상태 변경
res, err = http.Get(ts.URL + "/complete-todo/" + strconv.Itoa(id1) + "?complete=true")
assert.NoError(err)
assert.Equal(http.StatusOK, res.StatusCode)
res, err = http.Get(ts.URL + "/todos")
assert.NoError(err)
assert.Equal(http.StatusOK, res.StatusCode)
todos = []*Todo{}
err = json.NewDecoder(res.Body).Decode(&todos)
assert.NoError(err)
assert.Equal(len(todos), 2)
for _, t := range todos {
if t.ID == id1 {
assert.True(t.Completed)
}
}
}

- 다음은 "/todos/" + id 로 delete 요청을 보냈을 때 삭제 여부를 체크하는 테스트 코드이다.
- http 패키지는 delete 와 put, patch 를 지원하지 않기 때문에 NewRequest 로 해결한다.
- 삭제를 하면 todos 리스트에는 자료가 1개 남는다. len 이 1과 일치하는지 확인하고, 첫 번째 자료의 id 가 id2 인지 비교한다.
func TestTodos(t *testing.T) {
...
...
// "/todos/" + id 로 delete 요청을 보냈을 때 삭제 여부 체크
// http 패키지는 delete 와 put, patch 를 지원하지 않기 때문에 NewRequest 로 해결한다.
req, _ := http.NewRequest("DELETE", ts.URL+"/todos/"+strconv.Itoa(id1), nil)
res, err = http.DefaultClient.Do(req)
assert.NoError(err)
assert.Equal(http.StatusOK, res.StatusCode)
res, err = http.Get(ts.URL + "/todos")
assert.NoError(err)
assert.Equal(http.StatusOK, res.StatusCode)
todos = []*Todo{}
err = json.NewDecoder(res.Body).Decode(&todos)
assert.NoError(err)
assert.Equal(len(todos), 1)
for _, t := range todos {
assert.Equal(t.ID, id2)
}
}
- 이제 app 의 모든 기능을 테스트하는 코드가 완성되었다.
- 테스트 코드 작성하는게 귀찮을 수 있지만, 테스트 코드가 있으면 Refactoring을 할 때 그 이상의 시간을 절약할 수 있고 매우 유용하게 사용된다고 한다!