Expand description
§Testable Model
Tests are modeled within a heirarchy:
Module
Group
Test
The Module
model represents the Rust module that is being tested.
The Group
model is an optional model that allows further sub-grouping of testing attributes and behaviors.
The Test
model represents the actual test or benchmark that is being performed.
A Module
is categorized between three use-cases:
- Unit tests
- Integration tests
- Benchmarks
Each testable model uses a builder pattern for construction.
Each testable holds a one-way reference to its parent in the heirarchy.
Group
and Test
models may inherit or override certain attributes from their parents in this heirarchy.
Module
and Group
models are typically created with a static builder pattern. Teardown is then handled by a process exit hook, as destructors are unavailable at the static scope.
Test
models are typically constructed and dropped with the lifespan of the test.
Each model object is represented structurally within the project using a string namepath
, based on the Rust module path scheme.
Where resources are represented externally, models are represented with the same heirarchy, described by the namepath
.
In a filesystem, an example of this might be:
my-model / my-group / my-test
§Namepathing
This crate uses a concept of a namepath
which is an extended form of the Rust module pathing scheme.
Preceding the module path, a /
path separator can be used to delimit a file-system-like heirarchy. This may represent some form of context for the project.
Following the module path, a .
dot notation character can be used to delimit anything that can’t be reached by the Rust module pathing scheme, real or conceptual.
Examples:
org-name/team-name/crate_name::module_name
crate_name::module_name::type_name.concept_name
§Project file structure
§File fixture directories
File fixtures for testing purposes may be stored (by default) relative to the crate’s project directory in ./testing/fixtures
.
The file structure within the base fixture directory reflects the test model’s use-case and heirarchy:
./ testing / fixtures /
[ unit | integration | benchmark ] /
{ module } /
{ group } /
{ test }
The default fixture path f/or a model mirrors its heirarchy and namepath.
It is an error to build a test model with a fixture path that does not exist.
Fixture dirs must be explicitly configured during construction:
using_fixture_dir()
uses a default calculated path.inherit_fixture_dir()
inherits the same path as its parent in the model heirarchy.import_fixture_dir(Namepath)
imports a fixture directory from another testable model.
The aforementioned builder methods will verify that the configured path exists before construction.
After construction, a testable’s fixture_dir() can then be used retrieve the configured Path
. Any imported fixture
directories can be retrieved with imported_fixture_dir().
§Temporary file directories
Temporary directories are created upon construction if requested in the builder. They are automatically deleted upon teardown.
Temporary directories follow the same parent heirarchy as the rest of this crate. The parent Module
or Group
will have its own randomly generated
directory, within which each child component will have a subdirectory.
The base path for temporary directories can be re-configured away from the operating system’s default, if neededed.
Temporary directories must be explicitly configured during construction:
using_temp_dir()
uses a default calculated path.inherit_temp_dir()
inherits the same path as its parent in the model heirarchy.
After construction, a model’s temp_dir()
can then be used retrieve the pre-created Path
.
§Example Usage
fn main() {}
#[cfg(test)]
mod tests {
use std::fs;
use asmov_testing::{self as testing, prelude::*};
static TESTING: testing::StaticModule = testing::module(|| {
testing::integration(module_path!())
.using_temp_dir()
.using_fixture_dir()
.setup(|module| {
let tmp_file = module.temp_dir()
.join("hello.txt");
fs::write(&tmp_file,
"Hello, Temp").unwrap();
})
.teardown_static(teardown)
.build()
});
extern fn teardown() {
println!("Farewell, sweet test run");
}
#[named]
#[test]
fn test_things() {
let test = TESTING.test(function_name!())
.using_fixture_dir()
.inherit_temp_dir()
.build();
let temp_file = test.temp_dir()
.join("hello.txt");
let temp_text = fs::read_to_string(temp_file)
.unwrap();
assert_eq!("Hello, Temp", temp_text);
let fixture_file = test.fixture_dir()
.join("sample.txt");
let fixture_text = fs::read_to_string(fixture_file)
.unwrap();
assert_eq!("Hello, Fixture", fixture_text);
}
}
Re-exports§
pub use module::Module;
pub use module::ModuleBuilder;
pub use group::Group;
pub use group::GroupBuilder;
pub use test::Test;
pub use test::TestBuilder;
pub use namepath::Namepath;
pub use namepath::NamepathTrait;
Modules§
Enums§
Traits§
- Testable
- Common to all testable models; Module, Group, Test).
- Testable
Builder
Functions§
Type Aliases§
- Static
Group - Static
Module - A static reference to a Module instance.