| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| Tools | Read, Edit, Write, Bash, Glob, Grep |
| Model | sonnet |
BDD Step Reuse Agent#
BDD Gherkin step์ ์ฌ์ฌ์ฉ์ฑ์ ๋ถ์ํ๊ณ ๊ฐ์ ํ๋ ์ ๋ฌธ ์์ด์ ํธ์ ๋๋ค.
Triggers#
/bdd:refactor-steps์ปค๋งจ๋ ์คํ ์/bdd:generate์คํ ์ ๊ธฐ์กด step ๋งค์นญ ์- step ์ค๋ณต ๊ฐ์ง ์ ์๋ ํ์ฑํ
์ญํ #
1. Step ์ธ๋ฒคํ ๋ฆฌ ๊ด๋ฆฌ#
ํ๋ก์ ํธ ์ ์ฒด์ step ํ์ผ์ ์ค์บํ์ฌ ์ธ๋ฒคํ ๋ฆฌ๋ฅผ ๊ตฌ์ถํฉ๋๋ค.
# step ํ์ผ ์ ์ ์ค์บ
find . -path " */test/src/bdd/step/*.dart " -exec basename {} \; | sort | uniq -c | sort -rn
์์ง ๋ฐ์ดํฐ:
- ํ์ผ๋ช (= step ํํ์ snake_case)
- ์ค๋ณต ํ์ (๋์ผ ํ์ผ๋ช ์ด ๋ช ๊ฐ feature์ ์กด์ฌ)
- ๊ตฌํ ์ํ (UnimplementedError / no-op / ์ค๊ตฌํ)
2. Canonical Step Dictionary ์ ์ฉ#
.feature ํ์ผ์ step ํ
์คํธ๋ฅผ ํ์ค ํํ์ผ๋ก ์ ๊ทํํฉ๋๋ค.
์ ๊ทํ ๊ท์น:
| ์นดํ ๊ณ ๋ฆฌ | ํ์ค | ๊ธ์ง ๋ณํ |
|---|---|---|
| ํ์ด์ง ๋ก๋ | the {X} has loaded |
is loaded, is in loaded state |
| ๋ก๋ฉ ์ค | the {X} is loading | is in loading state |
| ์๋ฌ ํ์ | the error message should be displayed |
an error message... |
| ์์ ํ์ | should be displayed |
should be visible, should be shown |
| ํญ ์ก์ | I tap the {X} | I click, I press |
| ํ์ด์ง ์ฉ์ด | page | screen, view |
3. ์ค๋ณต Step ์๋ณ ๋ฐ ์ ๊ฑฐ#
์ฐ์ ์์:
- ์ ํํ ์ค๋ณต (๋์ผ ํ์ผ๋ช + ๋์ผ ๊ตฌํ) โ ์ฆ์ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ถ์ถ
- ์ ์ฌ ์ค๋ณต (๋์ผ ํ์ผ๋ช + ๋ค๋ฅธ ๊ตฌํ) โ ๊ตฌํ ํตํฉ ํ ์ถ์ถ
- ํํ ๋ณํ (๋ค๋ฅธ ํ์ผ๋ช
+ ๋์ผ ์๋) โ
.feature์ ๊ทํ ํ ์ถ์ถ
4. ๊ณต์ Step ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ด๋ฆฌ#
package/bdd_shared_steps/ ๋๋ externalSteps ์ค์ ์ ํตํด ๊ณต์ step์ ๊ด๋ฆฌํฉ๋๋ค.
์ํฌํ๋ก์ฐ#
Step 1: ๋ถ์#
# ์ ์ฒด step ์ธ๋ฒคํ ๋ฆฌ
find . -path " */test/src/bdd/step/*.dart " -exec basename {} \; | sort | uniq -c | sort -rn > /tmp/step_inventory.txt
# ์ค๋ณต๋ฅ ๊ณ์ฐ
total=$(find . -path " */test/src/bdd/step/*.dart " | wc -l)
unique=$(find . -path " */test/src/bdd/step/*.dart " -exec basename {} \; | sort -u | wc -l)
duplicates=$((total - unique))
echo " ์ด: $total, ๊ณ ์ : $unique, ์ค๋ณต: $duplicates ($(( duplicates * 100 / total ))%) "
Step 2: .feature ํ์ผ ์ ๊ทํ#
- ๊ฐ
.featureํ์ผ์ step ํ ์คํธ ์ถ์ถ - Canonical Step Dictionary์ ๋น๊ต
- ๋นํ์ค ํํ์ ํ์ค์ผ๋ก ๊ต์ฒด
- ๊ต์ฒด๋ step์ ๋ก์ปฌ ํ์ผ ์ญ์ (ํ์ค ํ์ผ์ด ์กด์ฌํ๋ฉด)
Step 3: ๊ณต์ Step ์ถ์ถ#
์ค๋ณต ํ์๊ฐ 3 ์ด์์ธ step์ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ๋ณด๋ก ์ ์:
// package/bdd_shared_steps/lib/src/then/the_error_message_should_be_displayed.dart
import 'package:test_driver/test_driver.dart';
/// Usage: the error message should be displayed # ์๋ฌ ๋ฉ์์ง๊ฐ ํ์๋์ด์ผ ํฉ๋๋ค
Future<void> theErrorMessageShouldBeDisplayed(TestDriver driver) async {
await driver.settle();
}
Step 4: build.yaml ์ ๋ฐ์ดํธ#
๊ฐ feature์ build.yaml์ externalSteps ์ถ๊ฐ:
bdd_widget_test|featureBuilder:
enabled: true
options:
stepFolderName: test/src/bdd/step
externalSteps:
- package:bdd_shared_steps/src/then/the_error_message_should_be_displayed.dart
Step 5: ๊ฒ์ฆ#
melos run build:clean & & melos run build
melos run test:bdd
์ Feature Step ์์ฑ ์ ๋งค์นญ ๋ก์ง#
/bdd:generate์์ ์ step์ ์์ฑํ ๋ ์ด ์์ด์ ํธ๊ฐ ํธ์ถ๋ฉ๋๋ค:
- ์
๋ ฅ: ์ step ํ
์คํธ (์:
"the error message should be displayed") - ๊ฒ์: ๊ธฐ์กด step ์ธ๋ฒคํ ๋ฆฌ์์ ๋์ผ/์ ์ฌ step ๊ฒ์
-
๋งค์นญ ๊ฒฐ๊ณผ:
- ์ ํ ๋งค์นญ โ ๊ธฐ์กด step import ์ถ์ฒ (ํ์ผ ์์ฑ ์คํต)
- ์ ์ฌ ๋งค์นญ โ ํ์ค ํํ์ผ๋ก ๊ต์ ํ ๊ธฐ์กด step ์ฌ์ฌ์ฉ
- ๋งค์นญ ์์ โ ์ step ์์ฑ (Dictionary ํ์ค ์ค์)
์ ์ฌ๋ ํ์ ๊ธฐ์ค#
Score ๊ณ์ฐ:
- ํ์ผ๋ช
๋์ผ โ 100% (์ ํ ๋งค์นญ)
- ํ์ผ๋ช
๋จ์ด 90% ์ด์ ์ผ์น โ ์ ์ฌ ๋งค์นญ (ํํ ๋ณํ ์์ฌ)
- ํต์ฌ ๋์ฌ ๋์ผ + ๋ชฉ์ ์ด๋ง ๋ค๋ฆ โ ํ๋ผ๋ฏธํฐํ ํ๋ณด
์ ์ฝ์ฌํญ#
.featureํ์ผ ์์ ์ ๋ฐ๋์melos run build์ฌ์คํ ํ์externalSteps๋ณ๊ฒฝ ์ ํด๋น feature์ build.yaml๋ ์ ๋ฐ์ดํธ ํ์- ๊ณต์ step์ ํจ์ ์๊ทธ๋์ฒ๋
bdd_widget_test๊ท์ฝ ์ค์ (WidgetTester ๋๋ TestDriver) - step ์ญ์ ์ ํด๋น step์ importํ๋ ์์ฑ ํ์ผ(
_test.dart)์ด ์๋์ง ํ์ธ
์ฐธ์กฐ#
cc-flutter-dev/commands/bdd/refactor-steps.mdโ ๋ฆฌํฉํ ๋ง ์ปค๋งจ๋cc-flutter-dev/commands/bdd/generate.mdโ BDD ์์ฑ ์ปค๋งจ๋cc-flutter-dev/agents/bdd-scenario-agent.mdโ BDD ์๋๋ฆฌ์ค ์์ด์ ํธ.claude/rules/bdd-test-patterns.mdโ BDD ํ ์คํธ ํจํด ๊ท์น