テスト
esa-cliのテスト実行方法と、テストの追加方法について説明します。
テストの基本方針
Section titled “テストの基本方針”- 標準の
testing
パッケージを使用 - 各テストは独立して実行可能
- テストデータは適切にクリーンアップ
テストの実行
Section titled “テストの実行”- Go 1.21以上
make
コマンドが利用可能- インターネット接続
テストの実行方法
Section titled “テストの実行方法”- すべてのテストを実行
make test
- 特定のパッケージのテストを実行
go test ./pkg/...
- 特定のテストファイルを実行
go test ./pkg/commands/...
- テストカバレッジの確認
make test-coverage
テストの種類
Section titled “テストの種類”ユニットテスト
Section titled “ユニットテスト”各パッケージの機能を個別にテストします。
# 例:コマンドパッケージのテストgo test ./pkg/commands/...
複数のパッケージを組み合わせた機能をテストします。
# 例:記事の取得から更新までの一連の流れgo test ./tests/integration/...
E2Eテスト
Section titled “E2Eテスト”実際のesa.io APIを使用して、エンドツーエンドの動作をテストします。
# E2Eテストの実行make test-e2e
テストの構造
Section titled “テストの構造”テストは「Given-When-Then」の考え方に基づいて構造化します:
func Test機能名(t *testing.T) { // Given: テストの前提条件を記述 tests := []struct { name string setup func() // 前提条件のセットアップ input interface{} want interface{} wantErr bool }{ { name: "正常系:記事一覧を取得できる", setup: func() { // テストの前提条件をセットアップ }, input: "入力値", want: "期待値", wantErr: false, }, { name: "異常系:無効なトークンの場合はエラーを返す", setup: func() { // エラーケースの前提条件をセットアップ }, input: "不正な入力", want: nil, wantErr: true, }, }
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Given: 前提条件のセットアップ if tt.setup != nil { tt.setup() }
// When: テスト対象の関数を実行 got, err := テスト対象の関数(tt.input)
// Then: 結果の検証 if (err != nil) != tt.wantErr { t.Errorf("関数名() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { t.Errorf("関数名() = %v, want %v", got, tt.want) } }) }}
テストの命名規則
Section titled “テストの命名規則”- テストファイル:
{テスト対象ファイル名}_test.go
- テスト関数:
Test{機能名}
- サブテスト: 以下の形式で記述
- 正常系:
正常系:{期待される動作}
- 異常系:
異常系:{エラー時の動作}
- エッジケース:
エッジケース:{特殊な条件}
- 境界値:
境界値:{境界条件}
- 正常系:
テストの品質基準
Section titled “テストの品質基準”- テストは独立して実行可能
- テストは再現可能
- テストは高速に実行可能
- テストは適切にエラーメッセージを出力
- テストは適切にログを出力
テストの追加基準
Section titled “テストの追加基準”- 新機能追加時は必ずテストを追加
- バグ修正時は必ずテストを追加
- リファクタリング時は既存のテストを維持
- テストの追加は機能の実装前に行う
モックの使用
Section titled “モックの使用”外部依存(API等)は必ずモック化します:
type MockAPIClient struct { // モックの実装}
func (m *MockAPIClient) GetArticle(id int) (*Article, error) { // モックの実装}
テストヘルパー
Section titled “テストヘルパー”package testutil
import ( "os" "path/filepath" "testing")
// テスト用の一時ディレクトリを作成func CreateTempDir(t *testing.T) string { t.Helper() dir, err := os.MkdirTemp("", "esa-cli-test-*") if err != nil { t.Fatal(err) } t.Cleanup(func() { os.RemoveAll(dir) }) return dir}
// テスト用の記事データを作成func CreateTestPost(t *testing.T) string { t.Helper() return `---title: テスト記事category: testtags: [test]wip: false---
テスト本文`}
トラブルシューティング
Section titled “トラブルシューティング”テストが失敗する場合
Section titled “テストが失敗する場合”- テストの実行環境を確認
go versionmake --version
- 依存関係の確認
go mod tidy
- キャッシュのクリア
go clean -testcache
テストカバレッジが低い場合
Section titled “テストカバレッジが低い場合”- カバレッジレポートの確認
make test-coverage
- 未テストのコードの特定
go tool cover -html=coverage.out
関連ドキュメント
Section titled “関連ドキュメント”- 開発者ガイド - 開発に関する全般的な情報
- リリース手順 - リリースプロセスの説明
- コマンドリファレンス - コマンドの詳細な説明