1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Golang]Elasticsearchのテストフィクスチャ管理ライブラリ「go-elasticsearch-testfixtures」を作った

1
Posted at

本記事でやること

Elasticsearchを使ったアプリケーションの統合テストにおいて、テストデータ(フィクスチャ)を簡単に管理するためのGoライブラリ「go-elasticsearch-testfixtures」を紹介します。

対象読者

  • GoでElasticsearchを使ったアプリケーションを開発している方
  • 統合テストでElasticsearchのテストデータ管理に課題を感じている方
  • go-testfixturesを使ったことがある方

なぜ作ったのか

これまでいくつかのGo製API + Elasticsearchの構成でプロダクトを実装してきました。

毎回繰り返していたこと

  • インデックス作成・削除のヘルパーメソッドを書く
  • テストデータ投入処理を書く
  • スタブデータの定義場所・型についてチームで議論する

本来やるべきこと

  • どのようなテストをすべきか考える
  • どのようなテストデータを用意すべきか考える
  • 素早く実装する

定型的なセットアップコードではなく、テスト設計に時間をかけるべきです。

統一された方法でシンプルに管理したい。 そう思って作ったのが「go-elasticsearch-testfixtures」です。

go-testfixturesというアプローチ

Goには、RDB向けの優れたテストフィクスチャライブラリ「go-testfixtures」があります。

このライブラリは、YAMLファイルでテストデータを宣言的に管理し、Load()を呼ぶだけでデータベースをクリーンな状態にリセットしてくれます。

# testdata/fixtures/users.yml
- id: 1
  name: Alice
  email: alice@example.com

- id: 2
  name: Bob
  email: bob@example.com
fixtures.Load()  // これだけでOK

このアプローチをElasticsearchにも適用したい。しかし、go-testfixturesのメンテナーは「非リレーショナルデータベースはこのパッケージのスコープ外」と明言しています。

"non-relational databases are out-of-the-scope of this package."
"If you're willing to work on that, that could be a different package since the code will differ a lot from testfixtures anyway."

そこで、go-testfixturesのアプローチにインスパイアされた別パッケージとして「go-elasticsearch-testfixtures」を作りました。

go-elasticsearch-testfixturesの設計

ディレクトリ構造 = インデックス構造

フィクスチャはディレクトリとファイルで管理します。

testdata/fixtures/
├── users/
│   ├── _mapping.json       # インデックスのマッピング定義
│   ├── _settings.json      # インデックスの設定(任意)
│   └── documents.yml       # テストドキュメント
└── products/
    ├── _mapping.json
    └── documents.yml
  • 各サブディレクトリがElasticsearchのインデックスに対応
  • _mapping.jsonでマッピングを定義(ES Mappings APIと同じ形式)
  • _settings.jsonで設定を定義(任意)
  • *.ymlファイルにテストドキュメントを記述

ファイル形式

_mapping.json

{
  "properties": {
    "name": { "type": "text" },
    "email": { "type": "keyword" },
    "age": { "type": "integer" }
  }
}

documents.yml

- _id: "1"
  name: "Alice"
  email: "alice@example.com"
  age: 30

- _id: "2"
  name: "Bob"
  email: "bob@example.com"
  age: 25

_idフィールドは特別扱いされ、ElasticsearchのドキュメントIDとして使用されます。省略すると自動生成されます。

削除→再作成でテスト間の干渉を防止

Load()を呼ぶと、以下の処理が実行されます。

  1. 既存のインデックスを削除
  2. マッピング・設定を適用してインデックスを作成
  3. ドキュメントを一括挿入
  4. インデックスをリフレッシュ(即座に検索可能に)

毎回クリーンな状態からスタートするので、テスト間の干渉を確実に防げます。

使い方

インストール

go get github.com/kurakura967/go-elasticsearch-testfixtures

基本的な使い方

var fixtures *testfixtures.Loader

func TestMain(m *testing.M) {
    client, _ := elasticsearch.NewClient(elasticsearch.Config{
        Addresses: []string{"http://localhost:9200"},
    })

    fixtures, _ = testfixtures.New(
        client,
        testfixtures.Directory("testdata/fixtures"),
    )

    os.Exit(m.Run())
}

func TestSearchUsers(t *testing.T) {
    fixtures.Load()
    t.Cleanup(func() { fixtures.Clean() })

    // テスト本体
}

テスト例

func TestSearchUsers(t *testing.T) {
    if err := fixtures.Load(); err != nil {
        t.Fatal(err)
    }
    t.Cleanup(func() { fixtures.Clean() })

    // age >= 30 のユーザーを検索
    query := `{
        "query": {
            "range": { "age": { "gte": 30 } }
        }
    }`

    res, err := client.Search(
        client.Search.WithIndex("users"),
        client.Search.WithBody(strings.NewReader(query)),
    )
    if err != nil {
        t.Fatal(err)
    }
    defer res.Body.Close()

    // 結果を検証...
}

今後の展望

現在の実装はシンプルですが、以下の機能追加を検討しています。

  • インデックスプレフィックス対応: テストごとにユニークなプレフィックスを付けることで、並列テスト実行をサポート
  • テンプレート機能: go-testfixturesのように、YAMLファイル内でGoテンプレートを使用できるように
  • 複数のフィクスチャセット: テストシナリオに応じて異なるデータセットを切り替え

まとめ

テストコードは、ビジネスロジックの検証に集中すべきです。セットアップの定型作業はライブラリに任せましょう。

「go-elasticsearch-testfixtures」は、Elasticsearchの統合テストにおけるフィクスチャ管理をシンプルにするためのライブラリです。

OSSとして公開しているので、ぜひ使ってみてください。フィードバックやContributionも歓迎です!

GitHub: https://github.com/kurakura967/go-elasticsearch-testfixtures

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?