GinkgoフレームワークによるGoPoolテストコードのリファクタリング

既存のテストコードは gopool_test.go ファイルに集中しており、可読性と保守性の向上が必要となっていた。このため、Ginkgoテストフレームワークを導入してテスト構造を見直すことにした。

Ginkgo環境のセットアップ

まず、GinkgoとGomegaライブラリをプロジェクトに追加する:

go get github.com/onsi/ginkgo/v2/ginkgo
go get github.com/onsi/gomega

次に、テストスイートを作成:

ginkgo bootstrap

これにより gopool_suite_test.go ファイルが生成される。続いて、テストファイルの雛形を作成:

ginkgo generate gopool

機能テストの移行

既存のテストケースをGinkgo形式に変換した例:

package gopool_test

import (
    . "github.com/onsi/ginkgo/v2"
    . "github.com/onsi/gomega"
    
    "github.com/devchat-ai/gopool"
    "errors"
    "sync"
    "time"
)

var _ = Describe("ワーカープールの機能検証", func() {
    Context("뮤텍スロック使用時", func() {
        It("正常にタスクを処理できる", func() {
            workerPool := gopool.NewGoPool(100, gopool.WithLock(new(sync.Mutex)))
            defer workerPool.Release()
            
            for idx := 0; idx < 1000; idx++ {
                workerPool.AddTask(func() (interface{}, error) {
                    time.Sleep(10 * time.Millisecond)
                    return nil, nil
                })
            }
            workerPool.Wait()
        })
    })

    Context("エラーハンドリング", func() {
        It("コールバックでエラーを受け取る", func() {
            testErr := errors.New("処理エラー")
            workerPool := gopool.NewGoPool(100, gopool.WithErrorCallback(func(err error) {
                Expect(err).To(Equal(testErr))
            }))
            defer workerPool.Release()

            for idx := 0; idx < 1000; idx++ {
                workerPool.AddTask(func() (interface{}, error) {
                    return nil, testErr
                })
            }
            workerPool.Wait()
        })
    })
})

ベンチマークテストの分離

パフォーマンス測定用のコードは別ファイルに分離:

package gopool

import (
    "sync"
    "testing"
    "time"
)

func BenchmarkWorkerPoolMutex(b *testing.B) {
    var waitGroup sync.WaitGroup
    taskCount := int(1e6)
    poolInstance := NewGoPool(1e4, WithLock(new(sync.Mutex)))
    defer poolInstance.Release()

    b.ResetTimer()
    for cycle := 0; cycle < b.N; cycle++ {
        waitGroup.Add(taskCount)
        for taskId := 0; taskId < taskCount; taskId++ {
            poolInstance.AddTask(func() (interface{}, error) {
                time.Sleep(10 * time.Millisecond)
                waitGroup.Done()
                return nil, nil
            })
        }
        waitGroup.Wait()
    }
    b.StopTimer()
}

バージョン互換性への注意

Ginkgo v2を使用する際は、インポートパスにバージョンを明示する必要がある:

// 正しいインポート
. "github.com/onsi/ginkgo/v2"

// 古い形式(競合を引き起こす可能性)
. "github.com/onsi/ginkgo"

依存関係の更新後、go.modファイルには以下が含まれるべきである:

require (
    github.com/onsi/ginkgo/v2 v2.11.0
    github.com/onsi/gomega v1.27.10
)

新しいテスト構造により、各機能の検証が明確に分離され、テスト結果の可読性が大幅に向上した。Ginkgoの詳細な出力機能を利用することで、テスト実行状況をより詳細に把握できるようになった。

タグ: Ginkgo Gomega Goテスト テストリファクタリング GoPool

7月5日 22:14 投稿