Rust
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Ownership and Borrowing
-
Section 4: Structuring Data
-
Section 5: Collections and Error Handling
-
Section 6: Traits and Generics
-
Section 7: Concurrency
-
Section 8: Building for the Web
-
Section 9: Memory and Performance
-
Section 10: More Standard Library and Ecosystem
-
Section 11: Advanced Rust
-
Section 12: Rust for Systems and WebAssembly
-
Section 13: Tooling and Best Practices
-
Section 14: Data Structures and Algorithms in Rust
-
Section 15: Practical Projects
-
Section 16: Interview Practice
-
Section 17: std::collections In Depth
-
Section 18: std::io and std::fs In Depth
-
Section 19: std::net
-
Section 20: std::option and std::result In Depth
-
Section 21: std::iter In Depth
-
Section 22: std::sync In Depth
-
Section 23: std::string and std::str
-
Section 24: Cargo and Crates.io Ecosystem
-
Section 25: Popular Crates Ecosystem
-
Section 26: Rust Memory Model Deep Dive
-
Section 27: More Practice Exercises
-
Section 28: More Interview Practice
-
Section 29: Async Rust Deep Dive
-
Section 30: Tokio Ecosystem In Depth
-
Section 31: Error Handling Ecosystem Deep Dive
-
Section 32: Serde In Depth
-
Section 33: Web Development with Rust Deep Dive
-
Section 34: Database Access Ecosystem
-
Section 35: Rust for Embedded Systems Deep Dive
-
Section 36: Rust Macros In Depth
-
Section 37: Advanced Trait System
-
Section 38: Unsafe Rust In Depth
-
Section 39: Rust CLI Development
-
Section 40: Testing Ecosystem Deep Dive
-
Section 41: WebAssembly Deep Dive
-
Section 42: Rust Design Patterns
-
Section 43: More Data Structures in Rust
-
Section 44: Final Practice Projects
-
Section 45: Rust Performance Optimization
-
Section 46: Rust Ecosystem Tooling
-
Section 47: More Interview and Review
209: Snapshot Testing with insta
Why bother with snapshot testing when I can just use assert_eq!?
I've seen a lot of developers try to test complex data structures by writing a massive block of assert_eq! calls for every single field. It's tedious, and frankly, it's a nightmare to maintain. If you add one field to a struct, you have to update twenty different tests manually.
Snapshot testing solves this by saying: "I don't want to write the expected output by hand; I just want Rust to remember what the output looked like the last time it was correct." The first time you run the test, insta saves the output to a file (the snapshot). Every subsequent run compares the new output against that file. If they differ, the test fails. It's a lifesaver when you're dealing with large JSON blobs, YAML configs, or complex Debug prints.
How do I actually implement this in my code?
Let's say we're building a tool that generates a project manifest. Instead of asserting every string in the manifest, we can just snapshot the whole thing. First, add insta to your [dev-dependencies]. Then, you can use the assert_snapshot! macro.
#[derive(Debug, Serialize)]
struct ProjectManifest {
name: String,
version: String,
dependencies: Vec<String>,
}
#[test]
fn test_manifest_generation() {
let manifest = ProjectManifest {
name: "my_cool_app".into(),
version: "0.1.0".into(),
dependencies: vec!["serde".into(), "tokio".into()],
};
// This will create a .snap file in your snapshots directory
insta::assert_yaml_snapshot!(manifest);
}
I prefer assert_yaml_snapshot! or assert_json_snapshot! over the generic assert_snapshot! because they handle the serialization for you and make the resulting snapshot files much easier for humans to read in a git diff.
What happens when I actually change the output and the test fails?
This is where insta really beats the manual approach. When a test fails because the output changed, you don't go hunting through your source code to find the line that broke. Instead, you use the insta review tool.
Run this in your terminal:
cargo insta review
This opens an interactive CLI (or a web interface if you prefer) that shows you a side-by-side diff of the "old" snapshot and the "new" output. You can then decide: "Yes, this change was intentional, accept it," or "No, this is a regression, I need to fix my code." Once you accept, insta updates the snapshot file automatically. It turns a tedious chore into a quick decision process.
Can I use snapshots for things that aren't just data structs?
Absolutely. As long as the value implements Debug (or you can turn it into a string), you can snapshot it. I often use it for testing complex error messages or custom CLI output. If you're writing a compiler or a linter, snapshotting the error diagnostics is the only sane way to ensure you haven't accidentally changed the wording of your errors across a hundred different edge cases.
Just keep in mind: don't snapshot things that change every time they run, like timestamps or random IDs. If you do, your tests will fail every single time. You'll need to scrub that data (replace it with a placeholder like <TIMESTAMP>) before passing it to insta.
📋 Practical Task
Implementing Snapshot Tests for a Mock API Response
You are working on a client library that parses API responses from a weather service. The responses are deeply nested and complex, making assert_eq! impractical.
Your Task:
- Create a
WeatherResponsestruct that includes fields forcity,temperature, and a nestedForecaststruct (containing a list of daily highs/lows). - Implement
serde::Serializefor these structs. - Write a test called
test_weather_serializationthat usesinsta::assert_json_snapshot!to verify the output of a sampleWeatherResponse. - Once the snapshot is created, intentionally change one of the temperature values in your test data and run
cargo testto observe the failure. - Use
cargo insta reviewto inspect the diff and accept the change.
There are no comments for now.