rmv_bevy_testing_tools/
lib.rs

1#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
2
3// TODO: setup tags for different versions of bevy
4
5#[allow(dead_code)]
6mod deprecated {
7    use konst::{iter, result, string};
8    use static_assertions::const_assert_eq;
9    const VERSION: [u32; 3] = iter::collect_const!(u32 =>
10        string::split(env!("CARGO_PKG_VERSION"), "."),
11        map(|s| result::unwrap!(u32::from_str_radix(s, 10))));
12    const MAJOR: u32 = VERSION[0];
13    const MINOR: u32 = VERSION[1];
14    const PATCH: u32 = VERSION[2];
15    const_assert_eq!(MAJOR, 0);
16
17    #[cfg(any(not(feature = "iter_tools"), feature = "iter_tools"))]
18    const_assert_eq!(MINOR, 7);
19    // TODO: remove deprecated feature `iter_tools` before 0.8
20}
21
22#[cfg(feature = "speculoos")]
23pub mod assertions;
24#[cfg(any(all(test, feature = "rstest"), feature = "trait_collect_events"))]
25pub mod events;
26#[cfg(any(test, feature = "rstest"))]
27pub mod fixtures;
28#[allow(unused_imports)] // silence warning about name starting with test_
29pub mod test_app;
30pub mod traits;
31
32#[cfg(feature = "insta")]
33#[macro_export]
34macro_rules! set_snapshot_suffix {
35    ($($expr:expr),*) => {
36        let mut settings = insta::Settings::clone_current();
37        settings.set_snapshot_suffix(format!($($expr,)*));
38        let _guard = settings.bind_to_scope();
39    }
40}
41
42pub mod prelude {
43    #[cfg(feature = "speculoos")]
44    pub use super::assertions::*;
45    #[cfg(feature = "trait_collect_events")]
46    pub use super::events::*;
47    #[cfg(any(test, feature = "rstest"))]
48    pub use super::fixtures::*;
49    #[cfg(feature = "insta")]
50    pub use super::set_snapshot_suffix;
51    pub use super::test_app::*;
52    #[allow(unused_imports)]
53    pub use super::traits::*;
54}
55
56#[doc = include_str!("../Readme.md")]
57#[cfg(doctest)]
58pub struct ReadmeDoctests;
59
60#[cfg(test)]
61#[cfg_attr(coverage_nightly, coverage(off))]
62mod tests {
63    #[allow(unused_imports)]
64    use rstest::rstest;
65
66    #[cfg(feature = "rstest")]
67    use crate::prelude::{test_app, TestApp};
68
69    #[cfg(feature = "rstest")]
70    #[rstest]
71    fn with_rstest_fixtures(#[from(test_app)] mut app: TestApp) {
72        // if it compiles, it's fine
73        if skip_feature_test_body() {
74            return;
75        }
76
77        use bevy_app::AppExit;
78
79        use crate::prelude::{CollectEvents, SendEvents};
80
81        app.collect_events::<AppExit>()
82            .send_event_default::<AppExit>();
83    }
84
85    #[cfg(feature = "insta")]
86    #[rstest]
87    fn can_access_insta_macro() {
88        // if it compiles, it's fine
89        if skip_feature_test_body() {
90            return;
91        }
92
93        set_snapshot_suffix!("works");
94    }
95
96    #[cfg(feature = "speculoos")]
97    #[rstest]
98    fn can_access_assertions() {
99        // if it compiles, it's fine
100        if skip_feature_test_body() {
101            return;
102        }
103
104        use speculoos::assert_that;
105
106        use crate::prelude::IsContainedIn;
107
108        let items = vec![1, 2, 3];
109        assert_that!(1).is_contained_in(&items);
110    }
111
112    #[cfg(feature = "itertools")]
113    #[rstest]
114    fn can_access_query_vec() {
115        // if it compiles, it's fine
116        if skip_feature_test_body() {
117            return;
118        }
119
120        use bevy_app::App;
121        use bevy_ecs::entity::Entity;
122
123        use crate::{test_app::TestApp, traits::ImmediateQuery};
124
125        TestApp(App::new()).query_vec::<Entity>();
126    }
127
128    #[allow(dead_code)]
129    fn skip_feature_test_body() -> bool {
130        // basically return true always but don't let the compiler know
131        // so it checks code that we don't want to run anyway
132        std::env::var("_SKIP_FEATURE_TESTS_")
133            .map(|s| matches!(s.as_str(), "true" | "1"))
134            .unwrap_or(true)
135    }
136}