tdd-workshop-exercises/shopping_cart/README.md
fiatcode 3d94c96ed2 Initial commit: TDD Workshop exercises for participants
- Password Validator kata with starter code and tests
- Shopping Cart kata with starter code and tests
- FizzBuzz reference code (from live demo)
- Setup guide and TDD reference card
- No solutions included (participants implement themselves)
2026-03-10 15:37:58 +07:00

62 lines
1.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Feature B — Shopping Cart
## Your goal
Implement `ShoppingCart` using strict TDD. **Do not write any production code before you have a failing test.**
## Domain rules to implement (in order)
| Step | Feature | Notes |
|------|---------|-------|
| 1 | Empty cart has subtotal 0 and count 0 | The baseline |
| 2 | Add items — subtotal = price × quantity | Multiple items accumulate |
| 3 | Remove item by name | Removing unknown name does nothing |
| 4 | Apply % discount to subtotal | 10% off $50 → $45 |
| 5 | CartItem rejects zero/negative price & quantity | Value Object validation |
| 6 | Bonus: duplicate name / float precision | Design decision — your call |
## The rhythm — repeat for every rule
```
1. Uncomment the next test → run → watch it FAIL (Red)
2. Write the minimum code to make it pass → run → GREEN
3. Refactor if needed → run → still GREEN
4. Move to the next test
```
## Running the tests
```bash
dart pub get
dart test
```
## Files
- `lib/shopping_cart.dart` — your implementation goes here
- `test/shopping_cart_test.dart` — uncomment tests one at a time
## Design hints (don't peek until you're stuck!)
<details>
<summary>Hint for Step 3 — Remove by name</summary>
When you need to remove by name, a `List<CartItem>` forces you to search by name.
A `Map<String, CartItem>` makes lookup O(1) and removal trivial.
Let the test drive you toward the right data structure.
</details>
<details>
<summary>Hint for Step 5 — Value Object</summary>
Validation belongs in `CartItem`'s constructor, not in `ShoppingCart.addItem()`.
If the item can't be created, the cart never sees it.
This is the Value Object pattern: invalid state is unrepresentable.
</details>
<details>
<summary>Hint for the float precision bonus test</summary>
Use `closeTo(expected, delta)` instead of `equals()` for floating point comparisons.
Example: `expect(result, closeTo(0.30, 0.001))`
</details>