Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ### Test Driven Development (TDD)
- #### Definitions
- | Term | Meaning |
- | ----------------------- | ----------------------------------------------------------------------- |
- | **Red** | Test compiles, runs, and fails on an assertion |
- | **Green** | Test passes after implementation changes |
- | **Refactor** | Code cleanup while tests remain green |
- | **Signature change** | Adding function parameters, struct fields, enum variants, or variant fields |
- | **Implementation change** | Modifying function or method bodies |
- | **Observable behavior** | Outputs, return values, or side effects visible through the public API |
- #### Execution Steps
- 1. Write a test calling the desired public API.
- 2. Resolve compilation errors by signature changes only. No implementation changes.
- 3. Run the test. Confirm assertion failure.
- 4. Write minimal implementation code.
- 5. Run the test. Confirm it passes.
- 6. Refactor. Confirm tests remain green.
- #### Phase Validation Criteria
- ##### Red Phase
- Run `cargo test`. All conditions must be true:
- | Condition | Validation |
- | ----------------- | --------------------------------------------------- |
- | Compiles | No compilation errors |
- | Runs | Test executes without panic before assertions |
- | Fails | Assertion fails (e.g., `assert_eq!` mismatch) |
- | Signatures only | Only function signatures, struct fields, enum variants changed |
- | Tests behavior | Assertion checks outputs, not internal state |
- If any condition is false, fix the test or signatures before proceeding.
- | Symptom | Diagnosis | Action |
- | ------------------- | -------------------------------------- | ----------------------------- |
- | Compilation error | Missing signature elements | Add parameters, fields, variants |
- | Panic before assert | Missing setup or invalid state | Fix test setup |
- | Test passes | Behavior already exists or test is bad | Verify test logic |
- | Implementation edited | Function body modified | Revert implementation changes |
- ##### Green Phase
- Run `cargo test`. All conditions must be true:
- | Condition | Validation |
- | ---------------------- | ----------------------------------- |
- | Test passes | Assertion succeeds |
- | Implementation minimal | No code beyond what test requires |
- | Test unchanged | Test file has no modifications |
- Modify implementation to pass the test. Keep the test unchanged.
- ##### Refactor Phase
- Run `cargo test` after each change. Condition: all tests pass.
- #### Example
- Goal: Watcher emits one event per file during rapid saves (currently emits multiple).
- ##### Red
- Step 1: Write test calling desired API.
- ```rust
- #[tokio::test]
- async fn test_rapid_saves_produce_single_event() {
- // Arrange
- let config = WatcherConfiguration { debounce_milliseconds: 100 };
- let (mut watcher, mut rx) = create_watcher(config).unwrap();
- watch_path(&mut watcher, &temp_dir).unwrap();
- // Act: trigger multiple filesystem writes
- for i in 0..10 {
- write_file(&path, format!("v{}", i));
- }
- sleep(Duration::from_millis(200)).await;
- // Assert: expect 1 event (will fail when impl added)
- let events: Vec<_> = collect_all(&mut rx);
- assert_eq!(events.len(), 1);
- }
- ```
- Step 2: Resolve compilation errors (signature changes only).
- ```rust
- pub struct WatcherConfiguration {
- pub debounce_milliseconds: u64,
- }
- pub fn create_watcher(config: WatcherConfiguration) -> Result<(Watcher, Receiver)> {
- todo!() // unchanged body
- }
- ```
- Step 3: Run test.
- Run: `cargo test test_rapid_saves` → panics on `todo!()` before assertion → Fix: replace `todo!()` with minimal non-panicking stub → Run again → fails with `assertion failed: 1 != 10` → Red confirmed.
- ##### Green
- Implement deduplication using `config.debounce_milliseconds` in `create_watcher`. Run: `cargo test test_rapid_saves` → passes → Green confirmed.
- ##### Refactor
- Clean up. Run: `cargo test` → all pass → Refactor complete.
Advertisement
Add Comment
Please, Sign In to add comment