8 releases (breaking)
| 0.15.3 | Aug 23, 2020 |
|---|---|
| 0.6.1 | Aug 17, 2020 |
| 0.6.0 | Mar 23, 2020 |
| 0.4.0 | Sep 26, 2019 |
| 0.1.0 | Feb 18, 2019 |
#30 in #amethyst
72 downloads per month
1MB
3K
SLoC
Test harness to support testing of Amethyst types, including:
BundleStateSystem- Resource loading.
- Arbitrary types that
Systems use during processing.
The test harness minimizes boilerplate code to set up an Amethyst Application with common
bundles, and can take in logic that is normally masked behind a number of layers through a thin
interface.
Usage
The following shows a simple example of testing a State. More examples are in the
Examples section.
#
#
#
#
#
#
#
#
// #[test]
fn loading_state_adds_load_resource() {
assert!(
AmethystApplication::blank()
.with_state(|| LoadingState::new())
.with_assertion(|world| {
world.read_resource::<LoadResource>();
})
.run()
.is_ok()
);
}
#
The Amethyst application is initialized with one of the following functions, each providing a different set of bundles:
use amethyst_test::prelude::*;
#[test]
fn test_name() {
// Start with no bundles
AmethystApplication::blank();
// Start with the following bundles:
//
// * `TransformBundle`
// * `InputBundle`
// * `UiBundle`
//
// The type parameters here are the Axis and Action types for the
// `InputBundle` and `UiBundle`.
use amethyst::input::StringBindings;
AmethystApplication::ui_base::<StringBindings>();
// If you need types from the rendering bundle, make sure you have
// the `"test-support"` feature enabled:
//
// ```toml
// # Cargo.toml
// amethyst = { version = "..", features = ["test-support"] }
// ```
//
// Then you can include the `RenderEmptyBundle`:
use amethyst::renderer::{types::DefaultBackend, RenderEmptyBundle};
AmethystApplication::blank()
.with_bundle(RenderEmptyBundle::<DefaultBackend>::new());
}
Next, attach the logic you wish to test using the various .with_*(..) methods:
#
#
#
#[test]
fn test_name() {
let visibility = false; // Whether the window should be shown
AmethystApplication::render_base::<String, String, _>("test_name", visibility)
.with_bundle(MyBundle::new()) // Registers a bundle.
.with_bundle_fn(|| MyNonSendBundle::new()) // Registers a `!Send` bundle.
.with_resource(MyResource::new()) // Adds a resource to the world.
.with_system(MySystem, "my_sys", &[]) // Registers a system with the main
// dispatcher.
// These are run in the order they are invoked.
// You may invoke them multiple times.
.with_setup(|world| { /* do something */ })
.with_state(|| MyState::new())
.with_effect(|world| { /* do something */ })
.with_assertion(|world| { /* do something */ })
// ...
}
Finally, call .run() to run the application. This returns amethyst::Result<()>, so you can
wrap it in an assert!(..);:
#[test]
fn test_name() {
let visibility = false; // Whether the window should be shown
assert!(
AmethystApplication::render_base("test_name", visibility)
// ...
.run()
.is_ok()
);
}
Examples
Testing a bundle:
#
#
#
#
#
#
// #[test]
fn bundle_registers_system_with_resource() {
assert!(
AmethystApplication::blank()
.with_bundle(MyBundle)
.with_assertion(|world| { world.read_resource::<ApplicationResource>(); })
.run()
.is_ok()
);
}
#
Testing a system:
#
#
#
#
#
#
// #[test]
fn system_increases_component_value_by_one() {
assert!(
AmethystApplication::blank()
.with_system(MySystem, "my_system", &[])
.with_effect(|world| {
let entity = world.create_entity().with(MyComponent(0)).build();
world.insert(EffectReturn(entity));
})
.with_assertion(|world| {
let entity = world.read_resource::<EffectReturn<Entity>>().0.clone();
let my_component_storage = world.read_storage::<MyComponent>();
let my_component = my_component_storage
.get(entity)
.expect("Entity should have a `MyComponent` component.");
// If the system ran, the value in the `MyComponent` should be 1.
assert_eq!(1, my_component.0);
})
.run()
.is_ok()
);
}
#
Testing a System in a custom dispatcher. This is useful when your system must run after some setup has been done:
#
#
#
#
#
// #[test]
fn system_increases_resource_value_by_one() {
assert!(
AmethystApplication::blank()
.with_setup(|world| {
world.insert(MyResource(0));
})
.with_system_single(MySystem, "my_system", &[])
.with_assertion(|world| {
let my_resource = world.read_resource::<MyResource>();
// If the system ran, the value in the `MyResource` should be 1.
assert_eq!(1, my_resource.0);
})
.run()
.is_ok()
);
}
#
Dependencies
~30–51MB
~1M SLoC