agy-superpowers 5.1.4 → 5.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/package.json +1 -1
  2. package/template/agent/rules/debug-confirmation-policy.md +34 -0
  3. package/template/agent/rules/language-matching.md +32 -0
  4. package/template/agent/skills/rust-developer/SKILL.md +281 -0
  5. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +231 -0
  6. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +124 -0
  7. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +131 -0
  8. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +132 -0
  9. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +95 -0
  10. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +141 -0
  11. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +125 -0
  12. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +127 -0
  13. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +120 -0
  14. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +131 -0
  15. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +156 -0
  16. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +122 -0
  17. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +167 -0
  18. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +134 -0
  19. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +143 -0
  20. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +121 -0
  21. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +143 -0
  22. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +187 -0
  23. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +165 -0
  24. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +177 -0
  25. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +163 -0
  26. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +146 -0
  27. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +142 -0
  28. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +160 -0
  29. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +125 -0
  30. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +162 -0
  31. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +177 -0
  32. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +184 -0
  33. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +168 -0
  34. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +182 -0
  35. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +199 -0
  36. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +175 -0
  37. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +185 -0
  38. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +203 -0
  39. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +171 -0
  40. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +158 -0
  41. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +195 -0
  42. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +171 -0
  43. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +156 -0
  44. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +191 -0
  45. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +198 -0
  46. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +154 -0
  47. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +167 -0
  48. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +169 -0
  49. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +172 -0
  50. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +189 -0
  51. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +113 -0
  52. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +147 -0
  53. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +122 -0
  54. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +161 -0
  55. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +149 -0
  56. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +138 -0
  57. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +169 -0
  58. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +116 -0
  59. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +128 -0
  60. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +136 -0
  61. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +131 -0
  62. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +179 -0
  63. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +144 -0
  64. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +152 -0
  65. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +145 -0
  66. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +133 -0
  67. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +152 -0
  68. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +124 -0
  69. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +115 -0
  70. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +151 -0
  71. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +130 -0
  72. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +155 -0
  73. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +171 -0
  74. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +138 -0
  75. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +107 -0
  76. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +154 -0
  77. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +118 -0
  78. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +157 -0
  79. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +133 -0
  80. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +131 -0
  81. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +136 -0
  82. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +135 -0
  83. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +122 -0
  84. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +172 -0
  85. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +168 -0
  86. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +142 -0
  87. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +168 -0
  88. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +147 -0
  89. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +158 -0
  90. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +139 -0
  91. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +147 -0
  92. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +149 -0
  93. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +174 -0
  94. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +159 -0
  95. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +138 -0
  96. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +142 -0
  97. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +156 -0
  98. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +172 -0
  99. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +164 -0
  100. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +99 -0
  101. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +104 -0
  102. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +94 -0
  103. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +78 -0
  104. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +76 -0
  105. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +123 -0
  106. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +127 -0
  107. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +129 -0
  108. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +131 -0
  109. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +142 -0
  110. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +86 -0
  111. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +154 -0
  112. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +118 -0
  113. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +92 -0
  114. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +65 -0
  115. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +101 -0
  116. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +161 -0
  117. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +187 -0
  118. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +142 -0
  119. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +152 -0
  120. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +141 -0
  121. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +181 -0
  122. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +160 -0
  123. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +171 -0
  124. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +130 -0
  125. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +167 -0
  126. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +144 -0
  127. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +154 -0
  128. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +141 -0
  129. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +95 -0
  130. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +135 -0
  131. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +124 -0
  132. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +135 -0
  133. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +134 -0
  134. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +134 -0
  135. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +105 -0
  136. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +65 -0
  137. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +97 -0
  138. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +122 -0
  139. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +119 -0
  140. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +153 -0
  141. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +136 -0
  142. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +133 -0
  143. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +120 -0
  144. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +137 -0
  145. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +134 -0
  146. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +150 -0
  147. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +123 -0
  148. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +113 -0
  149. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +175 -0
  150. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +149 -0
  151. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +142 -0
  152. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +133 -0
  153. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +148 -0
  154. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +130 -0
  155. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +120 -0
  156. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +155 -0
  157. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +139 -0
  158. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +135 -0
  159. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +162 -0
  160. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +186 -0
  161. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +162 -0
  162. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +160 -0
  163. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +151 -0
  164. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +171 -0
  165. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +142 -0
  166. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +168 -0
  167. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +151 -0
  168. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +144 -0
  169. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +189 -0
  170. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +226 -0
  171. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +161 -0
  172. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +130 -0
  173. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +154 -0
  174. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +127 -0
  175. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +154 -0
  176. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +142 -0
  177. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +146 -0
  178. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +160 -0
  179. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +159 -0
  180. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +144 -0
  181. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +137 -0
  182. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +188 -0
  183. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +143 -0
  184. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +131 -0
  185. package/template/agent/skills/systematic-debugging/SKILL.md +17 -0
@@ -0,0 +1,171 @@
1
+ # test-criterion-bench
2
+
3
+ > Use `criterion` for benchmarking
4
+
5
+ ## Why It Matters
6
+
7
+ Criterion provides statistically rigorous benchmarking with warmup, multiple iterations, outlier detection, and comparison between runs. It's far more reliable than simple timing with `Instant::now()`.
8
+
9
+ ## Setup
10
+
11
+ ```toml
12
+ # Cargo.toml
13
+ [dev-dependencies]
14
+ criterion = "0.5"
15
+
16
+ [[bench]]
17
+ name = "my_benchmark"
18
+ harness = false
19
+ ```
20
+
21
+ ## Basic Benchmark
22
+
23
+ ```rust
24
+ // benches/my_benchmark.rs
25
+ use criterion::{black_box, criterion_group, criterion_main, Criterion};
26
+
27
+ fn fibonacci(n: u64) -> u64 {
28
+ match n {
29
+ 0 => 0,
30
+ 1 => 1,
31
+ n => fibonacci(n - 1) + fibonacci(n - 2),
32
+ }
33
+ }
34
+
35
+ fn bench_fibonacci(c: &mut Criterion) {
36
+ c.bench_function("fib 20", |b| {
37
+ b.iter(|| fibonacci(black_box(20)))
38
+ });
39
+ }
40
+
41
+ criterion_group!(benches, bench_fibonacci);
42
+ criterion_main!(benches);
43
+ ```
44
+
45
+ ## black_box is Critical
46
+
47
+ ```rust
48
+ // BAD: Compiler may optimize away the computation
49
+ b.iter(|| fibonacci(20)); // Result unused, might be eliminated
50
+
51
+ // GOOD: black_box prevents optimization
52
+ b.iter(|| fibonacci(black_box(20)));
53
+
54
+ // Also wrap the result if needed
55
+ b.iter(|| black_box(fibonacci(black_box(20))));
56
+ ```
57
+
58
+ ## Comparing Implementations
59
+
60
+ ```rust
61
+ fn bench_comparison(c: &mut Criterion) {
62
+ let mut group = c.benchmark_group("String concat");
63
+
64
+ let data = "hello";
65
+
66
+ group.bench_function("format!", |b| {
67
+ b.iter(|| format!("{}{}", black_box(data), " world"))
68
+ });
69
+
70
+ group.bench_function("push_str", |b| {
71
+ b.iter(|| {
72
+ let mut s = String::from(black_box(data));
73
+ s.push_str(" world");
74
+ s
75
+ })
76
+ });
77
+
78
+ group.bench_function("concat", |b| {
79
+ b.iter(|| [black_box(data), " world"].concat())
80
+ });
81
+
82
+ group.finish();
83
+ }
84
+ ```
85
+
86
+ ## Parameterized Benchmarks
87
+
88
+ ```rust
89
+ fn bench_vec_push(c: &mut Criterion) {
90
+ let mut group = c.benchmark_group("Vec::push");
91
+
92
+ for size in [100, 1000, 10000].iter() {
93
+ group.bench_with_input(
94
+ BenchmarkId::from_parameter(size),
95
+ size,
96
+ |b, &size| {
97
+ b.iter(|| {
98
+ let mut v = Vec::new();
99
+ for i in 0..size {
100
+ v.push(black_box(i));
101
+ }
102
+ v
103
+ });
104
+ },
105
+ );
106
+ }
107
+
108
+ group.finish();
109
+ }
110
+ ```
111
+
112
+ ## Throughput Measurement
113
+
114
+ ```rust
115
+ use criterion::Throughput;
116
+
117
+ fn bench_parse(c: &mut Criterion) {
118
+ let input = "a]ong string to parse...";
119
+
120
+ let mut group = c.benchmark_group("Parser");
121
+ group.throughput(Throughput::Bytes(input.len() as u64));
122
+
123
+ group.bench_function("parse", |b| {
124
+ b.iter(|| parse(black_box(input)))
125
+ });
126
+
127
+ group.finish();
128
+ }
129
+ ```
130
+
131
+ ## Running Benchmarks
132
+
133
+ ```bash
134
+ # Run all benchmarks
135
+ cargo bench
136
+
137
+ # Run specific benchmark
138
+ cargo bench -- fib
139
+
140
+ # Save baseline for comparison
141
+ cargo bench -- --save-baseline main
142
+
143
+ # Compare against baseline
144
+ cargo bench -- --baseline main
145
+ ```
146
+
147
+ ## Evidence from tokio
148
+
149
+ ```rust
150
+ // https://github.com/tokio-rs/tokio/blob/master/benches/sync_mpsc.rs
151
+ use criterion::{criterion_group, criterion_main, Criterion};
152
+
153
+ fn send_data<T: Default, const SIZE: usize>(
154
+ g: &mut BenchmarkGroup<WallTime>,
155
+ prefix: &str
156
+ ) {
157
+ let rt = rt();
158
+ g.bench_function(format!("{prefix}_{SIZE}"), |b| {
159
+ b.iter(|| {
160
+ let (tx, mut rx) = mpsc::channel::<T>(SIZE);
161
+ rt.block_on(tx.send(T::default())).unwrap();
162
+ rt.block_on(rx.recv()).unwrap();
163
+ })
164
+ });
165
+ }
166
+ ```
167
+
168
+ ## See Also
169
+
170
+ - [perf-profile-first](perf-profile-first.md) - Profile before optimizing
171
+ - [perf-black-box-bench](perf-black-box-bench.md) - Use black_box in benchmarks
@@ -0,0 +1,142 @@
1
+ # test-descriptive-names
2
+
3
+ > Use descriptive test names that explain what is being tested
4
+
5
+ ## Why It Matters
6
+
7
+ Test names appear in test output and serve as documentation. A good test name tells you what behavior is being verified without reading the test body. When a test fails, a descriptive name immediately tells you what broke.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ #[test]
13
+ fn test1() { ... }
14
+
15
+ #[test]
16
+ fn test_parse() { ... } // Parse what? What behavior?
17
+
18
+ #[test]
19
+ fn it_works() { ... }
20
+
21
+ #[test]
22
+ fn test_function() { ... }
23
+
24
+ // Failure output: "test test_parse ... FAILED"
25
+ // What failed? No idea.
26
+ ```
27
+
28
+ ## Good
29
+
30
+ ```rust
31
+ #[test]
32
+ fn parse_returns_error_for_empty_input() { ... }
33
+
34
+ #[test]
35
+ fn parse_handles_unicode_characters() { ... }
36
+
37
+ #[test]
38
+ fn user_creation_requires_valid_email() { ... }
39
+
40
+ #[test]
41
+ fn expired_token_is_rejected() { ... }
42
+
43
+ // Failure output: "test parse_returns_error_for_empty_input ... FAILED"
44
+ // Immediately know what broke!
45
+ ```
46
+
47
+ ## Naming Patterns
48
+
49
+ ```rust
50
+ // Pattern: function_condition_expected_result
51
+ #[test]
52
+ fn parse_valid_json_returns_document() { ... }
53
+
54
+ #[test]
55
+ fn parse_invalid_json_returns_syntax_error() { ... }
56
+
57
+ // Pattern: scenario_expectation
58
+ #[test]
59
+ fn empty_cart_has_zero_total() { ... }
60
+
61
+ #[test]
62
+ fn adding_item_increases_cart_total() { ... }
63
+
64
+ // Pattern: when_given_then (BDD-style)
65
+ #[test]
66
+ fn when_user_not_found_then_returns_404() { ... }
67
+ ```
68
+
69
+ ## Edge Cases
70
+
71
+ ```rust
72
+ #[test]
73
+ fn handles_empty_string() { ... }
74
+
75
+ #[test]
76
+ fn handles_max_length_input() { ... }
77
+
78
+ #[test]
79
+ fn handles_unicode_emoji() { ... }
80
+
81
+ #[test]
82
+ fn handles_null_bytes() { ... }
83
+
84
+ #[test]
85
+ fn handles_concurrent_access() { ... }
86
+ ```
87
+
88
+ ## Error Cases
89
+
90
+ ```rust
91
+ #[test]
92
+ fn rejects_negative_quantity() { ... }
93
+
94
+ #[test]
95
+ fn returns_error_for_invalid_email_format() { ... }
96
+
97
+ #[test]
98
+ fn panics_on_double_initialization() { ... }
99
+
100
+ #[test]
101
+ fn timeout_returns_timeout_error() { ... }
102
+ ```
103
+
104
+ ## Module Organization
105
+
106
+ ```rust
107
+ #[cfg(test)]
108
+ mod tests {
109
+ use super::*;
110
+
111
+ mod parsing {
112
+ use super::*;
113
+
114
+ #[test]
115
+ fn accepts_valid_json() { ... }
116
+
117
+ #[test]
118
+ fn rejects_trailing_comma() { ... }
119
+ }
120
+
121
+ mod validation {
122
+ use super::*;
123
+
124
+ #[test]
125
+ fn requires_name_field() { ... }
126
+
127
+ #[test]
128
+ fn email_must_contain_at_symbol() { ... }
129
+ }
130
+ }
131
+
132
+ // Test output:
133
+ // tests::parsing::accepts_valid_json
134
+ // tests::parsing::rejects_trailing_comma
135
+ // tests::validation::requires_name_field
136
+ ```
137
+
138
+ ## See Also
139
+
140
+ - [test-arrange-act-assert](./test-arrange-act-assert.md) - Test structure
141
+ - [test-cfg-test-module](./test-cfg-test-module.md) - Test module organization
142
+ - [doc-examples-section](./doc-examples-section.md) - Documentation tests
@@ -0,0 +1,168 @@
1
+ # test-doctest-examples
2
+
3
+ > Keep documentation examples as executable doctests
4
+
5
+ ## Why It Matters
6
+
7
+ Doctests are examples in documentation that are automatically tested. They serve dual purposes: demonstrating usage to readers and verifying the examples compile and work. When your API changes, failing doctests catch outdated documentation.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ /// Parses a number from a string.
13
+ ///
14
+ /// Example:
15
+ /// let n = parse("42"); // Not tested!
16
+ /// assert_eq!(n, 42);
17
+ pub fn parse(s: &str) -> i32 {
18
+ s.parse().unwrap()
19
+ }
20
+
21
+ // Documentation can become outdated:
22
+ /// Adds two numbers.
23
+ ///
24
+ /// ```
25
+ /// let sum = add(1, 2, 3); // Wrong number of args - not caught!
26
+ /// ```
27
+ pub fn add(a: i32, b: i32) -> i32 {
28
+ a + b
29
+ }
30
+ ```
31
+
32
+ ## Good
33
+
34
+ ```rust
35
+ /// Parses a number from a string.
36
+ ///
37
+ /// # Examples
38
+ ///
39
+ /// ```
40
+ /// use my_crate::parse;
41
+ ///
42
+ /// let n = parse("42");
43
+ /// assert_eq!(n, 42);
44
+ /// ```
45
+ pub fn parse(s: &str) -> i32 {
46
+ s.parse().unwrap()
47
+ }
48
+
49
+ /// Adds two numbers.
50
+ ///
51
+ /// # Examples
52
+ ///
53
+ /// ```
54
+ /// use my_crate::add;
55
+ ///
56
+ /// let sum = add(1, 2);
57
+ /// assert_eq!(sum, 3);
58
+ /// ```
59
+ pub fn add(a: i32, b: i32) -> i32 {
60
+ a + b
61
+ }
62
+ ```
63
+
64
+ ## Hiding Setup Code
65
+
66
+ ```rust
67
+ /// Processes data from a file.
68
+ ///
69
+ /// # Examples
70
+ ///
71
+ /// ```
72
+ /// # use std::io::Write;
73
+ /// # let mut file = tempfile::NamedTempFile::new().unwrap();
74
+ /// # writeln!(file, "test data").unwrap();
75
+ /// # let path = file.path();
76
+ /// use my_crate::process_file;
77
+ ///
78
+ /// let result = process_file(path)?;
79
+ /// assert!(!result.is_empty());
80
+ /// # Ok::<(), Box<dyn std::error::Error>>(())
81
+ /// ```
82
+ pub fn process_file(path: &Path) -> Result<String, Error> {
83
+ std::fs::read_to_string(path).map_err(Error::from)
84
+ }
85
+ ```
86
+
87
+ ## Showing Error Handling
88
+
89
+ ```rust
90
+ /// Parses and validates an email address.
91
+ ///
92
+ /// # Examples
93
+ ///
94
+ /// ```
95
+ /// use my_crate::Email;
96
+ ///
97
+ /// let email = Email::parse("user@example.com")?;
98
+ /// assert_eq!(email.domain(), "example.com");
99
+ /// # Ok::<(), my_crate::EmailError>(())
100
+ /// ```
101
+ ///
102
+ /// # Errors
103
+ ///
104
+ /// Returns error for invalid format:
105
+ ///
106
+ /// ```
107
+ /// use my_crate::Email;
108
+ ///
109
+ /// assert!(Email::parse("not-an-email").is_err());
110
+ /// ```
111
+ pub fn parse(s: &str) -> Result<Email, EmailError> {
112
+ // ...
113
+ }
114
+ ```
115
+
116
+ ## no_run and ignore
117
+
118
+ ```rust
119
+ /// Starts the server.
120
+ ///
121
+ /// ```no_run
122
+ /// use my_crate::Server;
123
+ ///
124
+ /// // This compiles but doesn't run (would block forever)
125
+ /// Server::new().run();
126
+ /// ```
127
+ pub fn run(&self) { ... }
128
+
129
+ /// Platform-specific example.
130
+ ///
131
+ /// ```ignore
132
+ /// // This might not compile on all platforms
133
+ /// use windows_specific::Feature;
134
+ /// ```
135
+ ```
136
+
137
+ ## compile_fail
138
+
139
+ ```rust
140
+ /// This type is not Clone.
141
+ ///
142
+ /// ```compile_fail
143
+ /// use my_crate::UniqueHandle;
144
+ ///
145
+ /// let a = UniqueHandle::new();
146
+ /// let b = a.clone(); // Error: Clone not implemented
147
+ /// ```
148
+ pub struct UniqueHandle { ... }
149
+ ```
150
+
151
+ ## Running Doctests
152
+
153
+ ```bash
154
+ # Run all tests including doctests
155
+ cargo test
156
+
157
+ # Run only doctests
158
+ cargo test --doc
159
+
160
+ # Run doctests for specific item
161
+ cargo test --doc my_function
162
+ ```
163
+
164
+ ## See Also
165
+
166
+ - [doc-examples-section](./doc-examples-section.md) - Documentation structure
167
+ - [doc-hidden-setup](./doc-hidden-setup.md) - Hiding setup code
168
+ - [doc-question-mark](./doc-question-mark.md) - Error handling in examples
@@ -0,0 +1,151 @@
1
+ # test-fixture-raii
2
+
3
+ > Use RAII pattern (Drop trait) for automatic test cleanup
4
+
5
+ ## Why It Matters
6
+
7
+ Tests often need setup and teardown—creating temp files, starting servers, setting environment variables. Using RAII (Resource Acquisition Is Initialization) with Drop ensures cleanup happens automatically, even if the test panics. This prevents test pollution and resource leaks.
8
+
9
+ ## Bad
10
+
11
+ ```rust
12
+ #[test]
13
+ fn test_with_temp_file() {
14
+ let path = "/tmp/test_file.txt";
15
+ std::fs::write(path, "test data").unwrap();
16
+
17
+ let result = process_file(path);
18
+
19
+ std::fs::remove_file(path).unwrap(); // Might not run if test panics!
20
+ assert!(result.is_ok());
21
+ }
22
+
23
+ #[test]
24
+ fn test_with_env_var() {
25
+ std::env::set_var("MY_VAR", "test_value");
26
+
27
+ let result = read_config();
28
+
29
+ std::env::remove_var("MY_VAR"); // Might not run if test panics!
30
+ assert!(result.is_ok());
31
+ }
32
+ ```
33
+
34
+ ## Good
35
+
36
+ ```rust
37
+ use tempfile::NamedTempFile;
38
+
39
+ #[test]
40
+ fn test_with_temp_file() {
41
+ // Arrange - file deleted automatically when `file` drops
42
+ let file = NamedTempFile::new().unwrap();
43
+ std::fs::write(file.path(), "test data").unwrap();
44
+
45
+ // Act
46
+ let result = process_file(file.path());
47
+
48
+ // Assert - file cleaned up even if assertion panics
49
+ assert!(result.is_ok());
50
+ }
51
+
52
+ // Custom RAII guard for environment variables
53
+ struct EnvGuard {
54
+ key: String,
55
+ original: Option<String>,
56
+ }
57
+
58
+ impl EnvGuard {
59
+ fn set(key: &str, value: &str) -> Self {
60
+ let original = std::env::var(key).ok();
61
+ std::env::set_var(key, value);
62
+ EnvGuard {
63
+ key: key.to_string(),
64
+ original,
65
+ }
66
+ }
67
+ }
68
+
69
+ impl Drop for EnvGuard {
70
+ fn drop(&mut self) {
71
+ match &self.original {
72
+ Some(v) => std::env::set_var(&self.key, v),
73
+ None => std::env::remove_var(&self.key),
74
+ }
75
+ }
76
+ }
77
+
78
+ #[test]
79
+ fn test_with_env_var() {
80
+ let _guard = EnvGuard::set("MY_VAR", "test_value");
81
+
82
+ let result = read_config();
83
+
84
+ assert!(result.is_ok());
85
+ } // MY_VAR automatically restored
86
+ ```
87
+
88
+ ## Common RAII Patterns
89
+
90
+ ```rust
91
+ // Temporary directory
92
+ use tempfile::TempDir;
93
+
94
+ #[test]
95
+ fn test_with_temp_dir() {
96
+ let dir = TempDir::new().unwrap();
97
+ let file_path = dir.path().join("test.txt");
98
+ std::fs::write(&file_path, "data").unwrap();
99
+
100
+ // dir and all contents deleted on drop
101
+ }
102
+
103
+ // Server guard
104
+ struct TestServer {
105
+ handle: std::thread::JoinHandle<()>,
106
+ shutdown: std::sync::mpsc::Sender<()>,
107
+ }
108
+
109
+ impl Drop for TestServer {
110
+ fn drop(&mut self) {
111
+ let _ = self.shutdown.send(());
112
+ // Wait for server to stop
113
+ }
114
+ }
115
+
116
+ // Database transaction rollback
117
+ struct TestTransaction<'a> {
118
+ conn: &'a mut Connection,
119
+ }
120
+
121
+ impl Drop for TestTransaction<'_> {
122
+ fn drop(&mut self) {
123
+ self.conn.execute("ROLLBACK").unwrap();
124
+ }
125
+ }
126
+ ```
127
+
128
+ ## scopeguard Crate
129
+
130
+ ```rust
131
+ use scopeguard::defer;
132
+
133
+ #[test]
134
+ fn test_with_defer() {
135
+ let path = "/tmp/test_file.txt";
136
+ std::fs::write(path, "data").unwrap();
137
+
138
+ defer! {
139
+ std::fs::remove_file(path).ok();
140
+ }
141
+
142
+ // Test logic here
143
+ // File removed when scope exits
144
+ }
145
+ ```
146
+
147
+ ## See Also
148
+
149
+ - [test-arrange-act-assert](./test-arrange-act-assert.md) - Test structure
150
+ - [test-tokio-async](./test-tokio-async.md) - Async test cleanup
151
+ - [test-mock-traits](./test-mock-traits.md) - Mocking with RAII