Documentation
¶
Overview ¶
Package testutil はテストで共通して使用するユーティリティ関数を提供する。
Overview ¶
testutilパッケージは、テスト全体で共有される便利な関数やヘルパーを提供します。 主に、並行テスト実行時の競合状態を避けるためのユーティリティと、 テスト実行速度を最適化するための軽量なWorld初期化機能を含みます。
World初期化 ¶
このパッケージは軽量なテスト用World初期化関数を提供します:
InitTestWorld() - 軽量な初期化
- ECS、RawMaster、Dungeonリソースのみを初期化
- フォント、スプライトシート、UIリソースは読み込まない
- 実行時間: 約1-5ms(従来の約40-50倍高速)
- RawMasterは全テストで共有されるためメモリ効率も良い
使用例 ¶
基本的な使い方:
func TestGameLogic(t *testing.T) {
t.Parallel()
world := testutil.InitTestWorld(t)
// エンティティ操作、アイテムのテストなど
}
適用範囲 ¶
InitTestWorld は以下のテストで使用できます:
- エンティティの作成・操作をテストする
- ゲームロジック(クラフト、戦闘、移動など)をテストする
- アイテムやレシピの動作をテストする
- worldhelperパッケージの関数をテストする
- UIを使わないテスト全般
UIテストの場合:
- UIコンポーネントのテストでは、各テストファイルで必要に応じて maingame.InitWorld()を直接呼び出すか、独自のヘルパーを作成してください
並行テストにおける競合回避 ¶
InitTestWorld()はRawMasterを一度だけ読み込んで全テストで共有することで、 並行テスト実行時の競合状態(concurrent map writes)を避けつつ高速に実行できます。
パフォーマンス比較 ¶
100個のテストケースを実行した場合の推定時間:
- maingame.InitWorld() 直接使用: 約5-10秒
- InitTestWorld(): 約0.1-0.5秒(並行実行可能、40-50倍高速)
設計上の利点 ¶
- テストの並行実行を維持(テスト実行速度の最適化)
- 共有リソースへのアクセスを保護(競合状態の回避)
- 各テストが完全に独立したWorldインスタンスを取得
- 必要最小限のリソースのみを読み込む(メモリ効率)
- 既存のテストコードへの影響を最小限に抑える
歴史的背景 ¶
当初、equip_menu_sort_test.goで"fatal error: concurrent map writes"が発生しました。 これは、複数のテストが並行してInitWorld()を呼び出すことで、内部のリソースローダーが 同時にマップに書き込むことが原因でした。
解決策の進化: 1. t.Parallel()を削除 → テスト速度が低下 2. mutex保護でInitWorld()を順次実行 → 競合は解決したが依然として遅い 3. InitTestWorld()を作成 → 速度と安全性を両立
これにより、以下のような多数のテストで安全に並行実行できるようになりました:
- worldhelper/craft_test.go
- worldhelper/currency_test.go
- worldhelper/equipment_test.go
- その他、UIを使わない全てのテスト
Package testutil はテスト用のユーティリティ関数を提供する
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
This section is empty.