Repository: fast/fastrace
Pull request #95: feat: Add Insta Snapshot Testing
Author: login: kutal10
Created: 2025-05-17T11:45:27Z | Merged: 2025-05-18T11:27:31Z

## Summary

Introduces snapshot testing via the `insta` crate and refactors tests accordingly. It keeps the Rust toolchain version at 1.80 to meet the downstream requirement of [Apache OpenDAL](https://github.com/apache/opendal)

This PR really focuses on improving clarity & maintainability

Resolves https://github.com/fast/fastrace/issues/66

## Changes

### 1. Added `insta` for Snapshot Testing
- Introduces [`insta`](https://crates.io/crates/insta) as a testing dependency.
- Enables diff-based snapshot review on assertion failure.
- Snapshots are managed via the CLI (`cargo insta review`).

### 2. Refactored Tests to Use Snapshots
- Converted relevant test assertions to snapshot-based assertions using `insta`.

---

## Testing

```powershell
$ cargo test --features snapshots  

test result: ok. 55 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.01s
```

## Documentation 

The `CONTRIBUTING.md` has been updated to take note of how to run all relevant tests with Insta


Diff:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b32415fb..36bb52a0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -9,7 +9,7 @@ This is a pure rust project, so only `cargo` is needed.
 - `cargo check` to analyze the current package and report errors.
 - `cargo build` to compile the current package.
 - `cargo clippy` to catch common mistakes and improve code.
-- `cargo test` to run unit tests.
+- `cargo test` to run unit tests (*see notes on snapshot testing below*).
 - `cargo bench` to run benchmark tests.
 
 Useful tips:
@@ -17,6 +17,14 @@ Useful tips:
 - Check/Build/Test/Clippy all code: `cargo <cmd> --all-targets --workspace`
 - Test specific function: `cargo test multiple_local_parent`
 
+### Snapshot Testing 
+
+The core `fastrace` crate uses [Insta Snapshot testing](https://insta.rs/) locally. Be aware that to properly run tests,
+you will ideally need to have `cargo-insta` installed in your local rust toolchain to be able to review changes to tests
+where the snapshots have changed, and thus prevent CI from breaking in such instances.
+
+For more information on `cargo-insta` [read the official documentation here.](https://insta.rs/docs/cli/)
+
 ## For features, questions, or discussions
 
 Please open [a new issue](https://github.com/fast/fastrace/issues/new/choose).
diff --git a/Cargo.lock b/Cargo.lock
index ce4aae82..938d7499 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -175,6 +175,18 @@ version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af"
 
+[[package]]
+name = "console"
+version = "0.15.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
+dependencies = [
+ "encode_unicode",
+ "libc",
+ "once_cell",
+ "windows-sys 0.59.0",
+]
+
 [[package]]
 name = "core-foundation"
 version = "0.9.4"
@@ -295,6 +307,12 @@ version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
 
+[[package]]
+name = "encode_unicode"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
+
 [[package]]
 name = "encoding_rs"
 version = "0.8.35"
@@ -372,6 +390,7 @@ dependencies = [
  "fastrace-opentelemetry",
  "flume",
  "futures-timer",
+ "insta",
  "mockall",
  "opentelemetry",
  "opentelemetry-otlp",
@@ -973,6 +992,17 @@ dependencies = [
  "hashbrown 0.15.2",
 ]
 
+[[package]]
+name = "insta"
+version = "1.43.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371"
+dependencies = [
+ "console",
+ "once_cell",
+ "similar",
+]
+
 [[package]]
 name = "ipnet"
 version = "2.11.0"
@@ -1969,6 +1999,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "similar"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
+
 [[package]]
 name = "slab"
 version = "0.4.9"
diff --git a/fastrace/Cargo.toml b/fastrace/Cargo.toml
index 714fac4c..73e050cd 100644
--- a/fastrace/Cargo.toml
+++ b/fastrace/Cargo.toml
@@ -33,6 +33,7 @@ fastrace = { path = ".", features = ["enable"] }
 fastrace-opentelemetry = { workspace = true }
 flume = "0.11"
 futures-timer = "3"
+insta = "1.43.1"
 mockall = "0.13"
 pollster = { version = "0.4.0" }
 rand = "0.9"
diff --git a/fastrace/tests/lib.rs b/fastrace/tests/lib.rs
index d16611ba..674fd17f 100644
--- a/fastrace/tests/lib.rs
+++ b/fastrace/tests/lib.rs
@@ -50,17 +50,14 @@ fn single_thread_single_span() {
 
     fastrace::flush();
 
-    let expected_graph = r#"
-root []
-    iter-span-0 [("tmp_property", "tmp_value")]
-    iter-span-1 [("tmp_property", "tmp_value")]
-    rec-span []
+    let graph = tree_str_from_span_records(collected_spans.lock().clone());
+    insta::assert_snapshot!(graph, @r###"
+    root []
+        iter-span-0 [("tmp_property", "tmp_value")]
+        iter-span-1 [("tmp_property", "tmp_value")]
         rec-span []
-"#;
-    assert_eq!(
-        tree_str_from_span_records(collected_spans.lock().clone()),
-        expected_graph
-    );
+            rec-span []
+    "###);
 }
 
 #[test]
@@ -87,60 +84,53 @@ fn single_thread_multiple_spans() {
 
     fastrace::flush();
 
-    let expected_graph1 = r#"
-root1 []
-    iter-span-0 [("tmp_property", "tmp_value")]
-    iter-span-1 [("tmp_property", "tmp_value")]
-    rec-span []
-        rec-span []
-"#;
-    let expected_graph2 = r#"
-root2 []
-    iter-span-0 [("tmp_property", "tmp_value")]
-    iter-span-1 [("tmp_property", "tmp_value")]
-    rec-span []
-        rec-span []
-"#;
-    let expected_graph3 = r#"
-root3 []
-    iter-span-0 [("tmp_property", "tmp_value")]
-    iter-span-1 [("tmp_property", "tmp_value")]
-    rec-span []
-        rec-span []
-"#;
-    assert_eq!(
-        tree_str_from_span_records(
-            collected_spans
-                .lock()
-                .iter()
-                .filter(|s| s.trace_id == TraceId(12))
-                .cloned()
-                .collect()
-        ),
-        expected_graph1
+    let graph1 = tree_str_from_span_records(
+        collected_spans
+            .lock()
+            .iter()
+            .filter(|s| s.trace_id == TraceId(12))
+            .cloned()
+            .collect(),
     );
-    assert_eq!(
-        tree_str_from_span_records(
-            collected_spans
-                .lock()
-                .iter()
-                .filter(|s| s.trace_id == TraceId(13))
-                .cloned()
-                .collect()
-        ),
-        expected_graph2
+    insta::assert_snapshot!(graph1, @r###"
+    root1 []
+        iter-span-0 [("tmp_property", "tmp_value")]
+        iter-span-1 [("tmp_property", "tmp_value")]
+        rec-span []
+            rec-span []
+    "###);
+
+    let graph2 = tree_str_from_span_records(
+        collected_spans
+            .lock()
+            .iter()
+            .filter(|s| s.trace_id == TraceId(13))
+            .cloned()
+            .collect(),
     );
-    assert_eq!(
-        tree_str_from_span_records(
-            collected_spans
-                .lock()
-                .iter()
-                .filter(|s| s.trace_id == TraceId(14))
-                .cloned()
-                .collect()
-        ),
-        expected_graph3
+    insta::assert_snapshot!(graph2, @r###"
+    root2 []
+        iter-span-0 [("tmp_property", "tmp_value")]
+        iter-span-1 [("tmp_property", "tmp_value")]
+        rec-span []
+            rec-span []
+    "###);
+
+    let graph3 = tree_str_from_span_records(
+        collected_spans
+            .lock()
+            .iter()
+            .filter(|s| s.trace_id == TraceId(14))
+            .cloned()
+            .collect(),
     );
+    insta::assert_snapshot!(graph3, @r###"
+    root3 []
+        iter-span-0 [("tmp_property", "tmp_value")]
+        iter-span-1 [("tmp_property", "tmp_value")]
+        rec-span []
+            rec-span []
+    "###);
 }
 
 #[test]
@@ -172,37 +162,34 @@ fn multiple_threads_single_span() {
 
     fastrace::flush();
 
-    let expected_graph = r#"
-root []
-    cross-thread []
-        iter-span-0 [("tmp_property", "tmp_value")]
-        iter-span-1 [("tmp_property", "tmp_value")]
-        rec-span []
+    let graph = tree_str_from_span_records(collected_spans.lock().clone());
+    insta::assert_snapshot!(graph, @r###"
+    root []
+        cross-thread []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
             rec-span []
-    cross-thread []
-        iter-span-0 [("tmp_property", "tmp_value")]
-        iter-span-1 [("tmp_property", "tmp_value")]
-        rec-span []
+                rec-span []
+        cross-thread []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
             rec-span []
-    cross-thread []
-        iter-span-0 [("tmp_property", "tmp_value")]
-        iter-span-1 [("tmp_property", "tmp_value")]
-        rec-span []
+                rec-span []
+        cross-thread []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
             rec-span []
-    cross-thread []
+                rec-span []
+        cross-thread []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
+            rec-span []
+                rec-span []
         iter-span-0 [("tmp_property", "tmp_value")]
         iter-span-1 [("tmp_property", "tmp_value")]
         rec-span []
             rec-span []
-    iter-span-0 [("tmp_property", "tmp_value")]
-    iter-span-1 [("tmp_property", "tmp_value")]
-    rec-span []
-        rec-span []
-"#;
-    assert_eq!(
-        tree_str_from_span_records(collected_spans.lock().clone()),
-        expected_graph
-    );
+    "###);
 }
 
 #[test]
@@ -246,90 +233,85 @@ fn multiple_threads_multiple_spans() {
 
     fastrace::flush();
 
-    let expected_graph1 = r#"
-root1 []
-    iter-span-0 [("tmp_property", "tmp_value")]
-    iter-span-1 [("tmp_property", "tmp_value")]
-    merged []
+    let graph1 = tree_str_from_span_records(
+        collected_spans
+            .lock()
+            .iter()
+            .filter(|s| s.trace_id == TraceId(12))
+            .cloned()
+            .collect(),
+    );
+    insta::assert_snapshot!(graph1, @r###"
+    root1 []
         iter-span-0 [("tmp_property", "tmp_value")]
         iter-span-1 [("tmp_property", "tmp_value")]
-        local []
-        rec-span []
+        merged []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
+            local []
             rec-span []
-    merged []
-        iter-span-0 [("tmp_property", "tmp_value")]
-        iter-span-1 [("tmp_property", "tmp_value")]
-        local []
-        rec-span []
+                rec-span []
+        merged []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
+            local []
             rec-span []
-    merged []
-        iter-span-0 [("tmp_property", "tmp_value")]
-        iter-span-1 [("tmp_property", "tmp_value")]
-        local []
-        rec-span []
+                rec-span []
+        merged []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
+            local []
             rec-span []
-    merged []
-        iter-span-0 [("tmp_property", "tmp_value")]
-        iter-span-1 [("tmp_property", "tmp_value")]
-        local []
-        rec-span []
+                rec-span []
+        merged []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
+            local []
             rec-span []
-    rec-span []
-        rec-span []
-"#;
-    let expected_graph2 = r#"
-root2 []
-    iter-span-0 [("tmp_property", "tmp_value")]
-    iter-span-1 [("tmp_property", "tmp_value")]
-    merged []
-        iter-span-0 [("tmp_property", "tmp_value")]
-        iter-span-1 [("tmp_property", "tmp_value")]
-        local []
+                rec-span []
         rec-span []
             rec-span []
-    merged []
+    "###);
+
+    let graph2 = tree_str_from_span_records(
+        collected_spans
+            .lock()
+            .iter()
+            .filter(|s| s.trace_id == TraceId(13))
+            .cloned()
+            .collect(),
+    );
+    insta::assert_snapshot!(graph2, @r###"
+    root2 []
         iter-span-0 [("tmp_property", "tmp_value")]
         iter-span-1 [("tmp_property", "tmp_value")]
-        local []
-        rec-span []
+        merged []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
+            local []
             rec-span []
-    merged []
-        iter-span-0 [("tmp_property", "tmp_value")]
-        iter-span-1 [("tmp_property", "tmp_value")]
-        local []
-        rec-span []
+                rec-span []
+        merged []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
+            local []
             rec-span []
-    merged []
-        iter-span-0 [("tmp_property", "tmp_value")]
-        iter-span-1 [("tmp_property", "tmp_value")]
-        local []
-        rec-span []
+                rec-span []
+        merged []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
+            local []
+            rec-span []
+                rec-span []
+        merged []
+            iter-span-0 [("tmp_property", "tmp_value")]
+            iter-span-1 [("tmp_property", "tmp_value")]
+            local []
             rec-span []
-    rec-span []
+                rec-span []
         rec-span []
-"#;
-    assert_eq!(
-        tree_str_from_span_records(
-            collected_spans
-                .lock()
-                .iter()
-                .filter(|s| s.trace_id == TraceId(12))
-                .cloned()
-                .collect()
-        ),
-        expected_graph1
-    );
-    assert_eq!(
-        tree_str_from_span_records(
-            collected_spans
-                .lock()
-                .iter()
-                .filter(|s| s.trace_id == TraceId(13))
-                .cloned()
-                .collect()
-        ),
-        expected_graph2
-    );
+            rec-span []
+    "###);
 }
 
 #[test]
@@ -459,31 +441,28 @@ fn test_macro() {
 
     fastrace::flush();
 
-    let expected_graph = r#"
-root []
-    run []
-        local-span []
-        run-inner []
-        work []
+    let graph = tree_str_from_span_records(collected_spans.lock().clone());
+    insta::assert_snapshot!(graph, @r###"
+    root []
+        run []
+            local-span []
+            run-inner []
+            work []
+                sleep []
+            work []
+                sleep []
+                work-inner []
+        work2 []
             sleep []
-        work []
             sleep []
             work-inner []
-    work2 []
-        sleep []
-        sleep []
-        work-inner []
-    work3 []
-        sleep []
-        sleep []
-        sleep []
-        sleep []
-        work-inner []
-"#;
-    assert_eq!(
-        tree_str_from_span_records(collected_spans.lock().clone()),
-        expected_graph
-    );
+        work3 []
+            sleep []
+            sleep []
+            sleep []
+            sleep []
+            work-inner []
+    "###);
 }
 
 #[test]
@@ -523,17 +502,14 @@ fn macro_example() {
 
     fastrace::flush();
 
-    let expected_graph = r#"
-root []
-    do_something_async_short_name []
-    do_something_short_name []
-    lib::macro_example::{{closure}}::do_something []
-    lib::macro_example::{{closure}}::do_something_async::{{closure}} []
-"#;
-    assert_eq!(
-        tree_str_from_span_records(collected_spans.lock().clone()),
-        expected_graph
-    );
+    let graph = tree_str_from_span_records(collected_spans.lock().clone());
+    insta::assert_snapshot!(graph,@r###"
+    root []
+        do_something_async_short_name []
+        do_something_short_name []
+        lib::macro_example::{{closure}}::do_something []
+        lib::macro_example::{{closure}}::do_something_async::{{closure}} []
+    "###);
 }
 
 #[test]
@@ -556,17 +532,14 @@ fn multiple_local_parent() {
 
     fastrace::flush();
 
-    let expected_graph = r#"
-root []
-    span1 []
-        span2 []
-            span3 []
-        span4 []
-"#;
-    assert_eq!(
-        tree_str_from_span_records(collected_spans.lock().clone()),
-        expected_graph
-    );
+    let graph = tree_str_from_span_records(collected_spans.lock().clone());
+    insta::assert_snapshot!(graph, @r###"
+    root []
+        span1 []
+            span2 []
+                span3 []
+            span4 []
+    "###);
 }
 
 #[test]
@@ -588,15 +561,12 @@ fn early_local_collect() {
 
     fastrace::flush();
 
-    let expected_graph = r#"
-root []
-    span1 []
-        span2 []
-"#;
-    assert_eq!(
-        tree_str_from_span_records(collected_spans.lock().clone()),
-        expected_graph
-    );
+    let graph = tree_str_from_span_records(collected_spans.lock().clone());
+    insta::assert_snapshot!(graph, @r###"
+    root []
+        span1 []
+            span2 []
+    "###);
 }
 
 #[test]
@@ -639,14 +609,11 @@ fn test_property() {
 
     fastrace::flush();
 
-    let expected_graph = r#"
-root [("k1", "v1"), ("k2", "v2"), ("k3", "v3"), ("k4", "v4"), ("k5", "v5"), ("k6", "v6"), ("k7", "v7"), ("k8", "v8"), ("k9", "v9")]
-    span [("k10", "v10"), ("k11", "v11"), ("k12", "v12"), ("k13", "v13"), ("k14", "v14"), ("k15", "v15")]
-"#;
-    assert_eq!(
-        tree_str_from_span_records(collected_spans.lock().clone()),
-        expected_graph
-    );
+    let graph = tree_str_from_span_records(collected_spans.lock().clone());
+    insta::assert_snapshot!(graph, @r###"
+    root [("k1", "v1"), ("k2", "v2"), ("k3", "v3"), ("k4", "v4"), ("k5", "v5"), ("k6", "v6"), ("k7", "v7"), ("k8", "v8"), ("k9", "v9")]
+        span [("k10", "v10"), ("k11", "v11"), ("k12", "v12"), ("k13", "v13"), ("k14", "v14"), ("k15", "v15")]
+    "###);
 }
 
 #[test]
@@ -678,14 +645,11 @@ fn test_event() {
 
     fastrace::flush();
 
-    let expected_graph = r#"
-root [] [("event1 in root", [("k1", "v1"), ("k2", "v2"), ("k3", "v3")]), ("event2 in root", [("k4", "v4"), ("k5", "v5"), ("k6", "v6")])]
-    span [] [("event3 in span", [("k7", "v7"), ("k8", "v8"), ("k9", "v9")])]
-"#;
-    assert_eq!(
-        tree_str_from_span_records(collected_spans.lock().clone()),
-        expected_graph
-    );
+    let graph = tree_str_from_span_records(collected_spans.lock().clone());
+    insta::assert_snapshot!(graph, @r###"
+    root [] [("event1 in root", [("k1", "v1"), ("k2", "v2"), ("k3", "v3")]), ("event2 in root", [("k4", "v4"), ("k5", "v5"), ("k6", "v6")])]
+        span [] [("event3 in span", [("k7", "v7"), ("k8", "v8"), ("k9", "v9")])]
+    "###);
 }
 
 #[test]
@@ -741,17 +705,14 @@ fn test_macro_properties() {
 
     fastrace::flush();
 
-    let expected_graph = r#"
-root []
-    bar []
-    bar_async []
-    foo [("k1", "v1"), ("a", "argument a is 1"), ("b", "Bar"), ("escaped1", "Bar{}"), ("escaped2", "{ \"a\": \"b\"}")]
-    foo_async [("k1", "v1"), ("a", "argument a is 1"), ("b", "Bar"), ("escaped1", "Bar{}"), ("escaped2", "{ \"a\": \"b\"}")]
-"#;
-    assert_eq!(
-        tree_str_from_span_records(collected_spans.lock().clone()),
-        expected_graph
-    );
+    let graph = tree_str_from_span_records(collected_spans.lock().clone());
+    insta::assert_snapshot!(graph, @r###"
+    root []
+        bar []
+        bar_async []
+        foo [("k1", "v1"), ("a", "argument a is 1"), ("b", "Bar"), ("escaped1", "Bar{}"), ("escaped2", "{ \"a\": \"b\"}")]
+        foo_async [("k1", "v1"), ("a", "argument a is 1"), ("b", "Bar"), ("escaped1", "Bar{}"), ("escaped2", "{ \"a\": \"b\"}")]
+    "###);
 }
 
 #[test]
@@ -765,14 +726,12 @@ fn test_not_sampled() {
         let _span = LocalSpan::enter_with_local_parent("span");
     }
     fastrace::flush();
-    let expected_graph = r#"
-root []
-    span []
-"#;
-    assert_eq!(
-        tree_str_from_span_records(collected_spans.lock().clone()),
-        expected_graph
-    );
+
+    let graph = tree_str_from_span_records(collected_spans.lock().clone());
+    insta::assert_snapshot!(graph,@r###"
+    root []
+        span []
+    "###);
 
     let (reporter, collected_spans) = TestReporter::new();
     fastrace::set_reporter(reporter, Config::default());


Reviews:
user: login: andylokandy
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-18T11:08:32Z
user: login: kutal10
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T11:15:16Z
user: login: kutal10
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T11:15:20Z

Review comments:
diff_hunk: @@ -9,14 +9,22 @@ This is a pure rust project, so only `cargo` is needed.
 - `cargo check` to analyze the current package and report errors.
 - `cargo build` to compile the current package.
 - `cargo clippy` to catch common mistakes and improve code.
-- `cargo test` to run unit tests.
+- `cargo test` to run unit tests*.
path: CONTRIBUTING.md
user: login: andylokandy
body: is this a typo?
created_at: 2025-05-18T11:07:09Z
author_association: COLLABORATOR
diff_hunk: @@ -9,14 +9,22 @@ This is a pure rust project, so only `cargo` is needed.
 - `cargo check` to analyze the current package and report errors.
 - `cargo build` to compile the current package.
 - `cargo clippy` to catch common mistakes and improve code.
-- `cargo test` to run unit tests.
+- `cargo test` to run unit tests*.
 - `cargo bench` to run benchmark tests.
 
 Useful tips:
 
 - Check/Build/Test/Clippy all code: `cargo <cmd> --all-targets --workspace`
 - Test specific function: `cargo test multiple_local_parent`
 
+### *Testing 
path: CONTRIBUTING.md
user: login: andylokandy
body: ditto
created_at: 2025-05-18T11:07:20Z
author_association: COLLABORATOR
diff_hunk: @@ -9,14 +9,22 @@ This is a pure rust project, so only `cargo` is needed.
 - `cargo check` to analyze the current package and report errors.
 - `cargo build` to compile the current package.
 - `cargo clippy` to catch common mistakes and improve code.
-- `cargo test` to run unit tests.
+- `cargo test` to run unit tests*.
path: CONTRIBUTING.md
user: login: kutal10
body: Was not a typo - was using the asterisk as a footnote. Updated to be more explicit https://github.com/fast/fastrace/pull/95/commits/476316f44d43ba9fd29cbb427ea30f403220d3a9
created_at: 2025-05-18T11:15:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -9,14 +9,22 @@ This is a pure rust project, so only `cargo` is needed.
 - `cargo check` to analyze the current package and report errors.
 - `cargo build` to compile the current package.
 - `cargo clippy` to catch common mistakes and improve code.
-- `cargo test` to run unit tests.
+- `cargo test` to run unit tests*.
 - `cargo bench` to run benchmark tests.
 
 Useful tips:
 
 - Check/Build/Test/Clippy all code: `cargo <cmd> --all-targets --workspace`
 - Test specific function: `cargo test multiple_local_parent`
 
+### *Testing 
path: CONTRIBUTING.md
user: login: kutal10
body: Was not a typo - was using the asterisk as a footnote. Updated to be more explicit https://github.com/fast/fastrace/pull/95/commits/476316f44d43ba9fd29cbb427ea30f403220d3a9
created_at: 2025-05-18T11:15:20Z
author_association: CONTRIBUTOR

PR comments:
user: login: andylokandy
created_at: 2025-05-17T14:06:12Z
body: Hey @kutal10! Thanks so much for this contribution. The snapshot testing implementation looks really clean and well thought out.

One thing I'm a bit concerned about is how this might affect our MSRV. We're currently locked at 1.80 because of our major dependant [apache/opendal](https://github.com/apache/opendal). Have you checked if insta is compatible with 1.80?

Also, I was wondering if you'd considered using inline snapshots instead? They have the advantage of keeping the test content right next to the test logic, which I find makes the tests easier to understand and maintain. You wouldn't need to jump between files to see what's being tested.

Otherwise, great work on this!  Let me know your thoughts on these suggestions.
author_association: COLLABORATOR
user: login: kutal10
created_at: 2025-05-17T14:50:06Z
body: @andylokandy 

> One thing I'm a bit concerned about is how this might affect our MSRV. We're currently locked at 1.80 because of our major dependant [apache/opendal](https://github.com/apache/opendal). Have you checked if insta is compatible with 1.80?

Yep Insta works fine with 1.80, turns out the bump was just to help resolve something locally in my toolchain. Updated the PR to make mention it maintains the toolchain at 1.80. 

> Also, I was wondering if you'd considered using inline snapshots instead? They have the advantage of keeping the test content right next to the test logic, which I find makes the tests easier to understand and maintain. You wouldn't need to jump between files to see what's being tested.

Makes sense, it's a fairly self contained file. I've updated it to be inline now! 

PR's been updated - CI passes! 

author_association: CONTRIBUTOR
user: login: andylokandy
created_at: 2025-05-18T05:58:25Z
body: What is the reason why snapshot tests need the 'snapshot' feature flag? AFAIN, insta would work as normal test unless we need to update the snapshot.
author_association: COLLABORATOR
user: login: kutal10
created_at: 2025-05-18T09:17:40Z
body: @andylokandy 

Great question so you're right - insta works as normal if you just run `cargo test` if I removed the feature flag attributes. However, I  believes it's good practice to keep:

- If snapshot tests are failing because snapshots weren’t updated or `cargo insta review` wasn’t run, it could possibly break builds or introduce confusion. 
- It also signals "These tests are tied to output graph checks and may require developer review or snapshot updates."

So it's more of a clean separation of concerns to segregate logic tests vs specialised output tests. I have made a choice to make snapshot testing opt-in and explicit for just developer intent purposes. 

It wouldn't impact downstream consumers as `Insta` is a dev dependency of course
author_association: CONTRIBUTOR
user: login: andylokandy
created_at: 2025-05-18T09:28:38Z
body: > If snapshot tests are failing because snapshots weren’t updated or cargo insta review wasn’t run, it could possibly break builds or introduce confusion.

If someone changes code that affects snapshots, they'll need the insta tools installed or CI will break. Maybe we should document this requirement clearly?
author_association: COLLABORATOR
user: login: kutal10
created_at: 2025-05-18T09:50:21Z
body: Just so I understand, you'd rather I remove the feature flag, have it run every time, and instead update docs to make it clear that you need `cargo-insta` installed locally in the event any relevant snapshot tests change? 
author_association: CONTRIBUTOR
user: login: andylokandy
created_at: 2025-05-18T09:55:52Z
body: lgtm
author_association: COLLABORATOR
user: login: kutal10
created_at: 2025-05-18T10:29:55Z
body: @andylokandy Aforementioned changes pushed!
author_association: CONTRIBUTOR
user: login: kutal10
created_at: 2025-05-18T11:16:49Z
body: @andylokandy Docs updated - feel free to merge when you're happy
author_association: CONTRIBUTOR
user: login: andylokandy
created_at: 2025-05-18T11:18:34Z
body: LGTM. Thank you very much!
author_association: COLLABORATOR