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}