Skip to content

Commit

Permalink
Merge pull request #295 from epage/tryfn
Browse files Browse the repository at this point in the history
feat(fn)!: Split Harness out into tryfn
  • Loading branch information
epage authored Apr 23, 2024
2 parents 3e293f6 + a30d3bf commit 0a9e06b
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 78 deletions.
11 changes: 9 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 0 additions & 5 deletions crates/snapbox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ default = ["color-auto", "diff"]

#! Feature Flags

## Simple input/output test harness
harness = ["dep:libtest-mimic", "dep:ignore"]
## Smarter binary file detection
detect-encoding = ["dep:content_inspector"]
## Snapshotting of paths
Expand Down Expand Up @@ -71,9 +69,6 @@ name = "snap-fixture" # For `snapbox`s tests only
normalize-line-endings = "0.3.0"
snapbox-macros = { path = "../snapbox-macros", version = "0.3.8" }

libtest-mimic = { version = "0.7.0", optional = true }
ignore = { version = "0.4", optional = true }

content_inspector = { version = "0.2.4", optional = true }

tempfile = { version = "3.0", optional = true }
Expand Down
8 changes: 7 additions & 1 deletion crates/snapbox/src/assert/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ impl Assert {
}
}

pub(crate) fn try_eq(
pub fn try_eq(
&self,
expected: crate::Data,
actual: crate::Data,
Expand Down Expand Up @@ -397,6 +397,12 @@ impl Assert {
}
}

impl Assert {
pub fn selected_action(&self) -> Action {
self.action
}
}

impl Default for Assert {
fn default() -> Self {
Self {
Expand Down
36 changes: 0 additions & 36 deletions crates/snapbox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
//!
//! Testing Functions:
//! - [`assert_eq`][crate::assert_eq()] for quick and dirty snapshotting
//! - [`harness::Harness`] for discovering test inputs and asserting against snapshot files:
//!
//! Testing Commands:
//! - [`cmd::Command`]: Process spawning for testing of non-interactive commands
Expand Down Expand Up @@ -58,38 +57,6 @@
//! .eq(snapbox::file!["help_output_is_clean.txt"], actual);
//! ```
//!
//! [`harness::Harness`]
#![cfg_attr(not(feature = "harness"), doc = " ```rust,ignore")]
#![cfg_attr(feature = "harness", doc = " ```rust,no_run")]
//! snapbox::harness::Harness::new(
//! "tests/fixtures/invalid",
//! setup,
//! test,
//! )
//! .select(["tests/cases/*.in"])
//! .action_env("SNAPSHOTS")
//! .test();
//!
//! fn setup(input_path: std::path::PathBuf) -> snapbox::harness::Case {
//! let name = input_path.file_name().unwrap().to_str().unwrap().to_owned();
//! let expected = snapbox::Data::read_from(&input_path.with_extension("out"), None);
//! snapbox::harness::Case {
//! name,
//! fixture: input_path,
//! expected,
//! }
//! }
//!
//! fn test(input_path: &std::path::Path) -> Result<usize, Box<dyn std::error::Error>> {
//! let raw = std::fs::read_to_string(input_path)?;
//! let num = raw.parse::<usize>()?;
//!
//! let actual = num + 10;
//!
//! Ok(actual)
//! }
//! ```
//!
//! [trycmd]: https://docs.rs/trycmd
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
Expand All @@ -104,9 +71,6 @@ pub mod path;
pub mod report;
pub mod utils;

#[cfg(feature = "harness")]
pub mod harness;

pub use assert::Assert;
pub use data::Data;
pub use data::IntoData;
Expand Down
11 changes: 11 additions & 0 deletions crates/tryfn/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Change Log
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

<!-- next-header -->
## [Unreleased] - ReleaseDate

<!-- next-url -->
[Unreleased]: https://github.com/assert-rs/trycmd/compare/3e293f6f6167270d85f57a7b59fd94590af6fa97...HEAD
40 changes: 40 additions & 0 deletions crates/tryfn/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[package]
name = "tryfn"
version = "0.1.0"
description = "File-driven snapshot testing for a function"
authors = ["Ed Page <[email protected]>"]
repository = "https://github.com/assert-rs/trycmd.git"
homepage = "https://github.com/assert-rs/trycmd"
documentation = "http://docs.rs/tryfn/"
readme = "README.md"
categories = ["development-tools::testing"]
keywords = ["test", "assert", "snapsjot"]
license.workspace = true
edition.workspace = true
rust-version.workspace = true
include.workspace = true

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]

[package.metadata.release]
pre-release-replacements = [
{file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1},
{file="CHANGELOG.md", search="\\.\\.\\.HEAD", replace="...{{tag_name}}", exactly=1},
{file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1},
{file="CHANGELOG.md", search="<!-- next-header -->", replace="<!-- next-header -->\n## [Unreleased] - ReleaseDate\n", exactly=1},
{file="CHANGELOG.md", search="<!-- next-url -->", replace="<!-- next-url -->\n[Unreleased]: https://github.com/assert-rs/trycmd/compare/{{tag_name}}...HEAD", exactly=1},
]

[features]
default = ["color-auto", "diff"]
diff = ["snapbox/diff"]
color = ["snapbox/color"]
color-auto = ["snapbox/color-auto"]

[dependencies]
snapbox = { path = "../snapbox", version = "0.5.9", default-features = false }
libtest-mimic = "0.7.0"
ignore = "0.4"
1 change: 1 addition & 0 deletions crates/tryfn/LICENSE-APACHE
1 change: 1 addition & 0 deletions crates/tryfn/LICENSE-MIT
26 changes: 26 additions & 0 deletions crates/tryfn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# tryfn

> File-driven snapshot testing for a function
[![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation]
![License](https://img.shields.io/crates/l/tryfn.svg)
[![Crates Status](https://img.shields.io/crates/v/tryfn.svg)][Crates.io]

## License

Licensed under either of

* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.

[Crates.io]: https://crates.io/crates/tryfn
[Documentation]: https://docs.rs/tryfn
64 changes: 30 additions & 34 deletions crates/snapbox/src/harness.rs → crates/tryfn/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@
//! # Examples
//!
//! ```rust,no_run
//! snapbox::harness::Harness::new(
//! fn some_func(num: usize) -> usize {
//! // ...
//! # 10
//! }
//!
//! tryfn::Harness::new(
//! "tests/fixtures/invalid",
//! setup,
//! test,
//! )
//! .select(["tests/cases/*.in"])
//! .action_env("SNAPSHOTS")
//! .test();
//!
//! fn setup(input_path: std::path::PathBuf) -> snapbox::harness::Case {
//! fn setup(input_path: std::path::PathBuf) -> tryfn::Case {
//! let name = input_path.file_name().unwrap().to_str().unwrap().to_owned();
//! let expected = snapbox::Data::read_from(&input_path.with_extension("out"), None);
//! snapbox::harness::Case {
//! let expected = tryfn::Data::read_from(&input_path.with_extension("out"), None);
//! tryfn::Case {
//! name,
//! fixture: input_path,
//! expected,
Expand All @@ -29,26 +33,24 @@
//! let raw = std::fs::read_to_string(input_path)?;
//! let num = raw.parse::<usize>()?;
//!
//! let actual = num + 10;
//! let actual = some_func(num);
//!
//! Ok(actual)
//! }
//! ```
use crate::assert::Action;
use crate::Data;

use libtest_mimic::Trial;

pub use snapbox::data::DataFormat;
pub use snapbox::Data;

/// [`Harness`] for discovering test inputs and asserting against snapshot files
///
/// See [`harness`][crate::harness] for more details
pub struct Harness<S, T, I, E> {
root: std::path::PathBuf,
overrides: Option<ignore::overrides::Override>,
setup: S,
test: T,
config: crate::Assert,
config: snapbox::Assert,
test_output: std::marker::PhantomData<I>,
test_error: std::marker::PhantomData<E>,
}
Expand All @@ -67,29 +69,29 @@ where
/// - `setup`: Given a path, choose the test name and the output location
/// - `test`: Given a path, return the actual output value
///
/// By default [`filters`][crate::filters] are applied, including:
/// By default [`filters`][snapbox::filters] are applied, including:
/// - `...` is a line-wildcard when on a line by itself
/// - `[..]` is a character-wildcard when inside a line
/// - `[EXE]` matches `.exe` on Windows
/// - `\` to `/`
/// - Newlines
///
/// To limit this to newline normalization for text, have [`Setup`] call [`Data::raw`][crate::Data::raw] on `expected`.
/// To limit this to newline normalization for text, have [`Setup`] call [`Data::raw`][snapbox::Data::raw] on `expected`.
pub fn new(input_root: impl Into<std::path::PathBuf>, setup: S, test: T) -> Self {
Self {
root: input_root.into(),
overrides: None,
setup,
test,
config: crate::Assert::new().action_env(crate::assert::DEFAULT_ACTION_ENV),
config: snapbox::Assert::new().action_env(snapbox::assert::DEFAULT_ACTION_ENV),
test_output: Default::default(),
test_error: Default::default(),
}
}

/// Path patterns for selecting input files
///
/// This used gitignore syntax
/// This uses gitignore syntax
pub fn select<'p>(mut self, patterns: impl IntoIterator<Item = &'p str>) -> Self {
let mut overrides = ignore::overrides::OverrideBuilder::new(&self.root);
for line in patterns {
Expand All @@ -99,20 +101,12 @@ where
self
}

/// Read the failure action from an environment variable
pub fn action_env(mut self, var_name: &str) -> Self {
self.config = self.config.action_env(var_name);
self
}

/// Override the failure action
pub fn action(mut self, action: Action) -> Self {
self.config = self.config.action(action);
self
}

/// Customize the assertion behavior
pub fn with_assert(mut self, config: crate::Assert) -> Self {
///
/// Includes
/// - Configuring redactions
/// - Override updating environment vaeiable
pub fn with_assert(mut self, config: snapbox::Assert) -> Self {
self.config = config;
self
}
Expand Down Expand Up @@ -149,11 +143,13 @@ where
Trial::test(case.name.clone(), move || {
let actual = test.run(&case.fixture)?;
let actual = actual.to_string();
let actual = crate::Data::text(actual);
let actual = snapbox::Data::text(actual);
config.try_eq(case.expected.clone(), actual, Some(&case.name))?;
Ok(())
})
.with_ignored_flag(shared_config.action == Action::Ignore)
.with_ignored_flag(
shared_config.selected_action() == snapbox::assert::Action::Ignore,
)
})
.collect();

Expand All @@ -162,6 +158,7 @@ where
}
}

/// Function signature for generating a test [`Case`] from a path fixture
pub trait Setup {
fn setup(&self, fixture: std::path::PathBuf) -> Case;
}
Expand All @@ -175,6 +172,7 @@ where
}
}

/// Function signature for running a test [`Case`]
pub trait Test<S, E>
where
S: std::fmt::Display,
Expand All @@ -194,9 +192,7 @@ where
}
}

/// A test case enumerated by the [`Harness`] with data from the `setup` function
///
/// See [`harness`][crate::harness] for more details
/// A test case enumerated by the [`Harness`] with data from the [`Setup`] function
pub struct Case {
/// Display name
pub name: String,
Expand Down

0 comments on commit 0a9e06b

Please sign in to comment.