pub struct TestId {
pub runner: Runner,
pub name: String,
}Expand description
The stable identity of a test: the runner that owns it and the name that runner knows it by.
Derived from the path a claim already names, which is what makes the migration from
test: <path> deterministic and empty of data entry. test/cases/84_x.sh is the case
test/run.sh calls 84_x; apps/majordomus-cli/tests/why.rs is the binary cargo test --test why runs. Both spellings already exist in the repository; this only names the
join.
use majordomus_cli::evidence::{Runner, TestId};
let id = TestId::of("test/cases/07_scope.sh").unwrap();
assert_eq!(id, TestId { runner: Runner::Suite, name: "07_scope".into() });
// the identity and the path are two spellings of one thing, so the derivation is
// reversible and no claim in `docs/CLAIMS.yaml` has to be rewritten to carry an id
assert_eq!(TestId::of(&id.source()).unwrap(), id);§Example
use majordomus_cli::evidence::TestId;
let t = TestId::of("apps/majordomus-cli/tests/product.rs").unwrap();
assert_eq!(t.as_string(), "crate:product");
assert_eq!(t.reproduce(), "cargo test --test product");
assert!(TestId::of("lib/nothing.sh").is_none());Fields§
§runner: RunnerWhich runner owns it.
name: StringThe name that runner knows it by: a case’s file stem, a test binary’s file stem.
Implementations§
Source§impl TestId
impl TestId
Sourcepub fn as_string(&self) -> String
pub fn as_string(&self) -> String
The canonical string form: suite:84_distribution_model, crate:why.
This is the ledger’s key. Every execution is stored and looked up under it, which is why the runner is part of it rather than context a reader is expected to carry.
use majordomus_cli::evidence::TestId;
assert_eq!(
TestId::of("test/cases/07_scope.sh").unwrap().as_string(),
"suite:07_scope"
);
assert_eq!(
TestId::of("apps/majordomus-cli/tests/why.rs").unwrap().as_string(),
"crate:why"
);Sourcepub fn of(path: &str) -> Option<TestId>
pub fn of(path: &str) -> Option<TestId>
The test a path names, when a runner in this repository produces it.
None is an answer, not a failure: a claim may name a file no runner drives (a
template, a fixture, a document), and the report says so rather than counting it.
use majordomus_cli::evidence::{Runner, TestId};
assert_eq!(
TestId::of("test/cases/84_distribution_model.sh").unwrap().as_string(),
"suite:84_distribution_model"
);
assert_eq!(TestId::of("apps/majordomus-cli/tests/why.rs").unwrap().runner, Runner::Crate);
assert!(TestId::of("share/install/install.sh.in").is_none());
assert!(TestId::of("-").is_none());Sourcepub fn named(runner: Runner, name: &str) -> Option<TestId>
pub fn named(runner: Runner, name: &str) -> Option<TestId>
A test named directly, validated by the same rule TestId::of applies to a path.
The identity form (suite:84_x) and the path form (test/cases/84_x.sh) name the
same thing, so they must agree about what a name may be. They did not: the path
form rejected a name containing a separator and the identity form did not, so
suite:../../x produced the source test/cases/../../x.sh. Two parsers for one
grammar is the one-way check this repository keeps finding; this is the grammar,
and both forms go through it.
use majordomus_cli::evidence::{Runner, TestId};
assert_eq!(TestId::named(Runner::Suite, "84_x").unwrap().as_string(), "suite:84_x");
assert!(TestId::named(Runner::Suite, "../../x").is_none(), "a name is not a path");
assert!(TestId::named(Runner::Suite, "").is_none());
assert!(TestId::named(Runner::Crate, "a/b").is_none());
assert!(TestId::named(Runner::Suite, ".hidden").is_none());Sourcepub fn source(&self) -> String
pub fn source(&self) -> String
The repository-relative path of the test’s own source: the file that is hashed into
Execution::digest, and one of the paths a claim’s staleness is measured over.
use majordomus_cli::evidence::TestId;
let id = TestId::of("apps/majordomus-cli/tests/why.rs").unwrap();
assert_eq!(id.source(), "apps/majordomus-cli/tests/why.rs");
// a case's source is the file the runner executes, not the runner
assert_eq!(
TestId::of("test/cases/07_scope.sh").unwrap().source(),
"test/cases/07_scope.sh"
);Sourcepub fn reproduce(&self) -> String
pub fn reproduce(&self) -> String
The exact command that runs this one test, for a reader who wants the proof again rather than the claim that it exists.
One test, not the suite: a finding a reader can settle in seconds is settled, and one that costs a full run is argued about instead.
use majordomus_cli::evidence::TestId;
assert_eq!(
TestId::of("test/cases/84_distribution_model.sh").unwrap().reproduce(),
"bash test/run.sh 84_distribution_model"
);
assert_eq!(
TestId::of("apps/majordomus-cli/tests/why.rs").unwrap().reproduce(),
"cargo test --test why"
);Trait Implementations§
Source§impl<'de> Deserialize<'de> for TestId
impl<'de> Deserialize<'de> for TestId
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for TestId
Source§impl JsonSchema for TestId
impl JsonSchema for TestId
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreSource§impl Ord for TestId
impl Ord for TestId
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl PartialOrd for TestId
impl PartialOrd for TestId
impl StructuralPartialEq for TestId
Auto Trait Implementations§
impl Freeze for TestId
impl RefUnwindSafe for TestId
impl Send for TestId
impl Sync for TestId
impl Unpin for TestId
impl UnsafeUnpin for TestId
impl UnwindSafe for TestId
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.