Initial commit: Complete TDD workshop materials
- Workshop documentation (WORKSHOP_PLAN, FACILITATOR_GUIDE, etc.) - FizzBuzz kata with demo script (git history to be recreated) - Password Validator kata with demo script and solution - Shopping Cart kata with demo script and solution - Setup guide and TDD reference card for participants
This commit is contained in:
commit
c3355063f2
26 changed files with 4725 additions and 0 deletions
733
docs/fizzbuzz-git-history.patch
Normal file
733
docs/fizzbuzz-git-history.patch
Normal file
|
|
@ -0,0 +1,733 @@
|
|||
From 71fbd5a6f30e2c7f6e5e49807cae18274bc44506 Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:44:55 +0700
|
||||
Subject: [PATCH 01/12] Initial setup: Create FizzBuzz kata structure
|
||||
|
||||
---
|
||||
lib/fizzbuzz.dart | 1 +
|
||||
pubspec.yaml | 9 +++++++++
|
||||
test/fizzbuzz_test.dart | 6 ++++++
|
||||
3 files changed, 16 insertions(+)
|
||||
create mode 100644 lib/fizzbuzz.dart
|
||||
create mode 100644 pubspec.yaml
|
||||
create mode 100644 test/fizzbuzz_test.dart
|
||||
|
||||
diff --git a/lib/fizzbuzz.dart b/lib/fizzbuzz.dart
|
||||
new file mode 100644
|
||||
index 0000000..8c2215b
|
||||
--- /dev/null
|
||||
+++ b/lib/fizzbuzz.dart
|
||||
@@ -0,0 +1 @@
|
||||
+// FizzBuzz kata - empty implementation file
|
||||
diff --git a/pubspec.yaml b/pubspec.yaml
|
||||
new file mode 100644
|
||||
index 0000000..5e6dee3
|
||||
--- /dev/null
|
||||
+++ b/pubspec.yaml
|
||||
@@ -0,0 +1,9 @@
|
||||
+name: fizzbuzz
|
||||
+description: FizzBuzz kata for TDD workshop live demonstration
|
||||
+version: 1.0.0
|
||||
+
|
||||
+environment:
|
||||
+ sdk: ^3.0.0
|
||||
+
|
||||
+dev_dependencies:
|
||||
+ test: ^1.24.0
|
||||
diff --git a/test/fizzbuzz_test.dart b/test/fizzbuzz_test.dart
|
||||
new file mode 100644
|
||||
index 0000000..efeefe0
|
||||
--- /dev/null
|
||||
+++ b/test/fizzbuzz_test.dart
|
||||
@@ -0,0 +1,6 @@
|
||||
+import 'package:test/test.dart';
|
||||
+import '../lib/fizzbuzz.dart';
|
||||
+
|
||||
+void main() {
|
||||
+ // Tests will be added step by step during the demo
|
||||
+}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 39357bebb6432b14ae45942da92de4804e747d02 Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:45:29 +0700
|
||||
Subject: [PATCH 02/12] RED: Add test for input 1 returning "1"
|
||||
|
||||
---
|
||||
test/fizzbuzz_test.dart | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/fizzbuzz_test.dart b/test/fizzbuzz_test.dart
|
||||
index efeefe0..27e4266 100644
|
||||
--- a/test/fizzbuzz_test.dart
|
||||
+++ b/test/fizzbuzz_test.dart
|
||||
@@ -2,5 +2,7 @@ import 'package:test/test.dart';
|
||||
import '../lib/fizzbuzz.dart';
|
||||
|
||||
void main() {
|
||||
- // Tests will be added step by step during the demo
|
||||
+ test('returns "1" for 1', () {
|
||||
+ expect(fizzBuzz(1), equals('1'));
|
||||
+ });
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 334c5b510611a36ccd7b5db02b3a7ad1e3ae0863 Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:45:41 +0700
|
||||
Subject: [PATCH 03/12] GREEN: Return "1" (hardcoded minimal solution)
|
||||
|
||||
---
|
||||
lib/fizzbuzz.dart | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/fizzbuzz.dart b/lib/fizzbuzz.dart
|
||||
index 8c2215b..0178355 100644
|
||||
--- a/lib/fizzbuzz.dart
|
||||
+++ b/lib/fizzbuzz.dart
|
||||
@@ -1 +1,5 @@
|
||||
-// FizzBuzz kata - empty implementation file
|
||||
+// FizzBuzz kata - TDD progression
|
||||
+
|
||||
+String fizzBuzz(int n) {
|
||||
+ return '1';
|
||||
+}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From e0ae220dea66522d1726e342820f7e2d61edaafb Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:45:51 +0700
|
||||
Subject: [PATCH 04/12] RED: Add test for input 2 returning "2"
|
||||
|
||||
---
|
||||
test/fizzbuzz_test.dart | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/test/fizzbuzz_test.dart b/test/fizzbuzz_test.dart
|
||||
index 27e4266..7b517ae 100644
|
||||
--- a/test/fizzbuzz_test.dart
|
||||
+++ b/test/fizzbuzz_test.dart
|
||||
@@ -5,4 +5,8 @@ void main() {
|
||||
test('returns "1" for 1', () {
|
||||
expect(fizzBuzz(1), equals('1'));
|
||||
});
|
||||
+
|
||||
+ test('returns "2" for 2', () {
|
||||
+ expect(fizzBuzz(2), equals('2'));
|
||||
+ });
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 4c0471c02ac4bfef56517044519c65478ecd3dbd Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:46:03 +0700
|
||||
Subject: [PATCH 05/12] GREEN: Return string representation of number
|
||||
|
||||
---
|
||||
lib/fizzbuzz.dart | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/fizzbuzz.dart b/lib/fizzbuzz.dart
|
||||
index 0178355..4da1cfa 100644
|
||||
--- a/lib/fizzbuzz.dart
|
||||
+++ b/lib/fizzbuzz.dart
|
||||
@@ -1,5 +1,5 @@
|
||||
// FizzBuzz kata - TDD progression
|
||||
|
||||
String fizzBuzz(int n) {
|
||||
- return '1';
|
||||
+ return n.toString();
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 919e90fd474a2cc4200c9d6d0a0235365f6b718c Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:46:14 +0700
|
||||
Subject: [PATCH 06/12] RED: Add test for input 3 returning "Fizz"
|
||||
|
||||
---
|
||||
test/fizzbuzz_test.dart | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/test/fizzbuzz_test.dart b/test/fizzbuzz_test.dart
|
||||
index 7b517ae..27b1ce6 100644
|
||||
--- a/test/fizzbuzz_test.dart
|
||||
+++ b/test/fizzbuzz_test.dart
|
||||
@@ -9,4 +9,8 @@ void main() {
|
||||
test('returns "2" for 2', () {
|
||||
expect(fizzBuzz(2), equals('2'));
|
||||
});
|
||||
+
|
||||
+ test('returns "Fizz" for 3', () {
|
||||
+ expect(fizzBuzz(3), equals('Fizz'));
|
||||
+ });
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 1db35633b102b359860a7e85361d733038e8655d Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:46:27 +0700
|
||||
Subject: [PATCH 07/12] GREEN: Return "Fizz" for numbers divisible by 3
|
||||
|
||||
---
|
||||
lib/fizzbuzz.dart | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/lib/fizzbuzz.dart b/lib/fizzbuzz.dart
|
||||
index 4da1cfa..21150ec 100644
|
||||
--- a/lib/fizzbuzz.dart
|
||||
+++ b/lib/fizzbuzz.dart
|
||||
@@ -1,5 +1,6 @@
|
||||
// FizzBuzz kata - TDD progression
|
||||
|
||||
String fizzBuzz(int n) {
|
||||
+ if (n % 3 == 0) return 'Fizz';
|
||||
return n.toString();
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 08cc354e1f1798f062e9c947b7d64637870d8964 Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:46:38 +0700
|
||||
Subject: [PATCH 08/12] RED: Add test for input 5 returning "Buzz"
|
||||
|
||||
---
|
||||
test/fizzbuzz_test.dart | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/test/fizzbuzz_test.dart b/test/fizzbuzz_test.dart
|
||||
index 27b1ce6..46f279a 100644
|
||||
--- a/test/fizzbuzz_test.dart
|
||||
+++ b/test/fizzbuzz_test.dart
|
||||
@@ -13,4 +13,8 @@ void main() {
|
||||
test('returns "Fizz" for 3', () {
|
||||
expect(fizzBuzz(3), equals('Fizz'));
|
||||
});
|
||||
+
|
||||
+ test('returns "Buzz" for 5', () {
|
||||
+ expect(fizzBuzz(5), equals('Buzz'));
|
||||
+ });
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From 74d6e23f3faa7c7138178ce00c784c51e97677e4 Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:46:52 +0700
|
||||
Subject: [PATCH 09/12] GREEN: Return "Buzz" for numbers divisible by 5
|
||||
|
||||
---
|
||||
lib/fizzbuzz.dart | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/lib/fizzbuzz.dart b/lib/fizzbuzz.dart
|
||||
index 21150ec..063e7bd 100644
|
||||
--- a/lib/fizzbuzz.dart
|
||||
+++ b/lib/fizzbuzz.dart
|
||||
@@ -2,5 +2,6 @@
|
||||
|
||||
String fizzBuzz(int n) {
|
||||
if (n % 3 == 0) return 'Fizz';
|
||||
+ if (n % 5 == 0) return 'Buzz';
|
||||
return n.toString();
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From ca23fe7f17e7d29d8e375a4a2fc1ac32bf8452c6 Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:47:04 +0700
|
||||
Subject: [PATCH 10/12] RED: Add test for input 15 returning "FizzBuzz"
|
||||
|
||||
---
|
||||
test/fizzbuzz_test.dart | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/test/fizzbuzz_test.dart b/test/fizzbuzz_test.dart
|
||||
index 46f279a..f3203e3 100644
|
||||
--- a/test/fizzbuzz_test.dart
|
||||
+++ b/test/fizzbuzz_test.dart
|
||||
@@ -17,4 +17,8 @@ void main() {
|
||||
test('returns "Buzz" for 5', () {
|
||||
expect(fizzBuzz(5), equals('Buzz'));
|
||||
});
|
||||
+
|
||||
+ test('returns "FizzBuzz" for 15', () {
|
||||
+ expect(fizzBuzz(15), equals('FizzBuzz'));
|
||||
+ });
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From f15c0989635612226d40e28c8507276ecd1c976d Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:47:17 +0700
|
||||
Subject: [PATCH 11/12] GREEN: Return "FizzBuzz" for numbers divisible by both
|
||||
3 and 5 (check 15 first!)
|
||||
|
||||
---
|
||||
lib/fizzbuzz.dart | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/lib/fizzbuzz.dart b/lib/fizzbuzz.dart
|
||||
index 063e7bd..b312695 100644
|
||||
--- a/lib/fizzbuzz.dart
|
||||
+++ b/lib/fizzbuzz.dart
|
||||
@@ -1,6 +1,7 @@
|
||||
// FizzBuzz kata - TDD progression
|
||||
|
||||
String fizzBuzz(int n) {
|
||||
+ if (n % 15 == 0) return 'FizzBuzz';
|
||||
if (n % 3 == 0) return 'Fizz';
|
||||
if (n % 5 == 0) return 'Buzz';
|
||||
return n.toString();
|
||||
--
|
||||
2.53.0
|
||||
|
||||
|
||||
From cd13284513f428908ec0035f0848a12c27636eaa Mon Sep 17 00:00:00 2001
|
||||
From: Dhemas Nurjaya <dhemasnurjaya@outlook.com>
|
||||
Date: Tue, 10 Mar 2026 11:48:30 +0700
|
||||
Subject: [PATCH 12/12] Add documentation for FizzBuzz demo kata
|
||||
|
||||
---
|
||||
DEMO_SCRIPT.md | 346 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
README.md | 56 ++++++++
|
||||
2 files changed, 402 insertions(+)
|
||||
create mode 100644 DEMO_SCRIPT.md
|
||||
create mode 100644 README.md
|
||||
|
||||
diff --git a/DEMO_SCRIPT.md b/DEMO_SCRIPT.md
|
||||
new file mode 100644
|
||||
index 0000000..d0853e0
|
||||
--- /dev/null
|
||||
+++ b/DEMO_SCRIPT.md
|
||||
@@ -0,0 +1,346 @@
|
||||
+# FizzBuzz Live Demo Script
|
||||
+
|
||||
+**Duration:** 15 minutes (0:10–0:25 in workshop schedule)
|
||||
+**Purpose:** Demonstrate RED-GREEN-REFACTOR cycle in real-time
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## Setup (Before Demo Starts)
|
||||
+
|
||||
+- [ ] Open two windows side-by-side: `lib/fizzbuzz.dart` and `test/fizzbuzz_test.dart`
|
||||
+- [ ] Have terminal ready at bottom with `dart test --watch` (optional) or be ready to run `dart test` manually
|
||||
+- [ ] Start with the final completed kata, then `git reset --hard <initial-commit>` to beginning
|
||||
+- [ ] Have git log open in another terminal: `git log --oneline --all`
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## Demo Flow
|
||||
+
|
||||
+### Minutes 0-2: Introduction
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+We're going to build FizzBuzz together using TDD. Everyone knows the rules, right?
|
||||
+[Pause for nods]
|
||||
+
|
||||
+Divisible by 3 → "Fizz"
|
||||
+Divisible by 5 → "Buzz"
|
||||
+Divisible by both → "FizzBuzz"
|
||||
+Otherwise → the number as a string
|
||||
+
|
||||
+Here's the key: I'm NOT going to design this first. I'm going to let the tests tell me what to code.
|
||||
+
|
||||
+Watch the rhythm:
|
||||
+1. RED - Write a test, watch it fail
|
||||
+2. GREEN - Write minimal code to pass
|
||||
+3. REFACTOR - Clean up if needed
|
||||
+
|
||||
+Let's start.
|
||||
+```
|
||||
+
|
||||
+**What to Do:**
|
||||
+- Show the empty files
|
||||
+- Run `dart test` → shows no tests or all passing (from setup)
|
||||
+
|
||||
+---
|
||||
+
|
||||
+### Minutes 2-4: Cycle 1 (Input 1 → "1")
|
||||
+
|
||||
+**RED Phase:**
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+What's the simplest test I could write? Let me start with input 1 returning "1".
|
||||
+```
|
||||
+
|
||||
+**What to Do:**
|
||||
+```dart
|
||||
+// In test/fizzbuzz_test.dart
|
||||
+test('returns "1" for 1', () {
|
||||
+ expect(fizzBuzz(1), equals('1'));
|
||||
+});
|
||||
+```
|
||||
+
|
||||
+Run `dart test` → **FAILS** (function doesn't exist)
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Good! It's RED. The test is failing for the right reason - the function doesn't exist yet.
|
||||
+```
|
||||
+
|
||||
+**GREEN Phase:**
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Now, what's the minimum code to make this pass?
|
||||
+[Pause, let them think]
|
||||
+I could return the number... but even simpler: I'll just return "1".
|
||||
+This looks silly, but watch what happens next.
|
||||
+```
|
||||
+
|
||||
+**What to Do:**
|
||||
+```dart
|
||||
+// In lib/fizzbuzz.dart
|
||||
+String fizzBuzz(int n) {
|
||||
+ return '1';
|
||||
+}
|
||||
+```
|
||||
+
|
||||
+Run `dart test` → **PASSES** (GREEN ✅)
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+GREEN! It passes. Now I could refactor, but there's nothing to clean up yet.
|
||||
+Let's add another test.
|
||||
+```
|
||||
+
|
||||
+**Time Check:** You should be at ~4 minutes
|
||||
+
|
||||
+---
|
||||
+
|
||||
+### Minutes 4-6: Cycle 2 (Input 2 → "2")
|
||||
+
|
||||
+**RED Phase:**
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Next simplest test: input 2 should return "2".
|
||||
+```
|
||||
+
|
||||
+**What to Do:**
|
||||
+```dart
|
||||
+test('returns "2" for 2', () {
|
||||
+ expect(fizzBuzz(2), equals('2'));
|
||||
+});
|
||||
+```
|
||||
+
|
||||
+Run `dart test` → **FAILS** (Expected: '2', Actual: '1')
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+RED again. Now I have duplication in my tests - both expect numbers as strings.
|
||||
+That's okay. Let me make it GREEN.
|
||||
+```
|
||||
+
|
||||
+**GREEN Phase:**
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Now the hardcoded "1" won't work. What's the simplest solution?
|
||||
+[Pause]
|
||||
+Return the number as a string!
|
||||
+```
|
||||
+
|
||||
+**What to Do:**
|
||||
+```dart
|
||||
+String fizzBuzz(int n) {
|
||||
+ return n.toString();
|
||||
+}
|
||||
+```
|
||||
+
|
||||
+Run `dart test` → **PASSES** (both tests GREEN ✅)
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Both tests pass! Notice how the second test forced me to generalize.
|
||||
+I didn't plan that - the tests guided me.
|
||||
+```
|
||||
+
|
||||
+**Time Check:** You should be at ~6 minutes
|
||||
+
|
||||
+---
|
||||
+
|
||||
+### Minutes 6-9: Cycle 3 (Input 3 → "Fizz")
|
||||
+
|
||||
+**RED Phase:**
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Now it gets interesting. Input 3 should return "Fizz".
|
||||
+```
|
||||
+
|
||||
+**What to Do:**
|
||||
+```dart
|
||||
+test('returns "Fizz" for 3', () {
|
||||
+ expect(fizzBuzz(3), equals('Fizz'));
|
||||
+});
|
||||
+```
|
||||
+
|
||||
+Run `dart test` → **FAILS** (Expected: 'Fizz', Actual: '3')
|
||||
+
|
||||
+**GREEN Phase:**
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Okay, now I need to check divisibility by 3.
|
||||
+```
|
||||
+
|
||||
+**What to Do:**
|
||||
+```dart
|
||||
+String fizzBuzz(int n) {
|
||||
+ if (n % 3 == 0) return 'Fizz';
|
||||
+ return n.toString();
|
||||
+}
|
||||
+```
|
||||
+
|
||||
+Run `dart test` → **PASSES** (all 3 tests GREEN ✅)
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+All three pass! The algorithm is starting to emerge.
|
||||
+```
|
||||
+
|
||||
+**Time Check:** You should be at ~9 minutes
|
||||
+
|
||||
+---
|
||||
+
|
||||
+### Minutes 9-11: Cycle 4 (Input 5 → "Buzz")
|
||||
+
|
||||
+**RED Phase:**
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Pattern should be clear now. Input 5 returns "Buzz".
|
||||
+```
|
||||
+
|
||||
+**What to Do:**
|
||||
+```dart
|
||||
+test('returns "Buzz" for 5', () {
|
||||
+ expect(fizzBuzz(5), equals('Buzz'));
|
||||
+});
|
||||
+```
|
||||
+
|
||||
+Run `dart test` → **FAILS** (Expected: 'Buzz', Actual: '5')
|
||||
+
|
||||
+**GREEN Phase:**
|
||||
+
|
||||
+**What to Do:**
|
||||
+```dart
|
||||
+String fizzBuzz(int n) {
|
||||
+ if (n % 3 == 0) return 'Fizz';
|
||||
+ if (n % 5 == 0) return 'Buzz';
|
||||
+ return n.toString();
|
||||
+}
|
||||
+```
|
||||
+
|
||||
+Run `dart test` → **PASSES** (all 4 tests GREEN ✅)
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Four tests passing. But we haven't handled the tricky case yet...
|
||||
+```
|
||||
+
|
||||
+---
|
||||
+
|
||||
+### Minutes 11-14: Cycle 5 (Input 15 → "FizzBuzz")
|
||||
+
|
||||
+**RED Phase:**
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Here's where it gets fun. What should 15 return?
|
||||
+[Let them answer: "FizzBuzz"]
|
||||
+Right! It's divisible by both 3 AND 5.
|
||||
+```
|
||||
+
|
||||
+**What to Do:**
|
||||
+```dart
|
||||
+test('returns "FizzBuzz" for 15', () {
|
||||
+ expect(fizzBuzz(15), equals('FizzBuzz'));
|
||||
+});
|
||||
+```
|
||||
+
|
||||
+Run `dart test` → **FAILS** (Expected: 'FizzBuzz', Actual: 'Fizz')
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Uh oh! It returns "Fizz" because 15 is divisible by 3, and we check that first.
|
||||
+We need to check for BOTH before checking for either individually.
|
||||
+```
|
||||
+
|
||||
+**GREEN Phase:**
|
||||
+
|
||||
+**What to Do:**
|
||||
+```dart
|
||||
+String fizzBuzz(int n) {
|
||||
+ if (n % 15 == 0) return 'FizzBuzz'; // Or: if (n % 3 == 0 && n % 5 == 0)
|
||||
+ if (n % 3 == 0) return 'Fizz';
|
||||
+ if (n % 5 == 0) return 'Buzz';
|
||||
+ return n.toString();
|
||||
+}
|
||||
+```
|
||||
+
|
||||
+Run `dart test` → **PASSES** (all 5 tests GREEN ✅)
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Perfect! All tests pass. ORDER MATTERS. That's a lesson the test taught us.
|
||||
+```
|
||||
+
|
||||
+**Time Check:** You should be at ~14 minutes
|
||||
+
|
||||
+---
|
||||
+
|
||||
+### Minutes 14-15: Wrap Up
|
||||
+
|
||||
+**What to Say:**
|
||||
+```
|
||||
+Let me show you something cool.
|
||||
+[Run: git log --oneline]
|
||||
+
|
||||
+See these commits? Each one is a RED or GREEN step. I can jump back to any point.
|
||||
+
|
||||
+Notice what just happened:
|
||||
+1. I never wrote a "design document" for FizzBuzz
|
||||
+2. The tests told me what code to write
|
||||
+3. The algorithm emerged naturally from simple cases to complex
|
||||
+4. When I made a mistake (checking 3 before 15), the test caught it immediately
|
||||
+
|
||||
+This is TDD. It feels weird at first, but it becomes automatic.
|
||||
+
|
||||
+Now YOU'RE going to try it. Pick your kata and start with the first test.
|
||||
+```
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## Tips for Smooth Delivery
|
||||
+
|
||||
+### DO:
|
||||
+- **Narrate your thinking**: "What's the simplest test?" "What's the minimum code?"
|
||||
+- **Pause before answering**: Let them think for 2-3 seconds
|
||||
+- **Show RED clearly**: Let the test fail, read the error message aloud
|
||||
+- **Type slowly**: They're watching and learning the syntax too
|
||||
+- **Run tests frequently**: After every change
|
||||
+
|
||||
+### DON'T:
|
||||
+- Rush through the cycles - the rhythm is what they're learning
|
||||
+- Skip the RED step - it proves the test can fail
|
||||
+- Write all tests at once - that's not TDD
|
||||
+- Apologize for "simple" code - minimal solutions are the point
|
||||
+- Skip explaining the 15/3/5 order issue - that's a key insight
|
||||
+
|
||||
+### If You Make a Typo:
|
||||
+**Good!** Say: "Oops, typo. See how the test catches it?" Then fix it.
|
||||
+
|
||||
+### If Someone Asks a Question:
|
||||
+Pause the demo, answer briefly, then continue. You have buffer time.
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## Troubleshooting
|
||||
+
|
||||
+| Issue | Fix |
|
||||
+|-------|-----|
|
||||
+| Tests won't run | Check `dart pub get` was run |
|
||||
+| Can't see failure messages clearly | Increase terminal font size |
|
||||
+| Running behind schedule | Skip the "wrap up" or shorten it |
|
||||
+| Running ahead | Add a 6th test (e.g., input 6 → "Fizz") |
|
||||
+
|
||||
+---
|
||||
+
|
||||
+## After the Demo
|
||||
+
|
||||
+Transition to hands-on:
|
||||
+```
|
||||
+"Alright, now you try it. Open one of the katas, uncomment the first test, and make it RED. Then make it GREEN. I'll be walking around - grab me if you get stuck. Go!"
|
||||
+```
|
||||
diff --git a/README.md b/README.md
|
||||
new file mode 100644
|
||||
index 0000000..c4ae816
|
||||
--- /dev/null
|
||||
+++ b/README.md
|
||||
@@ -0,0 +1,56 @@
|
||||
+# FizzBuzz Kata - Live Demo
|
||||
+
|
||||
+## Purpose
|
||||
+
|
||||
+This kata is designed for **live demonstration** during the TDD workshop introduction. It shows the RED-GREEN-REFACTOR cycle in a familiar problem that requires minimal explanation.
|
||||
+
|
||||
+## The Rules
|
||||
+
|
||||
+Write a function that converts numbers to strings according to these rules:
|
||||
+
|
||||
+- Numbers divisible by 3 → `"Fizz"`
|
||||
+- Numbers divisible by 5 → `"Buzz"`
|
||||
+- Numbers divisible by both 3 and 5 → `"FizzBuzz"`
|
||||
+- All other numbers → the number as a string (e.g., `"1"`, `"2"`)
|
||||
+
|
||||
+## Git History as Teaching Tool
|
||||
+
|
||||
+This kata is built with **12 commits** showing each step of the TDD cycle:
|
||||
+
|
||||
+```bash
|
||||
+git log --oneline --all
|
||||
+```
|
||||
+
|
||||
+Each commit shows either:
|
||||
+- **RED**: A failing test
|
||||
+- **GREEN**: Minimal code to pass
|
||||
+- **REFACTOR**: Code cleanup (if needed)
|
||||
+
|
||||
+## Using This for the Demo
|
||||
+
|
||||
+See `DEMO_SCRIPT.md` for detailed talking points and timing guide.
|
||||
+
|
||||
+## Running the Tests
|
||||
+
|
||||
+```bash
|
||||
+dart pub get
|
||||
+dart test
|
||||
+```
|
||||
+
|
||||
+## Checking Out Individual Steps
|
||||
+
|
||||
+To see the code at any point:
|
||||
+
|
||||
+```bash
|
||||
+git log --oneline # See all commits
|
||||
+git checkout <commit-hash> # Jump to that step
|
||||
+git checkout main # Return to final solution
|
||||
+```
|
||||
+
|
||||
+## The "Aha!" Moment
|
||||
+
|
||||
+Notice how the simple tests (1, 2) led to a general solution (n.toString()), and the Fizz/Buzz tests forced the algorithm to emerge naturally. **We never designed the whole solution upfront—the tests revealed it step by step.**
|
||||
+
|
||||
+## For Facilitators
|
||||
+
|
||||
+This is your warm-up kata. Practice it a few times before the workshop so you can live-code it smoothly while talking through your thinking process.
|
||||
--
|
||||
2.53.0
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue