Godot4 GUT によるユニットテストの前後に行う共通処理の定義

無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、GD スクリプトで作成した機能のユニットテストをする際に便利な無料アセット GUT で、ユニットテストを行う前後に呼び出すイベント関数 before_each(), after_each() を用いて、テストの共通処理を定義して単体テスト実行します。
※ 3.x 系で 4.x 系が用意されていて 4.2 と書かれているので公式なサポートではないかもしれませんが 4.3 でも動作しました。

Godot4 ユニットテスト用アセットGUTのGodotAssetLibraryのページの一部20241124

※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※ GUT アセットのバージョンは 9.3.0 です。
※スクリプトは自己責任でご使用ください。

前回の記事

前回は、無料アセット GUT で、指定したフォルダ内に配置した公式のサンプルスクリプトユニットテストを実行する手順を紹介しました。

テストはフォルダ・ファイル・関数単位で行える

前回の記事では、 GUT タブの右側の Include Subdirs リスト指定したフォルダ内全てのテスト用スクリプトファイル全てのテスト関数を、左上の Run All ボタンを押してテストしました。

そのあとに GUT タブの左上の Run All ボタンの右側をみると、現在開いているテスト用スクリプトの名前が書かれたボタンが追加され、さらにその右側には現在カーソルを置いている位置のテスト関数の名前が書かれたボタンが追加されていました。

ファイル名・関数名の書かれたボタンを押すと、Run All ボタンを押したときのようにフォルダ内の全てではなく、1つのファイルに書かれた全てのテストや、選択しているテスト関数だけテストすることができます。

Godot4 GUT ユニットテストで Run All の後は、選択しているスクリプトや関数単位でテストを実行できます.

ユニットテストの前後に共通の処理を定義

以下のテスト用スクリプトでは、3つの各テスト関数最初の4行全く同じ処理を行っています。
また、return の前の1行の処理も同じです。
※処理の説明についてはスクリプト内のコメントを参照してください。

具体的には、ハイライト表示されている、6-9, 21-22, 27-30, 42-43, 48-51, 63-64行目が各テスト関数の共通の処理です。

extends GutTest
## SakuraCrowdUtil クラスで定義されたユーティリティ関数のテストを行います。

## SakuraCrowdUtil.to_cell_pos_ceil 関数の境界値(境界値 ± 0)の単体テストです。
func test_to_cell_pos_ceil_1():
	# テスト対象関数の TileMapLayer 型の引数の作成
	var tilemap_layer = TileMapLayer.new()	# オブジェクトを生成します。
	tilemap_layer.tile_set = TileSet.new()	# タイルセットリソースを新規作成して割り当てます。
	tilemap_layer.tile_set.tile_size = Vector2i(16, 16)	# タイルセットのタイル(セル)のサイズを設定します。
	
	# テスト対象関数の Vector2 型の引数の作成
	var global_pos = Vector2(16, 0)	# タイルサイズの境界値 ± 0 の値を設定
	
	# 期待する値を指定します。
	var correct = Vector2i(1, 0)
	# テスト対象関数を呼び出して結果を得ます。
	var result: Vector2i = SakuraCrowdUtil.to_cell_pos_ceil(global_pos, tilemap_layer)
	# GUT の関数で、結果の値と期待する値が同じかどうかをテストします。
	assert_eq(result, correct)

	# 動的に生成した TileMapLayer オブジェクトを破棄します。
	tilemap_layer.free()
	return

## SakuraCrowdUtil.to_cell_pos_ceil 関数の境界値(境界値 - 1)の単体テストです。
func test_to_cell_pos_ceil_2():
	# テスト対象関数の TileMapLayer 型の引数の作成
	var tilemap_layer = TileMapLayer.new()	# オブジェクトを生成します。
	tilemap_layer.tile_set = TileSet.new()	# タイルセットリソースを新規作成して割り当てます。
	tilemap_layer.tile_set.tile_size = Vector2i(16, 16)	# タイルセットのタイル(セル)のサイズを設定します。
	
	# テスト対象関数の Vector2 型の引数の作成
	var global_pos = Vector2(15, -1)	# タイルサイズの境界値 - 1 の値を設定
	
	# 期待する値を指定します。
	var correct = Vector2i(1, 0)
	# テスト対象関数を呼び出して結果を得ます。
	var result: Vector2i = SakuraCrowdUtil.to_cell_pos_ceil(global_pos, tilemap_layer)
	# GUT の関数で、結果の値と期待する値が同じかどうかをテストします。
	assert_eq(result, correct)

	# 動的に生成した TileMapLayer オブジェクトを破棄します。
	tilemap_layer.free()
	return

## SakuraCrowdUtil.to_cell_pos_ceil 関数の境界値(境界値 + 1)の単体テストです。
func test_to_cell_pos_ceil_3():
	# テスト対象関数の TileMapLayer 型の引数の作成
	var tilemap_layer = TileMapLayer.new()	# オブジェクトを生成します。
	tilemap_layer.tile_set = TileSet.new()	# タイルセットリソースを新規作成して割り当てます。
	tilemap_layer.tile_set.tile_size = Vector2i(16, 16)	# タイルセットのタイル(セル)のサイズを設定します。
	
	# テスト対象関数の Vector2 型の引数の作成
	var global_pos = Vector2(17, 1)	# タイルサイズの境界値 + 1 の値を設定
	
	# 期待する値を指定します。
	var correct = Vector2i(2, 1)
	# テスト対象関数を呼び出して結果を得ます。
	var result: Vector2i = SakuraCrowdUtil.to_cell_pos_ceil(global_pos, tilemap_layer)
	# GUT の関数で、結果の値と期待する値が同じかどうかをテストします。
	assert_eq(result, correct)

	# 動的に生成した TileMapLayer オブジェクトを破棄します。
	tilemap_layer.free()
	return

