bevy/crates/bevy_dev_tools/src/ci_testing/config.rs
BD103 b0409f63d5
Refactor ci_testing and separate it from DevToolsPlugin (#13513)
# Objective

- We use
[`ci_testing`](https://dev-docs.bevyengine.org/bevy/dev_tools/ci_testing/index.html)
to specify per-example configuration on when to take a screenshot, when
to exit, etc.
- In the future more features may be added, such as #13512. To support
this growth, `ci_testing` should be easier to read and maintain.

## Solution

- Convert `ci_testing.rs` into the folder `ci_testing`, splitting the
configuration and systems into `ci_testing/config.rs` and
`ci_testing/systems.rs`.
- Convert `setup_app` into the plugin `CiTestingPlugin`. This new plugin
is added to both `DefaultPlugins` and `MinimalPlugins`.
- Remove `DevToolsPlugin` from `MinimalPlugins`, since it was only used
for CI testing.
- Clean up some code, add many comments, and add a few unit tests.

## Testing

The most important part is that this still passes all of the CI
validation checks (merge queue), since that is when it will be used the
most. I don't think I changed any behavior, so it should operate the
same.

You can also test it locally using:

```shell
# Run the breakout example, enabling `bevy_ci_testing` and loading the configuration used in CI.
CI_TESTING_CONFIG=".github/example-run/breakout.ron" cargo r --example breakout -F bevy_ci_testing
```

---

## Changelog

- Added `CiTestingPlugin`, which is split off from `DevToolsPlugin`.
- Removed `DevToolsPlugin` from `MinimalPlugins`.

## Migration Guide

Hi maintainers! I believe `DevToolsPlugin` was added within the same
release as this PR, so I don't think a migration guide is needed.

`DevToolsPlugin` is no longer included in `MinimalPlugins`, so you will
need to remove it manually.

```rust
// Before
App::new()
    .add_plugins(MinimalPlugins)
    .run();

// After
App::new()
    .add_plugins(MinimalPlugins)
    .add_plugins(DevToolsPlugin)
    .run();
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-05-26 22:32:36 +00:00

86 lines
2.6 KiB
Rust

use bevy_ecs::prelude::*;
use serde::Deserialize;
/// A configuration struct for automated CI testing.
///
/// It gets used when the `bevy_ci_testing` feature is enabled to automatically
/// exit a Bevy app when run through the CI. This is needed because otherwise
/// Bevy apps would be stuck in the game loop and wouldn't allow the CI to progress.
#[derive(Deserialize, Resource, PartialEq, Debug)]
pub struct CiTestingConfig {
/// The setup for this test.
#[serde(default)]
pub setup: CiTestingSetup,
/// Events to send, with their associated frame.
#[serde(default)]
pub events: Vec<CiTestingEventOnFrame>,
}
/// Setup for a test.
#[derive(Deserialize, Default, PartialEq, Debug)]
pub struct CiTestingSetup {
/// The amount of time in seconds between frame updates.
///
/// This is set through the [`TimeUpdateStrategy::ManualDuration`] resource.
///
/// [`TimeUpdateStrategy::ManualDuration`]: bevy_time::TimeUpdateStrategy::ManualDuration
pub fixed_frame_time: Option<f32>,
}
/// An event to send at a given frame, used for CI testing.
#[derive(Deserialize, PartialEq, Debug)]
pub struct CiTestingEventOnFrame(pub u32, pub CiTestingEvent);
/// An event to send, used for CI testing.
#[derive(Deserialize, PartialEq, Debug)]
pub enum CiTestingEvent {
/// Takes a screenshot of the entire screen, and saves the results to
/// `screenshot-{current_frame}.png`.
Screenshot,
/// Stops the program by sending [`AppExit::Success`].
///
/// [`AppExit::Success`]: bevy_app::AppExit::Success
AppExit,
/// Sends a [`CiTestingCustomEvent`] using the given [`String`].
Custom(String),
}
/// A custom event that can be configured from a configuration file for CI testing.
#[derive(Event)]
pub struct CiTestingCustomEvent(pub String);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserialize() {
const INPUT: &str = r#"
(
setup: (
fixed_frame_time: Some(0.03),
),
events: [
(100, Custom("Hello, world!")),
(200, Screenshot),
(300, AppExit),
],
)"#;
let expected = CiTestingConfig {
setup: CiTestingSetup {
fixed_frame_time: Some(0.03),
},
events: vec![
CiTestingEventOnFrame(100, CiTestingEvent::Custom("Hello, world!".into())),
CiTestingEventOnFrame(200, CiTestingEvent::Screenshot),
CiTestingEventOnFrame(300, CiTestingEvent::AppExit),
],
};
let config: CiTestingConfig = ron::from_str(INPUT).unwrap();
assert_eq!(config, expected);
}
}