1.はじめに
Go言語で単体テストを実施したい
GO言語に標準で含まれている"testing"パッケージを利用してテストコードを書いてみる
以前投稿した以下の記事で作成したGoアプリにテストコードを追加する
Qiitaの最新記事を教えてくれるアレクサスキルを作ろう Alexa X Lambda X Golang
参考
2.単体テスト
2.1 テストファイルを用意する
テストしたいファイルと同じ階層にテストファイルを作成する。
テストファイルの名前は、元のファイル名 + _test.go
にします。そうすることでtestファイルがbuild時に無視されるのでこの命名規則に合わせてテストファイルを作る
# ファイル構造
└─NaviQiita
│
├─cmd
│ └─naviQiita
│ main.go
│ main_test.go # 新規作成
│
├─internal
│ └─qiita
│ qiita.go
| qiita_test.go # 新規作成
│
└─pkg
└─response
response.go
response_test.go # 新規作成
2.2 テストケースの記述
2.2.1 main.go
テストコードに記述する関数名はTestXxx
にする
引数はtesting.T型にする必要がある
(例)func TestXxx(*testing.T)
main.go
package main
import (
"context"
"githun.com/keny-N/NaviQiita/internal/qiita"
"githun.com/keny-N/NaviQiita/pkg/response"
"github.com/aws/aws-lambda-go/lambda"
)
func Handler(ctx context.Context) (response.AlexaResponse, error) {
items, err := qiita.FetchQiitaItems()
if err != nil {
return response.AlexaResponse{}, err
}
message := "最新のQiitaの記事を5つ紹介します。。: "
for _, item := range items {
message += item.Title + ", URL: " + item.URL + ". "
}
return response.CreateResponse(message), nil
}
func main() {
lambda.Start(Handler)
}
main_test.go
package main
import (
"context"
"strings"
"testing"
)
func TestHandler(t *testing.T) {
ctx := context.Background()
resp, err := Handler(ctx)
if err != nil {
t.Fatalf("Handler returned an error: %v", err)
}
// レスポンスの検証(特定のメッセージが含まれていることを確認)
expectedMessageSubstring := "最新のQiitaの記事を5つ紹介します。"
if !contains(resp.Response.OutputSpeech.Text, expectedMessageSubstring) {
t.Errorf("Expected response to contain '%s', got '%s'", expectedMessageSubstring, resp.Response.OutputSpeech.Text)
}
}
func contains(text, substring string) bool {
return strings.Contains(text, substring)
}
2.2.2qiita.go
5件のアイテムを返すことを検証する
qiita.go
package qiita
import (
"encoding/json"
"net/http"
)
type QiitaItem struct {
Title string `json:"title"`
URL string `json:"url"`
}
func FetchQiitaItems() ([]QiitaItem, error) {
resp, err := http.Get("https://qiita.com/api/v2/items?page=1&per_page=5")
if err != nil {
return nil, err
}
defer resp.Body.Close()
var items []QiitaItem
if err := json.NewDecoder(resp.Body).Decode(&items); err != nil {
return nil, err
}
return items, nil
}
qiita_test.go
package qiita
import (
"testing"
)
func TestFetchQiitaItems(t *testing.T) {
items, err := FetchQiitaItems()
if err != nil {
t.Fatalf("FetchQiitaItems() error = %v", err)
}
if len(items) != 5 {
t.Errorf("Expected 2 items, got %d", len(items))
}
}
2.2.3 response.go
レスポンスのバージョンや、タイプ、メッセージの検証を行う
response.go
package response
type AlexaResponse struct {
Version string `json:"version"`
SessionAttributes struct{} `json:"sessionAttributes"`
Response struct {
OutputSpeech struct {
Type string `json:"type"`
Text string `json:"text"`
} `json:"outputSpeech"`
} `json:"response"`
}
func CreateResponse(message string) AlexaResponse {
return AlexaResponse{
Version: "1.0",
Response: struct {
OutputSpeech struct {
Type string `json:"type"`
Text string `json:"text"`
} `json:"outputSpeech"`
}{
OutputSpeech: struct {
Type string `json:"type"`
Text string `json:"text"`
}{
Type: "PlainText",
Text: message,
},
},
}
}
response_test.go
package response
import (
"testing"
)
func TestCreateResponse(t *testing.T) {
message := "テストメッセージ"
expectedType := "PlainText"
result := CreateResponse(message)
if result.Version != "1.0" {
t.Errorf("Expected Version to be '1.0', got '%s'", result.Version)
}
if result.Response.OutputSpeech.Type != expectedType {
t.Errorf("Expected OutputSpeech.Type to be '%s', got '%s'", expectedType, result.Response.OutputSpeech.Type)
}
if result.Response.OutputSpeech.Text != message {
t.Errorf("Expected OutputSpeech.Text to be '%s', got '%s'", message, result.Response.OutputSpeech.Text)
}
}
2.3 テストの実行
`go test コマンドで実行できる
go test ./...
ok githun.com/keny-N/NaviQiita/cmd/naviQiita 0.785s
ok githun.com/keny-N/NaviQiita/internal/qiita 0.753s
ok githun.com/keny-N/NaviQiita/pkg/response 0.100s
-v
をつけると詳細を確認できる
$ go test ./... -v
=== RUN TestHandler
--- PASS: TestHandler (0.21s)
PASS
ok githun.com/keny-N/NaviQiita/cmd/naviQiita 0.414s
=== RUN TestFetchQiitaItems
--- PASS: TestFetchQiitaItems (0.24s)
PASS
ok githun.com/keny-N/NaviQiita/internal/qiita 0.406s
=== RUN TestCreateResponse
--- PASS: TestCreateResponse (0.00s)
PASS
ok githun.com/keny-N/NaviQiita/pkg/response 0.104s
3.まとめ
簡単に単体テストを実行できる方法を試してみました。
gomockをつかってテストをする方法などもあるのでプライベートでも今後動かしてみたいと思います。