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 {
 | 
			
		||||
    /// 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) {
 | 
			
		||||
        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 {
 | 
			
		||||
            self.delta = instant - last_update;
 | 
			
		||||
            self.delta_seconds_f64 = self.delta.as_secs_f64();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user