Expand description
§Ferrotype
A tintype, also known as a melainotype or ferrotype, is a photograph made by creating a direct positive on a thin sheet of metal, colloquially called ‘tin’, coated with a dark lacquer or enamel and used as the support for the photographic emulsion.
Ferrotype is an opinionated wrapper around insta.rs that makes it easy to create and maintain structured snapshot tests with multiple named sections.
§Features
- Multi-section snapshots with automatically formatted titles
- Rich content support for various data types:
- Debug output (
add_debug) - Token streams (
add_token_stream) with pretty formatting - Bluegum tree structures
- Hex dumps of binary data with
hexcrate - ANSI color code stripping
- Debug output (
- Deterministic output with automatic filtering of memory addresses and non-deterministic data
- Flexible organization with configurable snapshot directory structure
- Debugging support with backtraces and error handling
- Seamless integration with existing insta.rs workflows
§Installation
Add this to your Cargo.toml:
[dev-dependencies]
ferrotype = "0.1"§Quick Start
Here’s the minimum required code to create a ferrotype snapshot:
use ferrotype::Ferrotype;
// 1. Create a new snapshot
let mut snapshot = Ferrotype::new();
// 2. Add content to sections
snapshot.add("Input", "Hello, world!".to_string());
// 3. Assert the snapshot
ferrotype::assert!(snapshot);§Comprehensive Example
use ferrotype::Ferrotype;
#[derive(Debug)]
struct TestData {
name: String,
count: u32,
items: Vec<String>,
}
let mut snapshot = Ferrotype::new();
// Configure snapshot behavior
snapshot.set_filter_memory_addresses(true); // Default: true
snapshot.set_expect_errors(false); // Default: false
// Add different types of content
snapshot.add("Description", "Testing my awesome feature".to_string());
let test_data = TestData {
name: "test".to_string(),
count: 42,
items: vec!["a".to_string(), "b".to_string()],
};
snapshot.add_debug("Test Data", &test_data);
// Add hex dump of binary data
#[cfg(feature = "hex")]
snapshot.add_hex("Binary Data", &[0xDE, 0xAD, 0xBE, 0xEF]);
// Add formatted Rust code
#[cfg(feature = "tokenstream")]
{
let tokens: proc_macro2::TokenStream =
"fn hello() { println!(\"Hello!\"); }".parse().unwrap();
snapshot.add_token_stream("Generated Code", &tokens);
}
// Assert the snapshot
ferrotype::assert!(snapshot);§Examples
The crate includes several example programs demonstrating different aspects of ferrotype:
basic- Core functionality and simple usage patternsfiltering- Demonstrates all filtering options for non-deterministic datafeatures- Shows feature-specific functionality (hex dumps, token streams, etc.)testing- Real-world testing scenarios with an API client
Run examples with:
# Basic example
cargo run --example basic
# Filtering demonstration
cargo run --example filtering
# All features (requires all features enabled)
cargo run --example features --all-features
# Testing example
cargo run --example testing§Snapshot Output Format
The above example would create a snapshot file like this:
---
source: src/lib.rs
expression: "use my_crate::comprehensive_example"
---
Description: >
Testing my awesome feature
TestData: >
TestData {
name: "test",
count: 42,
items: [
"a",
"b",
],
}
BinaryData: >
Length: 4 (0x4) bytes
0000: de ad be ef ....
GeneratedCode: >
fn hello() {
println!("Hello!");
}
Backtrace: >
0: my_crate::comprehensive_example
at src/lib.rs:42:5
1: my_crate::comprehensive_example::{{closure}}
at src/lib.rs:41:1
...§Available Methods
§Core Methods
Ferrotype::new()- Create a new snapshot builderadd(title, content)- Add a section with string contentadd_debug(title, item)- Add a section with debug-formatted contentas_string()- Get the formatted snapshot contentprint()- Print to stdout
§Configuration
set_expect_errors(bool)- Configure whether errors are expectedset_filter_memory_addresses(bool)- Toggle memory address filteringadd_backtrace()- Add current call stack to snapshot
§Feature-specific Methods
These methods are available when the corresponding features are enabled:
§bluegum feature
add_bluegum(title, tree)- Add a rendered bluegum treeadd_bluegum_builder(title, builder)- Add a pre-built bluegum structureadd_bluegum_builder_with(title, closure)- Build bluegum structure with closureadd_bluegum_with(title, tree, styles)- Add bluegum tree with custom styles
§tokenstream feature
add_token_stream(title, tokens)- Add formatted Rust code from TokenStream
§anstream feature
add_strip_str(title, content)- Add content with ANSI codes stripped
§hex feature
add_hex(title, bytes)- Add hex dump of binary data
§Configuration Options
§Snapshot Directory
Control where snapshots are stored:
// Use custom folder structure
#[use_folder(parser, tests)]
ferrotype::assert!(snapshot);
// Results in snapshots stored in: snapshots/parser/tests/§Feature Flags
[dev-dependencies]
ferrotype = { version = "0.1", features = ["hex", "bluegum"] }
# Or disable default features and pick specific ones
ferrotype = { version = "0.1", default-features = false, features = ["tokenstream"] }Available features:
dot_snapshots- Store snapshots in.snapshots/instead ofsnapshots/tokenstream- Enableadd_token_stream()for formatting Rust codebluegum- Enable bluegum tree rendering methodsanstream- Enableadd_strip_str()for ANSI code removalhex- Enableadd_hex()for binary data hex dumps
All features are enabled by default.
§Error Handling
use ferrotype::Ferrotype;
let mut snapshot = Ferrotype::new();
snapshot.set_expect_errors(true); // Don't fail test on errors
snapshot.add("Error Case", "Some error output".to_string());
ferrotype::assert!(snapshot);§Memory Address Filtering
use ferrotype::Ferrotype;
#[derive(Debug)]
struct SomeStruct {
value: i32,
}
let some_struct = SomeStruct { value: 42 };
let mut snapshot = Ferrotype::new();
snapshot.set_filter_memory_addresses(false); // Preserve memory addresses
snapshot.add_debug("Raw Debug", &some_struct);
ferrotype::assert!(snapshot);§Integration with Existing Tests
Ferrotype works alongside existing insta.rs tests:
use ferrotype::Ferrotype;
// Existing insta test
fn existing_test() {
let my_data = vec![1, 2, 3];
insta::assert_debug_snapshot!(my_data);
}
// New ferrotype test
fn enhanced_test() {
let input_data = "test input";
let output_data = vec!["result1", "result2"];
let analysis_results = "analysis complete";
let mut snapshot = Ferrotype::new();
snapshot.add("Input", input_data.to_string());
snapshot.add_debug("Output", &output_data);
snapshot.add("Analysis", analysis_results.to_string());
ferrotype::assert!(snapshot);
}§Best Practices
- Use descriptive section titles: They become the headings in your snapshots
- Group related data: Put related information in the same test
- Enable memory filtering: Keeps snapshots deterministic across runs
- Use appropriate content methods:
add_debugfor structs,add_hexfor binary data, etc. - Review snapshots: Use
cargo insta reviewto accept/reject changes
§License
Licensed under the Blue Oak Model License 1.0.0 - see the LICENSE file for details.
Macros§
- assert
- Assert a snapshot using insta with ferrotype-specific configuration.
Structs§
Functions§
- get_
output_ dir - Get the output directory for snapshots based on the configured feature.