Make Time::update_with_instant public for use in tests (#4469)
# Objective To test systems that implement frame rate-independent update logic, one needs to be able to mock `Time`. By mocking time, it's possible to write tests that confirm systems are frame rate-independent. This is a follow-up PR to #2549 by @ostwilkens and based on his work. ## Solution To mock `Time`, one needs to be able to manually update the Time resource with an `Instant` defined by the developer. This can be achieved by making the existing `Time::update_with_instant` method public for use in tests. ## Changelog - Make `Time::update_with_instant` public - Add doc to `Time::update_with_instant` clarifying that the method should not be called outside of tests. - Add doc test to `Time` demonstrating how to use `update_with_instant` in tests. Co-authored-by: Martin Dickopp <martin@zero-based.org>
This commit is contained in:
parent
1cd17e903f
commit
93cee3b3c9
@ -29,11 +29,66 @@ impl Default for Time {
|
|||||||
|
|
||||||
impl Time {
|
impl Time {
|
||||||
/// Updates the internal time measurements.
|
/// Updates the internal time measurements.
|
||||||
|
///
|
||||||
|
/// Calling this method on the [`Time`] resource as part of your app will most likely result in
|
||||||
|
/// inaccurate timekeeping, as the resource is ordinarily managed by the
|
||||||
|
/// [`CorePlugin`](crate::CorePlugin).
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
self.update_with_instant(Instant::now());
|
self.update_with_instant(Instant::now());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn update_with_instant(&mut self, instant: Instant) {
|
/// Update time with a specified [`Instant`]
|
||||||
|
///
|
||||||
|
/// This method is provided for use in tests. Calling this method on the [`Time`] resource as
|
||||||
|
/// part of your app will most likely result in inaccurate timekeeping, as the resource is
|
||||||
|
/// ordinarily managed by the [`CorePlugin`](crate::CorePlugin).
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use bevy_core::prelude::*;
|
||||||
|
/// # use bevy_ecs::prelude::*;
|
||||||
|
/// # use bevy_utils::Duration;
|
||||||
|
/// # fn main () {
|
||||||
|
/// # test_health_system();
|
||||||
|
/// # }
|
||||||
|
/// struct Health {
|
||||||
|
/// // Health value between 0.0 and 1.0
|
||||||
|
/// health_value: f32,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn health_system(time: Res<Time>, mut health: ResMut<Health>) {
|
||||||
|
/// // Increase health value by 0.1 per second, independent of frame rate,
|
||||||
|
/// // but not beyond 1.0
|
||||||
|
/// health.health_value = (health.health_value + 0.1 * time.delta_seconds()).min(1.0);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // Mock time in tests
|
||||||
|
/// fn test_health_system() {
|
||||||
|
/// let mut world = World::default();
|
||||||
|
/// let mut time = Time::default();
|
||||||
|
/// time.update();
|
||||||
|
/// world.insert_resource(time);
|
||||||
|
/// world.insert_resource(Health { health_value: 0.2 });
|
||||||
|
///
|
||||||
|
/// let mut update_stage = SystemStage::single_threaded();
|
||||||
|
/// update_stage.add_system(health_system);
|
||||||
|
///
|
||||||
|
/// // Simulate that 30 ms have passed
|
||||||
|
/// let mut time = world.resource_mut::<Time>();
|
||||||
|
/// let last_update = time.last_update().unwrap();
|
||||||
|
/// time.update_with_instant(last_update + Duration::from_millis(30));
|
||||||
|
///
|
||||||
|
/// // Run system
|
||||||
|
/// update_stage.run(&mut world);
|
||||||
|
///
|
||||||
|
/// // Check that 0.003 has been added to the health value
|
||||||
|
/// let expected_health_value = 0.2 + 0.1 * 0.03;
|
||||||
|
/// let actual_health_value = world.resource::<Health>().health_value;
|
||||||
|
/// assert_eq!(expected_health_value, actual_health_value);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn update_with_instant(&mut self, instant: Instant) {
|
||||||
if let Some(last_update) = self.last_update {
|
if let Some(last_update) = self.last_update {
|
||||||
self.delta = instant - last_update;
|
self.delta = instant - last_update;
|
||||||
self.delta_seconds_f64 = self.delta.as_secs_f64();
|
self.delta_seconds_f64 = self.delta.as_secs_f64();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user