このように、ユニットテストの準備と後片付けといった共通の処理は、 GUT が用意したイベント関数 before_each(), after_each() に定義できます。

例では 4 ~ 19 行目に before_each(), after_each() イベント関数の処理を定義して、その内部で用いる変数は 5 行目に定義しています。

これにより、このファイルのユニットテストを行うと以下のように、各テスト関数を呼び出す前後に before_each() と after_each() 関数が実行され、各テスト関数の共通の準備と後片付けの処理1度定義するだけで実装できました。

  before_each() → test_to_cell_pos_ceil_1() → after_each()
→ before_each() → test_to_cell_pos_ceil_2() → after_each()
→ before_each() → test_to_cell_pos_ceil_3() → after_each()

extends GutTest
## SakuraCrowdUtil クラスで定義されたユーティリティ関数のテストを行います。

## TileMapLayer 型オブジェクトを引数とする複数のテストケースで共通して用いる変数です。
var tilemap_layer = null

## テストケースごとにテスト実行前に呼び出される GUT のイベント関数です。テスト前の共通の処理を書きます。
func before_each():
	# テスト対象関数の TileMapLayer 型の引数の作成
	tilemap_layer = TileMapLayer.new()	# オブジェクトを生成します。
	tilemap_layer.tile_set = TileSet.new()	# タイルセットリソースを新規作成して割り当てます。
	tilemap_layer.tile_set.tile_size = Vector2i(16, 16)	# タイルセットのタイル(セル)のサイズを設定します。
	return

## テストケースごとにテスト実行後に呼び出される GUT のイベント関数です。テスト後の共通の処理を書きます。
func after_each():
	# 動的に生成した TileMapLayer オブジェクトを破棄します。
	tilemap_layer.free()
	return


## SakuraCrowdUtil.to_cell_pos_ceil 関数の境界値(境界値 ± 0)の単体テストです。
func test_to_cell_pos_ceil_1():
	# テスト対象関数の Vector2 型の引数の作成
	var global_pos = Vector2(16, 0)	# タイルサイズの境界値 ± 0 の値を設定
	
	# 期待する値を指定します。
	var correct = Vector2i(1, 0)
	# テスト対象関数を呼び出して結果を得ます。
	var result: Vector2i = SakuraCrowdUtil.to_cell_pos_ceil(global_pos, tilemap_layer)
	# GUT の関数で、結果の値と期待する値が同じかどうかをテストします。
	assert_eq(result, correct)

	return

## SakuraCrowdUtil.to_cell_pos_ceil 関数の境界値(境界値 - 1)の単体テストです。
func test_to_cell_pos_ceil_2():	
	# テスト対象関数の Vector2 型の引数の作成
	var global_pos = Vector2(15, -1)	# タイルサイズの境界値 - 1 の値を設定
	
	# 期待する値を指定します。
	var correct = Vector2i(1, 0)
	# テスト対象関数を呼び出して結果を得ます。
	var result: Vector2i = SakuraCrowdUtil.to_cell_pos_ceil(global_pos, tilemap_layer)
	# GUT の関数で、結果の値と期待する値が同じかどうかをテストします。
	assert_eq(result, correct)

	return

## SakuraCrowdUtil.to_cell_pos_ceil 関数の境界値(境界値 + 1)の単体テストです。
func test_to_cell_pos_ceil_3():
	# テスト対象関数の Vector2 型の引数の作成
	var global_pos = Vector2(17, 1)	# タイルサイズの境界値 + 1 の値を設定
	
	# 期待する値を指定します。
	var correct = Vector2i(2, 1)
	# テスト対象関数を呼び出して結果を得ます。
	var result: Vector2i = SakuraCrowdUtil.to_cell_pos_ceil(global_pos, tilemap_layer)
	# GUT の関数で、結果の値と期待する値が同じかどうかをテストします。
	assert_eq(result, correct)

	return

テストの実行

下パネル GUT タブRun All ボタンの右側にある現在開いているテスト用スクリプトファイルの名前クリックすると、そのファイルの各テスト関数が正常に実行されました。

Godot4 GUT ユニットテストで自作のテスト関数を実行して3つ全て合格になった際のGUT下パネル.

実行ウィンドウの 2 ~ 4 行目に表示された関数名から、3つのテスト関数が実行されたことが確認できます。

Godot4 GUT ユニットテストで自作のテスト関数を実行して3つ全て合格になった際の実行ウィンドウ.

まとめ

今回は、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、GD スクリプトで作成した機能のユニットテストをする際に便利な無料アセット GUT で、ユニットテストを行う前後に呼び出すイベント関数 before_each(), after_each() を用いて、テストの共通処理を定義して単体テスト実行しました。

参照サイト Thank You!

記事一覧 → Compota-Soft-Press

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました