You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(test): prefer cfg_attr(ignore) over cfg for conditional test skipping (#369)
* refactor(test): replace `#[cfg]` with `#[cfg_attr(..., ignore)]` for test skipping
Use `#[cfg_attr(..., ignore = "reason")]` instead of `#[cfg(not(...))]` on
tests that can still compile under the skipped condition. This keeps the
tests compiled on all configurations, catching type errors early while
only skipping execution at runtime.
Changes:
- cli_errors::fs_errors: replace `#[cfg(not(pdu_test_skip_fs_errors))]`
with `#[cfg_attr(pdu_test_skip_fs_errors, ignore)]`; remove the same
gate from its imports and helper function
- test_remove_overlapping_paths: remove `#[cfg(unix)]` from module
declaration; add `#[cfg_attr(not(unix), ignore)]` to each test
- Add "Conditional Test Skipping" section to CONTRIBUTING.md
- Add guideline bullet to AI instruction templates
https://claude.ai/code/session_0184ceZayyCwvK7PEF9iB7K3
* refactor(test): address review feedback on ignore attributes
- Change ignore reason to "only one path separator style is tested"
- Reorder attributes: place #[cfg_attr(..., ignore)] below #[test]
- Revert hint message in fs_errors back to "skip"
- Soften "Always" to "Prefer" for reason strings in CONTRIBUTING.md
- Rephrase CONTRIBUTING.md to mention tests are "still compiled"
https://claude.ai/code/session_0184ceZayyCwvK7PEF9iB7K3
* docs(guide/dev): use generic `pdu_test_skip_*` name in example
https://claude.ai/code/session_0184ceZayyCwvK7PEF9iB7K3
---------
Co-authored-by: Claude <noreply@anthropic.com>
- Error types: only derive `Display` and `Error` from `derive_more` when each is actually needed — not all displayable types are errors
16
16
- Minimize `unwrap()` in non-test code — use proper error handling
17
+
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` to skip tests — use `#[cfg]` on tests only when the code cannot compile under the condition (e.g., references types/functions that don't exist on other platforms)
- Run `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh` to validate changes. If a test fails with a hint about `RUSTFLAGS` and `--cfg pdu_test_skip_*`, follow the hint and rerun with the suggested flags.
19
20
-**ALWAYS run the full test suite** (`FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh`) before committing, regardless of how trivial the change seems — this includes documentation-only changes, comment edits, config changes, and refactors. The test suite checks formatting, linting, building, tests, and docs across multiple feature combinations; any type of change can break any of these checks.
- Error types: only derive `Display` and `Error` from `derive_more` when each is actually needed — not all displayable types are errors
16
16
- Minimize `unwrap()` in non-test code — use proper error handling
17
+
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` to skip tests — use `#[cfg]` on tests only when the code cannot compile under the condition (e.g., references types/functions that don't exist on other platforms)
- Run `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh` to validate changes. If a test fails with a hint about `RUSTFLAGS` and `--cfg pdu_test_skip_*`, follow the hint and rerun with the suggested flags.
19
20
-**ALWAYS run the full test suite** (`FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh`) before committing, regardless of how trivial the change seems — this includes documentation-only changes, comment edits, config changes, and refactors. The test suite checks formatting, linting, building, tests, and docs across multiple feature combinations; any type of change can break any of these checks.
- Error types: only derive `Display` and `Error` from `derive_more` when each is actually needed — not all displayable types are errors
16
16
- Minimize `unwrap()` in non-test code — use proper error handling
17
+
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` to skip tests — use `#[cfg]` on tests only when the code cannot compile under the condition (e.g., references types/functions that don't exist on other platforms)
- Run `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh` to validate changes. If a test fails with a hint about `RUSTFLAGS` and `--cfg pdu_test_skip_*`, follow the hint and rerun with the suggested flags.
19
20
-**ALWAYS run the full test suite** (`FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh`) before committing, regardless of how trivial the change seems — this includes documentation-only changes, comment edits, config changes, and refactors. The test suite checks formatting, linting, building, tests, and docs across multiple feature combinations; any type of change can break any of these checks.
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+30Lines changed: 30 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -213,6 +213,36 @@ pub enum RuntimeError {
213
213
}
214
214
```
215
215
216
+
### Conditional Test Skipping: `#[cfg]` vs `#[cfg_attr(..., ignore)]`
217
+
218
+
When a test cannot run under certain conditions (e.g., wrong platform, running as root), prefer `#[cfg_attr(..., ignore)]` over `#[cfg(...)]` to skip it. This way the test is still compiled on all configurations — catching type errors and regressions early — but simply skipped at runtime.
219
+
220
+
Use `#[cfg]` on tests **only** when the code cannot compile under the condition — for example, when the test references types, functions, or trait methods that are gated behind `#[cfg]` and do not exist on other platforms or feature sets.
221
+
222
+
Prefer including a reason string in the `ignore` attribute to explain why the test is skipped.
223
+
224
+
```rust
225
+
// Good — test compiles everywhere, skipped at runtime on non-unix
226
+
#[test]
227
+
#[cfg_attr(not(unix), ignore ="only one path separator style is tested")]
228
+
fnunix_path_logic() { /* uses hardcoded unix paths but no unix-only types */ }
229
+
230
+
// Good — test CANNOT compile on non-unix (uses unix-only types)
231
+
#[cfg(unix)]
232
+
#[test]
233
+
fnblock_size() { /* uses GetBlockSize which only exists on unix */ }
234
+
235
+
// Good — test compiles with the flag, skipped at runtime
236
+
#[test]
237
+
#[cfg_attr(pdu_test_skip_some_test, ignore ="pdu_test_skip_some_test is set")]
238
+
fnsome_test() { /* ... */ }
239
+
240
+
// Bad — excludes the test from compilation entirely when it could still compile
241
+
#[cfg(not(pdu_test_skip_some_test))]
242
+
#[test]
243
+
fnsome_test() { /* ... */ }
244
+
```
245
+
216
246
### Using `pipe-trait`
217
247
218
248
This codebase uses the [`pipe-trait`](https://docs.rs/pipe-trait) crate extensively. The `Pipe` trait enables method-chaining through unary functions, keeping code in a natural left-to-right reading order. Import it as `use pipe_trait::Pipe;`.
- Error types: only derive `Display` and `Error` from `derive_more` when each is actually needed — not all displayable types are errors
16
16
- Minimize `unwrap()` in non-test code — use proper error handling
17
+
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` to skip tests — use `#[cfg]` on tests only when the code cannot compile under the condition (e.g., references types/functions that don't exist on other platforms)
- Run `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh` to validate changes. If a test fails with a hint about `RUSTFLAGS` and `--cfg pdu_test_skip_*`, follow the hint and rerun with the suggested flags.
19
20
-**ALWAYS run the full test suite** (`FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh`) before committing, regardless of how trivial the change seems — this includes documentation-only changes, comment edits, config changes, and refactors. The test suite checks formatting, linting, building, tests, and docs across multiple feature combinations; any type of change can break any of these checks.
0 commit comments