-
Notifications
You must be signed in to change notification settings - Fork 124
Description
Context
Awaiting provides wait_seconds, wait_frames and wait_for_signal, which are great.
A pattern that often comes up in my tests is to wait for a particular condition to be true.
For example
- repeatedly hit an enemy until it is dead
- hit an enemy then wait until its HP regenerates to 100%
- accelerate something until it has velocity X
In all cases, if a certain timeout is reached, I want the test to fail.
Ideas
Generic wait_until(predicate_func, timeout)
predicate_func
: Callable returning a boolean. Returns true when the success condition is reachedmax_wait
: same aswait_for_signal
. Timeout after which we stop blocking the test
Fail on max_time reached
I think wait_for_signal
and wait_until
should fail the test when the max_time is reached, just like a failed assertion.
is_object_freed predicate
GUT could provide a predicate function returning true when an object has been freed.
Other predicates
Many conditions used in assertions would be great as conditions to wait_until
if they were converted into predicate functions (excuse the bad names hehe)
await wait_until(has(vegetables_array, 'potato'))
await wait_until(is_signal_connected(signaler, connector, 'the_signal'))
await wait_until(has_call_count(doubled, 'set_value', 1, [4]))
Usage
func test_when_sword_collides_with_wall_then_it_is_stopped() -> void:
wall = add_child_autofree(WallScene.instantiate())
wall.set_position(Vector2.RIGHT * 100)
sword = add_child_autofree(SwordScene.instantiate())
sword.set_linear_velocity(Vector2.RIGHT * 300)
var is_immobile := func() -> bool: return sword.get_linear_velocity().is_zero_approx()
await wait_until(is_immobile, 5)
Bonus idea: wait until freed
Here's a PR I made for wait_until_freed. Another way to wait until something is freed could be done with GUT just providing a predicate to check if something is freed.
func test_when_enemy_collides_with_sword_then_it_dies() -> void:
enemy= add_child_autofree(EnemyScene.instantiate())
enemy.set_position(Vector2.RIGHT * 100)
sword.set_linear_velocity(Vector2.RIGHT * 300)
sword = add_child_autofree(SwordScene.instantiate())
var is_dead := func() -> bool: return is_object_freed(enemy) # is_object_freed being a new predicate provided by GUT
await wait_until(is_dead , 5)