Skip to content

Commit

Permalink
Merge pull request #283 from epage/harness
Browse files Browse the repository at this point in the history
fix(harness)!: Future proof the API
  • Loading branch information
epage authored Apr 21, 2024
2 parents 5210887 + 94e87ba commit 2bd880a
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 16 deletions.
66 changes: 52 additions & 14 deletions crates/snapbox/src/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@
//!
//! fn setup(input_path: std::path::PathBuf) -> snapbox::harness::Case {
//! let name = input_path.file_name().unwrap().to_str().unwrap().to_owned();
//! let expected = input_path.with_extension("out");
//! let expected = snapbox::Data::read_from(&input_path.with_extension("out"), None);
//! snapbox::harness::Case {
//! name,
//! fixture: input_path,
//! expected,
//! format: None,
//! }
//! }
//!
Expand All @@ -36,28 +35,30 @@
//! }
//! ```
use crate::data::DataFormat;
use crate::Action;
use crate::Data;

use libtest_mimic::Trial;

/// [`Harness`] for discovering test inputs and asserting against snapshot files
///
/// See [`harness`][crate::harness] for more details
pub struct Harness<S, T> {
pub struct Harness<S, T, I, E> {
root: std::path::PathBuf,
overrides: Option<ignore::overrides::Override>,
setup: S,
test: T,
config: crate::Assert,
test_output: std::marker::PhantomData<I>,
test_error: std::marker::PhantomData<E>,
}

impl<S, T, I, E> Harness<S, T>
impl<S, T, I, E> Harness<S, T, I, E>
where
S: Setup + Send + Sync + 'static,
T: Test<I, E> + Clone + Send + Sync + 'static,
I: std::fmt::Display,
E: std::fmt::Display,
S: Fn(std::path::PathBuf) -> Case + Send + Sync + 'static,
T: Fn(&std::path::Path) -> Result<I, E> + Send + Sync + 'static + Clone,
{
/// Specify where the test scenarios
///
Expand All @@ -72,6 +73,8 @@ where
setup,
test,
config: crate::Assert::new().action_env(crate::DEFAULT_ACTION_ENV),
test_output: Default::default(),
test_error: Default::default(),
}
}

Expand Down Expand Up @@ -127,15 +130,18 @@ where
let tests: Vec<_> = tests
.into_iter()
.map(|path| {
let case = (self.setup)(path);
let case = self.setup.setup(path);
assert!(
case.expected.source().map(|s| s.is_path()).unwrap_or(false),
"`Case::expected` must be from a file"
);
let test = self.test.clone();
let config = shared_config.clone();
Trial::test(case.name.clone(), move || {
let expected = crate::Data::read_from(&case.expected, case.format);
let actual = (test)(&case.fixture)?;
let actual = test.run(&case.fixture)?;
let actual = actual.to_string();
let actual = crate::Data::text(actual);
config.try_eq(expected, actual, Some(&case.name))?;
config.try_eq(case.expected.clone(), actual, Some(&case.name))?;
Ok(())
})
.with_ignored_flag(shared_config.action == Action::Ignore)
Expand All @@ -147,6 +153,38 @@ where
}
}

pub trait Setup {
fn setup(&self, fixture: std::path::PathBuf) -> Case;
}

impl<F> Setup for F
where
F: Fn(std::path::PathBuf) -> Case,
{
fn setup(&self, fixture: std::path::PathBuf) -> Case {
(self)(fixture)
}
}

pub trait Test<S, E>
where
S: std::fmt::Display,
E: std::fmt::Display,
{
fn run(&self, fixture: &std::path::Path) -> Result<S, E>;
}

impl<F, S, E> Test<S, E> for F
where
F: Fn(&std::path::Path) -> Result<S, E>,
S: std::fmt::Display,
E: std::fmt::Display,
{
fn run(&self, fixture: &std::path::Path) -> Result<S, E> {
(self)(fixture)
}
}

/// A test case enumerated by the [`Harness`] with data from the `setup` function
///
/// See [`harness`][crate::harness] for more details
Expand All @@ -156,7 +194,7 @@ pub struct Case {
/// Input for the test
pub fixture: std::path::PathBuf,
/// What the actual output should be compared against or updated
pub expected: std::path::PathBuf,
/// Explicitly specify what format `expected` is stored in
pub format: Option<DataFormat>,
///
/// Generally derived from `fixture` and loaded with [`Data::read_from`]
pub expected: Data,
}
3 changes: 1 addition & 2 deletions crates/snapbox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,11 @@
//!
//! fn setup(input_path: std::path::PathBuf) -> snapbox::harness::Case {
//! let name = input_path.file_name().unwrap().to_str().unwrap().to_owned();
//! let expected = input_path.with_extension("out");
//! let expected = snapbox::Data::read_from(&input_path.with_extension("out"), None);
//! snapbox::harness::Case {
//! name,
//! fixture: input_path,
//! expected,
//! format: None,
//! }
//! }
//!
Expand Down

0 comments on commit 2bd880a

Please sign in to comment.