bevy_dev_tools/ci_testing/
config.rs

1use bevy_ecs::prelude::*;
2use serde::Deserialize;
3
4/// A configuration struct for automated CI testing.
5///
6/// It gets used when the `bevy_ci_testing` feature is enabled to automatically
7/// exit a Bevy app when run through the CI. This is needed because otherwise
8/// Bevy apps would be stuck in the game loop and wouldn't allow the CI to progress.
9#[derive(Deserialize, Resource, PartialEq, Debug, Default)]
10pub struct CiTestingConfig {
11    /// The setup for this test.
12    #[serde(default)]
13    pub setup: CiTestingSetup,
14    /// Events to send, with their associated frame.
15    #[serde(default)]
16    pub events: Vec<CiTestingEventOnFrame>,
17}
18
19/// Setup for a test.
20#[derive(Deserialize, Default, PartialEq, Debug)]
21pub struct CiTestingSetup {
22    /// The amount of time in seconds between frame updates.
23    ///
24    /// This is set through the [`TimeUpdateStrategy::ManualDuration`] resource.
25    ///
26    /// [`TimeUpdateStrategy::ManualDuration`]: bevy_time::TimeUpdateStrategy::ManualDuration
27    pub fixed_frame_time: Option<f32>,
28}
29
30/// An event to send at a given frame, used for CI testing.
31#[derive(Deserialize, PartialEq, Debug)]
32pub struct CiTestingEventOnFrame(pub u32, pub CiTestingEvent);
33
34/// An event to send, used for CI testing.
35#[derive(Deserialize, PartialEq, Debug)]
36pub enum CiTestingEvent {
37    /// Takes a screenshot of the entire screen, and saves the results to
38    /// `screenshot-{current_frame}.png`.
39    Screenshot,
40    /// Takes a screenshot of the entire screen, and saves the results to
41    /// `screenshot-{name}.png`.
42    NamedScreenshot(String),
43    /// Stops the program by sending [`AppExit::Success`].
44    ///
45    /// [`AppExit::Success`]: bevy_app::AppExit::Success
46    AppExit,
47    /// Sends a [`CiTestingCustomEvent`] using the given [`String`].
48    Custom(String),
49}
50
51/// A custom event that can be configured from a configuration file for CI testing.
52#[derive(Event)]
53pub struct CiTestingCustomEvent(pub String);
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn deserialize() {
61        const INPUT: &str = r#"
62(
63    setup: (
64        fixed_frame_time: Some(0.03),
65    ),
66    events: [
67        (100, Custom("Hello, world!")),
68        (200, Screenshot),
69        (300, AppExit),
70    ],
71)"#;
72
73        let expected = CiTestingConfig {
74            setup: CiTestingSetup {
75                fixed_frame_time: Some(0.03),
76            },
77            events: vec![
78                CiTestingEventOnFrame(100, CiTestingEvent::Custom("Hello, world!".into())),
79                CiTestingEventOnFrame(200, CiTestingEvent::Screenshot),
80                CiTestingEventOnFrame(300, CiTestingEvent::AppExit),
81            ],
82        };
83
84        let config: CiTestingConfig = ron::from_str(INPUT).unwrap();
85
86        assert_eq!(config, expected);
87    }
88}