moicle 1.1.1 → 1.1.2

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.
@@ -0,0 +1,828 @@
1
+ ---
2
+ name: tdd
3
+ description: Test-Driven Development workflow. Use when doing TDD, writing tests first, or when user says "tdd", "test first", "test driven", "red green refactor".
4
+ ---
5
+
6
+ # Test-Driven Development (TDD) Workflow
7
+
8
+ Red-Green-Refactor cycle for test-first development with quality gates.
9
+
10
+ ## IMPORTANT: Read Architecture First
11
+
12
+ **Before starting TDD, you MUST read the appropriate architecture reference:**
13
+
14
+ ### Global Architecture Files
15
+ ```
16
+ ~/.claude/architecture/
17
+ ├── clean-architecture.md # Core principles for all projects
18
+ ├── flutter-mobile.md # Flutter + Riverpod
19
+ ├── react-frontend.md # React + Vite + TypeScript
20
+ ├── go-backend.md # Go + Gin
21
+ ├── laravel-backend.md # Laravel + PHP
22
+ ├── remix-fullstack.md # Remix fullstack
23
+ └── monorepo.md # Monorepo structure
24
+ ```
25
+
26
+ ### Project-specific (if exists)
27
+ ```
28
+ .claude/architecture/ # Project overrides
29
+ ```
30
+
31
+ **Understand the test patterns and conventions defined in these files.**
32
+
33
+ ## Recommended Agents
34
+
35
+ | Phase | Agent | Purpose |
36
+ |-------|-------|---------|
37
+ | RED | `@test-writer` | Write failing tests first |
38
+ | GREEN | `@react-frontend-dev`, `@go-backend-dev`, `@laravel-backend-dev`, `@flutter-mobile-dev`, `@remix-fullstack-dev` | Minimal implementation |
39
+ | REFACTOR | `@refactor` | Clean up code |
40
+ | REFACTOR | `@code-reviewer` | Review refactored code |
41
+ | REFACTOR | `@perf-optimizer` | Performance optimization |
42
+
43
+ ## Workflow Overview
44
+
45
+ ```
46
+ ┌─────────────────────────────────┐
47
+ │ TDD CYCLE │
48
+ │ │
49
+ │ ┌──────┐ ┌───────┐ ┌─────────┐
50
+ │ │ RED │──▶│ GREEN │──▶│REFACTOR │
51
+ │ └──────┘ └───────┘ └─────────┘
52
+ │ ▲ │
53
+ │ │ │
54
+ │ └─────────────────────────┘
55
+ │ Next requirement
56
+ └─────────────────────────────────┘
57
+
58
+ RED: Write a failing test
59
+ GREEN: Make it pass (minimal code)
60
+ REFACTOR: Improve code (keep tests green)
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Phase 1: RED - Write Failing Test
66
+
67
+ **Goal**: Write a test that fails because the feature doesn't exist yet
68
+
69
+ ### Actions
70
+
71
+ 1. **Read architecture doc** for test conventions:
72
+ - Test file location pattern
73
+ - Test framework/runner
74
+ - Mocking patterns
75
+ - Naming conventions
76
+
77
+ 2. **Understand the requirement**:
78
+ - What should this code do?
79
+ - What are the inputs?
80
+ - What are the expected outputs?
81
+ - What are the edge cases?
82
+
83
+ 3. **Write a single failing test**:
84
+ ```
85
+ // Start with ONE test for ONE behavior
86
+ // Don't write multiple tests at once
87
+ // Follow test patterns from architecture doc
88
+ ```
89
+
90
+ 4. **Run the test and verify it fails**:
91
+ - Test MUST fail for the right reason
92
+ - Failure message should be clear
93
+ - If test passes unexpectedly → investigate
94
+
95
+ ### Test Patterns by Stack
96
+
97
+ #### Flutter
98
+ ```dart
99
+ // test/[feature]_test.dart
100
+ import 'package:flutter_test/flutter_test.dart';
101
+
102
+ void main() {
103
+ group('[Feature]', () {
104
+ test('should [expected behavior]', () {
105
+ // Arrange
106
+
107
+ // Act
108
+
109
+ // Assert
110
+ expect(actual, expected);
111
+ });
112
+ });
113
+ }
114
+ ```
115
+
116
+ #### React/TypeScript
117
+ ```typescript
118
+ // src/[feature].test.ts
119
+ import { describe, it, expect } from 'vitest';
120
+
121
+ describe('[Feature]', () => {
122
+ it('should [expected behavior]', () => {
123
+ // Arrange
124
+
125
+ // Act
126
+
127
+ // Assert
128
+ expect(actual).toBe(expected);
129
+ });
130
+ });
131
+ ```
132
+
133
+ #### Go
134
+ ```go
135
+ // [package]_test.go
136
+ package mypackage
137
+
138
+ import "testing"
139
+
140
+ func Test[Feature](t *testing.T) {
141
+ // Arrange
142
+
143
+ // Act
144
+
145
+ // Assert
146
+ if got != want {
147
+ t.Errorf("got %v, want %v", got, want)
148
+ }
149
+ }
150
+ ```
151
+
152
+ #### Laravel/PHP
153
+ ```php
154
+ // tests/Unit/[Feature]Test.php
155
+ namespace Tests\Unit;
156
+
157
+ use PHPUnit\Framework\TestCase;
158
+
159
+ class FeatureTest extends TestCase
160
+ {
161
+ public function test_should_expected_behavior()
162
+ {
163
+ // Arrange
164
+
165
+ // Act
166
+
167
+ // Assert
168
+ $this->assertEquals($expected, $actual);
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### Output
174
+ ```markdown
175
+ ## RED Phase
176
+
177
+ ### Test Written
178
+ **File**: [path to test file]
179
+ **Test Name**: `test_[behavior]`
180
+
181
+ ### Test Code
182
+ [code snippet]
183
+
184
+ ### Expected Failure
185
+ **Reason**: [why it should fail - feature not implemented]
186
+
187
+ ### Test Run Result
188
+ ```bash
189
+ [test command from architecture doc]
190
+ [failure output]
191
+ ```
192
+ ```
193
+
194
+ ### Gate
195
+ - [ ] Architecture doc read for test patterns
196
+ - [ ] Single test written (AAA pattern)
197
+ - [ ] Test follows architecture conventions
198
+ - [ ] Test fails for the RIGHT reason
199
+ - [ ] Failure message is clear
200
+
201
+ ---
202
+
203
+ ## Phase 2: GREEN - Make It Pass
204
+
205
+ **Goal**: Write the minimal code to make the test pass (no more, no less)
206
+
207
+ ### Principles
208
+
209
+ 1. **Minimal code** - Write only enough to pass the test
210
+ 2. **No gold-plating** - Don't add features not tested
211
+ 3. **Simple first** - Hardcode if needed, refactor later
212
+ 4. **Follow architecture** - Respect layer boundaries from doc
213
+
214
+ ### Actions
215
+
216
+ 1. **Read architecture doc** for implementation patterns:
217
+ - Where to create the file
218
+ - Naming conventions
219
+ - Layer boundaries
220
+ - Dependency injection patterns
221
+
222
+ 2. **Write minimal implementation**:
223
+ ```
224
+ // Quick and dirty is OK at this stage
225
+ // Even hardcoded values are fine if test passes
226
+ // Focus on making test green, not perfect code
227
+ ```
228
+
229
+ 3. **Run the test**:
230
+ ```bash
231
+ # Use test command from architecture doc
232
+ flutter test # Flutter
233
+ go test ./... # Go
234
+ bun test # React/Remix
235
+ php artisan test # Laravel
236
+ ```
237
+
238
+ 4. **Verify test passes**:
239
+ - Test goes from RED → GREEN
240
+ - No other tests broken
241
+ - All tests in suite still pass
242
+
243
+ ### Implementation Examples
244
+
245
+ #### Start Simple
246
+ ```typescript
247
+ // ❌ Don't write this first:
248
+ function calculate(a: number, b: number, operation: string): number {
249
+ switch(operation) {
250
+ case 'add': return a + b;
251
+ case 'subtract': return a - b;
252
+ case 'multiply': return a * b;
253
+ default: throw new Error('Invalid operation');
254
+ }
255
+ }
256
+
257
+ // ✅ Do write this first (if test only checks addition):
258
+ function calculate(a: number, b: number): number {
259
+ return a + b; // Just make test pass
260
+ }
261
+ ```
262
+
263
+ ### Output
264
+ ```markdown
265
+ ## GREEN Phase
266
+
267
+ ### Implementation
268
+ **File**: [path to implementation file]
269
+ **Architecture Reference**: [layer from doc]
270
+
271
+ ### Code Written
272
+ [minimal code snippet]
273
+
274
+ ### Test Run Result
275
+ ```bash
276
+ [test command]
277
+ ✓ All tests pass
278
+ ```
279
+
280
+ ### Verification
281
+ - [ ] Target test passes
282
+ - [ ] No existing tests broken
283
+ - [ ] Code follows architecture doc structure
284
+ ```
285
+
286
+ ### Gate
287
+ - [ ] Test passes (RED → GREEN)
288
+ - [ ] Minimal code written (no extras)
289
+ - [ ] Architecture boundaries respected
290
+ - [ ] All tests in suite pass
291
+
292
+ ---
293
+
294
+ ## Phase 3: REFACTOR - Improve Code
295
+
296
+ **Goal**: Clean up code while keeping all tests green
297
+
298
+ ### Principles
299
+
300
+ 1. **Keep tests green** - Run tests after each refactor
301
+ 2. **Small steps** - One refactor at a time
302
+ 3. **Follow architecture** - Improve architecture compliance
303
+ 4. **No new functionality** - Tests stay same
304
+
305
+ ### Refactoring Checklist
306
+
307
+ #### Code Quality
308
+ - [ ] Remove duplication (DRY)
309
+ - [ ] Improve naming (clear, descriptive)
310
+ - [ ] Extract methods/functions (SRP)
311
+ - [ ] Simplify logic (reduce complexity)
312
+ - [ ] Remove magic numbers/strings
313
+
314
+ #### Architecture Compliance
315
+ - [ ] Follow patterns from architecture doc
316
+ - [ ] Respect layer boundaries
317
+ - [ ] Use dependency injection (if in doc)
318
+ - [ ] Follow naming conventions from doc
319
+ - [ ] Match directory structure from doc
320
+
321
+ #### Test Quality
322
+ - [ ] Remove test duplication
323
+ - [ ] Improve test names
324
+ - [ ] Add test helpers (if needed)
325
+ - [ ] Follow test patterns from doc
326
+
327
+ ### Actions
328
+
329
+ 1. **Read architecture doc** for refactoring patterns
330
+
331
+ 2. **Identify refactoring opportunities**:
332
+ ```
333
+ - Duplicated code?
334
+ - Poor names?
335
+ - Complex logic?
336
+ - Architecture violations?
337
+ - Performance issues?
338
+ ```
339
+
340
+ 3. **Refactor in small steps**:
341
+ ```
342
+ 1. Make one small change
343
+ 2. Run tests → must stay GREEN
344
+ 3. Commit (optional)
345
+ 4. Repeat
346
+ ```
347
+
348
+ 4. **Run full test suite after each change**:
349
+ ```bash
350
+ # After EVERY refactor
351
+ flutter test # Flutter
352
+ go test ./... # Go
353
+ bun test # React/Remix
354
+ php artisan test # Laravel
355
+ ```
356
+
357
+ ### Refactoring Patterns
358
+
359
+ #### Extract Method
360
+ ```typescript
361
+ // Before
362
+ function process(data: Data): Result {
363
+ const cleaned = data.trim().toLowerCase();
364
+ const validated = cleaned.length > 0 && cleaned.length < 100;
365
+ if (!validated) throw new Error('Invalid');
366
+ return { value: cleaned };
367
+ }
368
+
369
+ // After
370
+ function process(data: Data): Result {
371
+ const cleaned = cleanData(data);
372
+ validateData(cleaned);
373
+ return createResult(cleaned);
374
+ }
375
+
376
+ function cleanData(data: Data): string {
377
+ return data.trim().toLowerCase();
378
+ }
379
+
380
+ function validateData(data: string): void {
381
+ if (data.length === 0 || data.length >= 100) {
382
+ throw new Error('Invalid');
383
+ }
384
+ }
385
+
386
+ function createResult(value: string): Result {
387
+ return { value };
388
+ }
389
+ ```
390
+
391
+ #### Remove Duplication
392
+ ```go
393
+ // Before
394
+ func Add(a, b int) int {
395
+ if a < 0 { return 0 }
396
+ if b < 0 { return 0 }
397
+ return a + b
398
+ }
399
+
400
+ func Subtract(a, b int) int {
401
+ if a < 0 { return 0 }
402
+ if b < 0 { return 0 }
403
+ return a - b
404
+ }
405
+
406
+ // After
407
+ func Add(a, b int) int {
408
+ return calculate(a, b, func(x, y int) int { return x + y })
409
+ }
410
+
411
+ func Subtract(a, b int) int {
412
+ return calculate(a, b, func(x, y int) int { return x - y })
413
+ }
414
+
415
+ func calculate(a, b int, op func(int, int) int) int {
416
+ if a < 0 || b < 0 { return 0 }
417
+ return op(a, b)
418
+ }
419
+ ```
420
+
421
+ #### Improve Architecture Compliance
422
+ ```typescript
423
+ // Before (violates layer separation)
424
+ // ui/UserProfile.tsx
425
+ function UserProfile() {
426
+ const user = fetch('/api/users/1').then(r => r.json()); // ❌ Direct API call
427
+ return <div>{user.name}</div>;
428
+ }
429
+
430
+ // After (follows architecture doc)
431
+ // ui/UserProfile.tsx
432
+ function UserProfile() {
433
+ const user = useUserRepository().getUser(1); // ✅ Uses repository layer
434
+ return <div>{user.name}</div>;
435
+ }
436
+
437
+ // data/repositories/UserRepository.ts
438
+ export function useUserRepository() {
439
+ return {
440
+ getUser: (id: number) => fetch(`/api/users/${id}`).then(r => r.json())
441
+ };
442
+ }
443
+ ```
444
+
445
+ ### Output
446
+ ```markdown
447
+ ## REFACTOR Phase
448
+
449
+ ### Refactorings Applied
450
+
451
+ 1. **[Refactoring Name]**
452
+ - Before: [description/code]
453
+ - After: [description/code]
454
+ - Reason: [why this improves code]
455
+ - Architecture compliance: [how it follows doc]
456
+
457
+ 2. **[Refactoring Name]**
458
+ - Before: [description/code]
459
+ - After: [description/code]
460
+ - Reason: [why this improves code]
461
+
462
+ ### Test Run After Each Refactor
463
+ ```bash
464
+ [test command]
465
+ ✓ All tests still pass
466
+ ```
467
+
468
+ ### Architecture Compliance
469
+ - [ ] Follows patterns from [architecture doc]
470
+ - [ ] Layer boundaries respected
471
+ - [ ] Naming conventions followed
472
+ ```
473
+
474
+ ### Gate
475
+ - [ ] Code improved (cleaner, clearer)
476
+ - [ ] Architecture compliance improved
477
+ - [ ] All tests still pass (GREEN)
478
+ - [ ] No new functionality added
479
+ - [ ] Committed (optional)
480
+
481
+ ---
482
+
483
+ ## TDD Best Practices
484
+
485
+ ### Test Quality
486
+
487
+ #### Good Test Names
488
+ ```
489
+ ✅ test_should_return_empty_list_when_no_items_found
490
+ ✅ test_should_throw_error_when_invalid_email
491
+ ✅ test_should_calculate_total_with_tax
492
+
493
+ ❌ test_user
494
+ ❌ test1
495
+ ❌ test_it_works
496
+ ```
497
+
498
+ #### AAA Pattern (Arrange-Act-Assert)
499
+ ```typescript
500
+ test('should calculate discount', () => {
501
+ // Arrange - Setup
502
+ const price = 100;
503
+ const discountPercent = 10;
504
+
505
+ // Act - Execute
506
+ const result = calculateDiscount(price, discountPercent);
507
+
508
+ // Assert - Verify
509
+ expect(result).toBe(90);
510
+ });
511
+ ```
512
+
513
+ #### Test One Thing
514
+ ```typescript
515
+ // ❌ Testing multiple things
516
+ test('user service', () => {
517
+ expect(createUser()).toBeDefined();
518
+ expect(updateUser()).toBeTruthy();
519
+ expect(deleteUser()).toBeNull();
520
+ });
521
+
522
+ // ✅ One test per behavior
523
+ test('should create user with valid data', () => {
524
+ expect(createUser(validData)).toBeDefined();
525
+ });
526
+
527
+ test('should update existing user', () => {
528
+ expect(updateUser(user, newData)).toBeTruthy();
529
+ });
530
+
531
+ test('should delete user and return null', () => {
532
+ expect(deleteUser(userId)).toBeNull();
533
+ });
534
+ ```
535
+
536
+ ### TDD Discipline
537
+
538
+ #### Write Test First
539
+ ```
540
+ ❌ Wrong order:
541
+ 1. Write code
542
+ 2. Write test
543
+ 3. Run test
544
+
545
+ ✅ TDD order:
546
+ 1. Write test (RED)
547
+ 2. Write code (GREEN)
548
+ 3. Refactor (GREEN)
549
+ ```
550
+
551
+ #### Smallest Steps
552
+ ```
553
+ ✅ Start with simplest test:
554
+ test('should return empty array when no input', () => {
555
+ expect(process([])).toEqual([]);
556
+ });
557
+
558
+ Then build up:
559
+ test('should process single item', () => {
560
+ expect(process([1])).toEqual([2]);
561
+ });
562
+
563
+ test('should process multiple items', () => {
564
+ expect(process([1, 2, 3])).toEqual([2, 4, 6]);
565
+ });
566
+ ```
567
+
568
+ #### Run Tests Frequently
569
+ ```bash
570
+ # After writing test (should fail)
571
+ bun test
572
+
573
+ # After writing code (should pass)
574
+ bun test
575
+
576
+ # After refactoring (should still pass)
577
+ bun test
578
+
579
+ # Run tests constantly!
580
+ ```
581
+
582
+ ### Common TDD Mistakes
583
+
584
+ #### ❌ Writing Multiple Tests Before Code
585
+ ```typescript
586
+ // Don't do this:
587
+ describe('Calculator', () => {
588
+ test('should add', () => {});
589
+ test('should subtract', () => {});
590
+ test('should multiply', () => {});
591
+ test('should divide', () => {});
592
+ });
593
+ // Then implement all at once
594
+
595
+ // Do this instead: One test at a time
596
+ // Write test for add → implement add → refactor
597
+ // Write test for subtract → implement subtract → refactor
598
+ // ...
599
+ ```
600
+
601
+ #### ❌ Skipping RED Phase
602
+ ```
603
+ Don't assume test will fail - VERIFY IT!
604
+
605
+ 1. Write test
606
+ 2. Run test → see it FAIL
607
+ 3. Then write code
608
+
609
+ If test passes without implementation:
610
+ - Test might be wrong
611
+ - Feature might already exist
612
+ - False positive
613
+ ```
614
+
615
+ #### ❌ Over-implementing in GREEN Phase
616
+ ```typescript
617
+ // ❌ Test only checks addition, but you implement:
618
+ function calculate(a, b, operation) {
619
+ switch(operation) {
620
+ case 'add': return a + b;
621
+ case 'subtract': return a - b; // Not tested!
622
+ case 'multiply': return a * b; // Not tested!
623
+ }
624
+ }
625
+
626
+ // ✅ Only implement what test needs:
627
+ function calculate(a, b) {
628
+ return a + b; // Just this
629
+ }
630
+ ```
631
+
632
+ #### ❌ Refactoring Without Running Tests
633
+ ```
634
+ Every refactor MUST be followed by test run:
635
+
636
+ 1. Extract method → run tests
637
+ 2. Rename variable → run tests
638
+ 3. Simplify logic → run tests
639
+
640
+ Never skip this step!
641
+ ```
642
+
643
+ ---
644
+
645
+ ## Quick Reference
646
+
647
+ ### Architecture Docs
648
+ | Stack | Doc |
649
+ |-------|-----|
650
+ | All | `clean-architecture.md` |
651
+ | Flutter | `flutter-mobile.md` |
652
+ | React | `react-frontend.md` |
653
+ | Go | `go-backend.md` |
654
+ | Laravel | `laravel-backend.md` |
655
+ | Remix | `remix-fullstack.md` |
656
+ | Monorepo | `monorepo.md` |
657
+
658
+ ### TDD Cycle Summary
659
+ | Phase | Key Actions | Gate |
660
+ |-------|-------------|------|
661
+ | **RED** | Write failing test | Test fails (right reason) |
662
+ | **GREEN** | Minimal code to pass | Test passes |
663
+ | **REFACTOR** | Clean code | Tests still pass |
664
+
665
+ ### Test Commands by Stack
666
+ ```bash
667
+ # Flutter
668
+ flutter test
669
+ flutter test --coverage
670
+
671
+ # Go
672
+ go test ./...
673
+ go test -v ./...
674
+ go test -cover ./...
675
+
676
+ # React/Remix
677
+ bun test
678
+ bun test --coverage
679
+ bun test --watch
680
+
681
+ # Laravel
682
+ php artisan test
683
+ php artisan test --coverage
684
+ php artisan test --parallel
685
+ ```
686
+
687
+ ### Test File Locations
688
+ | Stack | Location Pattern |
689
+ |-------|------------------|
690
+ | Flutter | `test/[feature]_test.dart` |
691
+ | React | `src/[feature].test.ts` |
692
+ | Go | `[package]_test.go` (same dir) |
693
+ | Laravel | `tests/Unit/[Feature]Test.php` |
694
+ | Remix | `app/[feature].test.ts` |
695
+
696
+ ### TDD Mantras
697
+
698
+ ```
699
+ 🔴 RED: "Write a test that fails"
700
+ 🟢 GREEN: "Make it work"
701
+ 🔵 REFACTOR: "Make it right"
702
+
703
+ "Test first, code second"
704
+ "One test, one behavior"
705
+ "Minimal code, maximum coverage"
706
+ "Refactor fearlessly, tests protect you"
707
+ ```
708
+
709
+ ### When to Loop Back
710
+
711
+ - After REFACTOR → Return to RED for next behavior
712
+ - Test won't fail → Fix the test (RED)
713
+ - Test won't pass → Fix the code (GREEN)
714
+ - Code is messy → Refactor (REFACTOR)
715
+
716
+ ### Success Criteria
717
+
718
+ TDD session complete when:
719
+ 1. All behaviors have tests (RED → GREEN)
720
+ 2. Code is clean (REFACTOR)
721
+ 3. All tests pass
722
+ 4. Architecture compliance verified
723
+ 5. No TODO/hardcoded values left
724
+
725
+ ---
726
+
727
+ ## TDD Workflow Example
728
+
729
+ ### Example: Implementing a Shopping Cart
730
+
731
+ #### Cycle 1: Add item
732
+
733
+ **RED**
734
+ ```typescript
735
+ test('should add item to empty cart', () => {
736
+ const cart = new ShoppingCart();
737
+ cart.addItem({ id: 1, name: 'Book', price: 10 });
738
+ expect(cart.items).toHaveLength(1);
739
+ });
740
+ // Run: ❌ FAIL - ShoppingCart not defined
741
+ ```
742
+
743
+ **GREEN**
744
+ ```typescript
745
+ class ShoppingCart {
746
+ items: Item[] = [];
747
+ addItem(item: Item) {
748
+ this.items.push(item);
749
+ }
750
+ }
751
+ // Run: ✅ PASS
752
+ ```
753
+
754
+ **REFACTOR**
755
+ ```typescript
756
+ // Code is clean, nothing to refactor
757
+ // Run: ✅ PASS
758
+ ```
759
+
760
+ #### Cycle 2: Calculate total
761
+
762
+ **RED**
763
+ ```typescript
764
+ test('should calculate total of items', () => {
765
+ const cart = new ShoppingCart();
766
+ cart.addItem({ id: 1, name: 'Book', price: 10 });
767
+ cart.addItem({ id: 2, name: 'Pen', price: 5 });
768
+ expect(cart.getTotal()).toBe(15);
769
+ });
770
+ // Run: ❌ FAIL - getTotal is not a function
771
+ ```
772
+
773
+ **GREEN**
774
+ ```typescript
775
+ class ShoppingCart {
776
+ items: Item[] = [];
777
+
778
+ addItem(item: Item) {
779
+ this.items.push(item);
780
+ }
781
+
782
+ getTotal() {
783
+ return this.items.reduce((sum, item) => sum + item.price, 0);
784
+ }
785
+ }
786
+ // Run: ✅ PASS
787
+ ```
788
+
789
+ **REFACTOR**
790
+ ```typescript
791
+ // Extract calculation logic
792
+ class ShoppingCart {
793
+ items: Item[] = [];
794
+
795
+ addItem(item: Item) {
796
+ this.items.push(item);
797
+ }
798
+
799
+ getTotal() {
800
+ return this.calculateTotal(this.items);
801
+ }
802
+
803
+ private calculateTotal(items: Item[]): number {
804
+ return items.reduce((sum, item) => sum + item.price, 0);
805
+ }
806
+ }
807
+ // Run: ✅ PASS
808
+ ```
809
+
810
+ #### Cycle 3: Continue for each behavior...
811
+
812
+ ---
813
+
814
+ ## Resources
815
+
816
+ ### Learn More
817
+ - Kent Beck's "Test Driven Development: By Example"
818
+ - Martin Fowler's "Refactoring"
819
+ - Uncle Bob's TDD tutorials
820
+
821
+ ### Test Frameworks
822
+ | Stack | Framework |
823
+ |-------|-----------|
824
+ | Flutter | flutter_test, mockito |
825
+ | React | Vitest, Jest, Testing Library |
826
+ | Go | testing (stdlib), testify |
827
+ | Laravel | PHPUnit, Pest |
828
+ | Remix | Vitest, Playwright |