@k2works/claude-code-booster 6.4.0 → 6.5.0

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.
Files changed (297) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +61 -61
  3. package/bin/claude-code-booster +113 -113
  4. package/lib/assets/.claude/README.md +287 -287
  5. package/lib/assets/.claude/agents/xp-architect.md +250 -250
  6. package/lib/assets/.claude/agents/xp-executive.md +207 -207
  7. package/lib/assets/.claude/agents/xp-interaction-designer.md +239 -239
  8. package/lib/assets/.claude/agents/xp-product-manager.md +245 -245
  9. package/lib/assets/.claude/agents/xp-programmer.md +268 -268
  10. package/lib/assets/.claude/agents/xp-project-manager.md +229 -229
  11. package/lib/assets/.claude/agents/xp-technical-writer.md +224 -224
  12. package/lib/assets/.claude/agents/xp-tester.md +265 -265
  13. package/lib/assets/.claude/agents/xp-user-representative.md +204 -204
  14. package/lib/assets/.claude/scripts/generate-inception-deck.mjs +911 -911
  15. package/lib/assets/.claude/settings.json +11 -11
  16. package/lib/assets/.claude/skills/ai-agent-guidelines/SKILL.md +111 -111
  17. package/lib/assets/.claude/skills/analyzing-architecture/SKILL.md +83 -83
  18. package/lib/assets/.claude/skills/analyzing-business-architecture/SKILL.md +122 -122
  19. package/lib/assets/.claude/skills/analyzing-business-case/SKILL.md +148 -148
  20. package/lib/assets/.claude/skills/analyzing-business-strategy/SKILL.md +277 -277
  21. package/lib/assets/.claude/skills/analyzing-data-model/SKILL.md +77 -77
  22. package/lib/assets/.claude/skills/analyzing-domain-model/SKILL.md +117 -117
  23. package/lib/assets/.claude/skills/analyzing-inception-deck/SKILL.md +84 -84
  24. package/lib/assets/.claude/skills/analyzing-non-functional/SKILL.md +95 -95
  25. package/lib/assets/.claude/skills/analyzing-operation/SKILL.md +95 -95
  26. package/lib/assets/.claude/skills/analyzing-requirements/SKILL.md +91 -91
  27. package/lib/assets/.claude/skills/analyzing-review/SKILL.md +174 -174
  28. package/lib/assets/.claude/skills/analyzing-tech-stack/SKILL.md +101 -101
  29. package/lib/assets/.claude/skills/analyzing-test-strategy/SKILL.md +89 -89
  30. package/lib/assets/.claude/skills/analyzing-ui-design/SKILL.md +80 -80
  31. package/lib/assets/.claude/skills/analyzing-usecases/SKILL.md +72 -72
  32. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/benchmark.json +20 -0
  33. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/benchmark.md +13 -0
  34. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/eval_metadata.json +14 -0
  35. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/grading.json +39 -0
  36. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/adr/001-db.md +12 -0
  37. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/adr/002-cache-strategy.md +20 -0
  38. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/adr/index.md +4 -0
  39. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/design/data-model.md +12 -0
  40. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/design/index.md +3 -0
  41. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/index.md +10 -0
  42. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/log.md +7 -0
  43. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/operation/deploy-old.md +12 -0
  44. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/operation/deploy.md +12 -0
  45. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/operation/index.md +4 -0
  46. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/docs_after/reference/OKF/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211_V0.2.md +965 -0
  47. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/with_skill/outputs/report.md +76 -0
  48. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/grading.json +39 -0
  49. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/adr/001-db.md +12 -0
  50. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/adr/002-cache-strategy.md +20 -0
  51. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/adr/index.md +4 -0
  52. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/design/data-model.md +12 -0
  53. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/design/index.md +3 -0
  54. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/index.md +10 -0
  55. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/log.md +7 -0
  56. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/operation/deploy-old.md +12 -0
  57. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/operation/deploy.md +12 -0
  58. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/operation/index.md +4 -0
  59. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/docs_after/reference/OKF/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211_V0.2.md +965 -0
  60. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-1-register-new-adr/without_skill/outputs/report.md +22 -0
  61. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/eval_metadata.json +13 -0
  62. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/grading.json +34 -0
  63. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/adr/001-db.md +12 -0
  64. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/adr/002-cache-strategy.md +11 -0
  65. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/adr/index.md +3 -0
  66. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/design/data-model.md +14 -0
  67. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/design/index.md +3 -0
  68. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/index.md +10 -0
  69. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/log.md +7 -0
  70. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/operation/deploy-old.md +12 -0
  71. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/operation/deploy.md +12 -0
  72. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/operation/index.md +4 -0
  73. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/docs_after/reference/OKF/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211_V0.2.md +965 -0
  74. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/with_skill/outputs/report.md +61 -0
  75. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/grading.json +34 -0
  76. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/adr/001-db.md +12 -0
  77. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/adr/002-cache-strategy.md +11 -0
  78. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/adr/index.md +3 -0
  79. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/design/data-model.md +13 -0
  80. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/design/index.md +3 -0
  81. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/index.md +10 -0
  82. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/log.md +7 -0
  83. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/operation/deploy-old.md +12 -0
  84. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/operation/deploy.md +12 -0
  85. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/operation/index.md +4 -0
  86. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/docs_after/reference/OKF/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211_V0.2.md +965 -0
  87. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-2-verify-reviewed-doc/without_skill/outputs/report.md +18 -0
  88. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/eval_metadata.json +13 -0
  89. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/grading.json +34 -0
  90. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/adr/001-db.md +12 -0
  91. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/adr/002-cache-strategy.md +11 -0
  92. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/adr/index.md +3 -0
  93. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/design/data-model.md +12 -0
  94. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/design/index.md +3 -0
  95. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/index.md +10 -0
  96. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/log.md +7 -0
  97. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/operation/deploy-old.md +13 -0
  98. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/operation/deploy.md +12 -0
  99. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/operation/index.md +7 -0
  100. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/docs_after/reference/OKF/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211_V0.2.md +965 -0
  101. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/with_skill/outputs/report.md +83 -0
  102. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/grading.json +34 -0
  103. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/adr/001-db.md +12 -0
  104. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/adr/002-cache-strategy.md +11 -0
  105. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/adr/index.md +3 -0
  106. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/design/data-model.md +12 -0
  107. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/design/index.md +3 -0
  108. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/index.md +10 -0
  109. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/log.md +7 -0
  110. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/operation/deploy-old.md +14 -0
  111. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/operation/deploy.md +12 -0
  112. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/operation/index.md +4 -0
  113. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/docs_after/reference/OKF/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211_V0.2.md +965 -0
  114. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/eval-3-deprecate-replaced-doc/without_skill/outputs/report.md +15 -0
  115. package/lib/assets/.claude/skills/apply-okf-workspace/iteration-1/review.html +1325 -0
  116. package/lib/assets/.claude/skills/closing-iteration/SKILL.md +176 -176
  117. package/lib/assets/.claude/skills/creating-adr/SKILL.md +117 -117
  118. package/lib/assets/.claude/skills/creating-development-strategy/SKILL.md +187 -151
  119. package/lib/assets/.claude/skills/creating-iteration-report/SKILL.md +210 -210
  120. package/lib/assets/.claude/skills/creating-journal/SKILL.md +140 -140
  121. package/lib/assets/.claude/skills/creating-manual/SKILL.md +199 -199
  122. package/lib/assets/.claude/skills/creating-release-report/SKILL.md +161 -161
  123. package/lib/assets/.claude/skills/creating-slides/SKILL.md +86 -86
  124. package/lib/assets/.claude/skills/creating-slides/agents/openai.yaml +4 -4
  125. package/lib/assets/.claude/skills/creating-slides/references/manga-css.md +45 -45
  126. package/lib/assets/.claude/skills/creating-slides/scripts/slide_tools.py +239 -239
  127. package/lib/assets/.claude/skills/developing-backend/SKILL.md +138 -100
  128. package/lib/assets/.claude/skills/developing-frontend/SKILL.md +131 -93
  129. package/lib/assets/.claude/skills/developing-release/SKILL.md +120 -120
  130. package/lib/assets/.claude/skills/developing-review/SKILL.md +175 -175
  131. package/lib/assets/.claude/skills/developing-uiux-review/SKILL.md +207 -207
  132. package/lib/assets/.claude/skills/generating-bmc/SKILL.md +123 -123
  133. package/lib/assets/.claude/skills/generating-slides/SKILL.md +94 -94
  134. package/lib/assets/.claude/skills/git-commit/SKILL.md +81 -81
  135. package/lib/assets/.claude/skills/killing-processes/SKILL.md +44 -44
  136. package/lib/assets/.claude/skills/migrating-ai-dlc/evals/evals.json +59 -59
  137. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/benchmark.json +20 -0
  138. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/benchmark.md +13 -0
  139. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/eval_metadata.json +15 -0
  140. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/with_skill/grading.json +44 -0
  141. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/with_skill/outputs/docs_after/adr/index.md +10 -0
  142. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/with_skill/outputs/docs_after/index.md +15 -0
  143. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/with_skill/outputs/docs_after/log.md +5 -0
  144. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/with_skill/outputs/docs_after/reference/OKF/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211_V0.2.md +966 -0
  145. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/with_skill/outputs/docs_after/reference/index.md +6 -0
  146. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/with_skill/outputs/docs_after/reference//343/202/210/343/201/204/343/202/275/343/203/225/343/203/210/343/202/246/343/202/247/343/202/242/343/201/250/343/201/257.md +261 -0
  147. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/with_skill/outputs/docs_after/reference//343/203/252/343/203/252/343/203/274/343/202/271/343/202/254/343/202/244/343/203/211.md +480 -0
  148. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/with_skill/outputs/docs_after/reference//347/222/260/345/242/203/345/244/211/346/225/260/347/256/241/347/220/206/343/202/254/343/202/244/343/203/211.md +681 -0
  149. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/with_skill/outputs/report.md +85 -0
  150. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/without_skill/grading.json +44 -0
  151. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/without_skill/outputs/docs_after/adr/index.md +8 -0
  152. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/without_skill/outputs/docs_after/index.md +11 -0
  153. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/without_skill/outputs/docs_after/log.md +7 -0
  154. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/without_skill/outputs/docs_after/reference/OKF/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211_V0.2.md +964 -0
  155. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/without_skill/outputs/docs_after/reference/index.md +9 -0
  156. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/without_skill/outputs/docs_after/reference//343/202/210/343/201/204/343/202/275/343/203/225/343/203/210/343/202/246/343/202/247/343/202/242/343/201/250/343/201/257.md +250 -0
  157. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/without_skill/outputs/docs_after/reference//343/203/252/343/203/252/343/203/274/343/202/271/343/202/254/343/202/244/343/203/211.md +469 -0
  158. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/without_skill/outputs/docs_after/reference//347/222/260/345/242/203/345/244/211/346/225/260/347/256/241/347/220/206/343/202/254/343/202/244/343/203/211.md +677 -0
  159. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-1-migrate-docs/without_skill/outputs/report.md +49 -0
  160. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-2-upgrade-v01-to-v02/eval_metadata.json +13 -0
  161. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-2-upgrade-v01-to-v02/with_skill/grading.json +34 -0
  162. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-2-upgrade-v01-to-v02/with_skill/outputs/knowledge_after/index.md +7 -0
  163. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-2-upgrade-v01-to-v02/with_skill/outputs/knowledge_after/log.md +7 -0
  164. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-2-upgrade-v01-to-v02/with_skill/outputs/knowledge_after/metrics/churn.md +9 -0
  165. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-2-upgrade-v01-to-v02/with_skill/outputs/knowledge_after/metrics/income-statement.md +15 -0
  166. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/eval-2-upgrade-v01-to-v02/with_skill/outputs/report.md +147 -0
  167. package/lib/assets/.claude/skills/migrating-okf-workspace/iteration-1/review.html +1325 -0
  168. package/lib/assets/.claude/skills/opening-iteration/SKILL.md +124 -124
  169. package/lib/assets/.claude/skills/operating-backup/SKILL.md +59 -59
  170. package/lib/assets/.claude/skills/operating-cicd/SKILL.md +54 -54
  171. package/lib/assets/.claude/skills/operating-deploy/SKILL.md +67 -67
  172. package/lib/assets/.claude/skills/operating-docs/SKILL.md +219 -219
  173. package/lib/assets/.claude/skills/operating-provision/SKILL.md +77 -77
  174. package/lib/assets/.claude/skills/operating-qt/SKILL.md +147 -147
  175. package/lib/assets/.claude/skills/operating-review/SKILL.md +171 -171
  176. package/lib/assets/.claude/skills/operating-script/SKILL.md +145 -145
  177. package/lib/assets/.claude/skills/operating-setup/SKILL.md +63 -63
  178. package/lib/assets/.claude/skills/orchestrating-analysis/SKILL.md +110 -110
  179. package/lib/assets/.claude/skills/orchestrating-development/SKILL.md +208 -172
  180. package/lib/assets/.claude/skills/orchestrating-operation/SKILL.md +161 -161
  181. package/lib/assets/.claude/skills/orchestrating-project/SKILL.md +149 -149
  182. package/lib/assets/.claude/skills/planning-releases/SKILL.md +121 -121
  183. package/lib/assets/.claude/skills/practicing-getting-start-tdd/SKILL.md +262 -262
  184. package/lib/assets/.claude/skills/syncing-github-project/SKILL.md +151 -151
  185. package/lib/assets/.claude/skills/tracking-progress/SKILL.md +91 -91
  186. package/lib/assets/.claude/skills/validating-design/SKILL.md +130 -130
  187. package/lib/assets/.claude/skills/validating-iteration-plan/SKILL.md +238 -238
  188. package/lib/assets/.claude/skills/validating-operating-setup/SKILL.md +118 -118
  189. package/lib/assets/.devcontainer/devcontainer.json +37 -37
  190. package/lib/assets/.env.example +32 -32
  191. package/lib/assets/.gitattributes +4 -4
  192. package/lib/assets/.github/workflows/docker-publish.yml +77 -77
  193. package/lib/assets/.github/workflows/mkdocs.yml +39 -39
  194. package/lib/assets/AGENTS.md +102 -102
  195. package/lib/assets/README.md +304 -304
  196. package/lib/assets/docker-compose.yml +33 -33
  197. package/lib/assets/docs/adr/index.md +10 -10
  198. package/lib/assets/docs/article/index.md +1 -0
  199. package/lib/assets/docs/assets/css/extra.css +29 -29
  200. package/lib/assets/docs/assets/js/extra.js +48 -48
  201. package/lib/assets/docs/assets/js/mathjax.js +27 -27
  202. package/lib/assets/docs/design/index.md +44 -44
  203. package/lib/assets/docs/development/index.md +39 -39
  204. package/lib/assets/docs/index.md +37 -37
  205. package/lib/assets/docs/log.md +28 -28
  206. package/lib/assets/docs/operation/index.md +41 -41
  207. package/lib/assets/docs/reference/BDD/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211.md +766 -766
  208. package/lib/assets/docs/reference/CodexCLIMCP/343/202/242/343/203/227/343/203/252/343/202/261/343/203/274/343/202/267/343/203/247/343/203/263/351/226/213/347/231/272/343/203/225/343/203/255/343/203/274.md +555 -555
  209. package/lib/assets/docs/reference/CodexCLIMCP/343/202/265/343/203/274/343/203/220/343/203/274/350/250/255/345/256/232/346/211/213/351/240/206.md +351 -351
  210. package/lib/assets/docs/reference/Java/343/202/242/343/203/227/343/203/252/343/202/261/343/203/274/343/202/267/343/203/247/343/203/263/347/222/260/345/242/203/346/247/213/347/257/211/343/202/254/343/202/244/343/203/211.md +592 -592
  211. package/lib/assets/docs/reference/LivingDocumentation/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211.md +400 -0
  212. package/lib/assets/docs/reference/OKF/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211_V0.2.md +965 -965
  213. package/lib/assets/docs/reference/SonarQube/343/203/255/343/203/274/343/202/253/343/203/253/347/222/260/345/242/203/343/202/273/343/203/203/343/203/210/343/202/242/343/203/203/343/203/227/346/211/213/351/240/206/346/233/270.md +652 -652
  214. package/lib/assets/docs/reference/TypeScript/343/202/242/343/203/227/343/203/252/343/202/261/343/203/274/343/202/267/343/203/247/343/203/263/347/222/260/345/242/203/346/247/213/347/257/211/343/202/254/343/202/244/343/203/211.md +476 -476
  215. package/lib/assets/docs/reference/UI/350/250/255/350/250/210/343/202/254/343/202/244/343/203/211.md +460 -460
  216. package/lib/assets/docs/reference/Vim/346/223/215/344/275/234/343/203/236/343/203/213/343/203/245/343/202/242/343/203/253.md +177 -177
  217. package/lib/assets/docs/reference/images/Ansoff.drawio.svg +3 -3
  218. package/lib/assets/docs/reference/images/BMC.drawio.svg +3 -3
  219. package/lib/assets/docs/reference/images/BrandBasicStrategy.drawio.svg +3 -3
  220. package/lib/assets/docs/reference/images/BrandCategorization.drawio.svg +3 -3
  221. package/lib/assets/docs/reference/images/BrandRecurutementStrategy.drawio.svg +3 -3
  222. package/lib/assets/docs/reference/images/BrandValue.drawio.svg +3 -3
  223. package/lib/assets/docs/reference/images/BusinessActivitiy.svg +3 -3
  224. package/lib/assets/docs/reference/images/HRM.drawio.svg +3 -3
  225. package/lib/assets/docs/reference/images/MarketingStructure.drawio.svg +3 -3
  226. package/lib/assets/docs/reference/images/OrganizationElemnts.svg +3 -3
  227. package/lib/assets/docs/reference/images/PPM.drawio.svg +3 -3
  228. package/lib/assets/docs/reference/images/PositioningMap.drawio.svg +3 -3
  229. package/lib/assets/docs/reference/images/ProductLayer.drawio.svg +3 -3
  230. package/lib/assets/docs/reference/images/ProductMix.drawio.svg +3 -3
  231. package/lib/assets/docs/reference/images/SWOT.drawio.svg +3 -3
  232. package/lib/assets/docs/reference/images/TargetMarket.drawio.svg +3 -3
  233. package/lib/assets/docs/reference/images/ThreeGenericStrategies.drawio.svg +3 -3
  234. package/lib/assets/docs/reference/images/VRIO.drawio.svg +3 -3
  235. package/lib/assets/docs/reference/images/ValueChain.drawio.svg +3 -3
  236. package/lib/assets/docs/reference/index.md +66 -62
  237. package/lib/assets/docs/reference//343/202/210/343/201/204/343/202/275/343/203/225/343/203/210/343/202/246/343/202/247/343/202/242/343/201/250/343/201/257.md +250 -250
  238. package/lib/assets/docs/reference//343/202/242/343/203/216/343/203/206/343/203/274/343/202/267/343/203/247/343/203/263/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211.md +268 -0
  239. package/lib/assets/docs/reference//343/202/242/343/203/274/343/202/255/343/203/206/343/202/257/343/203/201/343/203/243/350/250/255/350/250/210/343/202/254/343/202/244/343/203/211.md +2226 -2226
  240. package/lib/assets/docs/reference//343/202/244/343/203/263/343/203/225/343/203/251/350/250/255/350/250/210/343/202/254/343/202/244/343/203/211.md +1888 -1888
  241. package/lib/assets/docs/reference//343/202/250/343/202/257/343/202/271/343/203/210/343/203/252/343/203/274/343/203/240/343/203/227/343/203/255/343/202/260/343/203/251/343/203/237/343/203/263/343/202/260.md +549 -549
  242. package/lib/assets/docs/reference//343/202/254/343/202/244/343/203/211/343/203/204/343/202/242/343/203/274/343/203/273/343/202/265/343/202/244/343/203/210/343/202/267/343/203/274/343/202/244/343/203/263/343/202/260/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211.md +192 -0
  243. package/lib/assets/docs/reference//343/202/263/343/203/274/343/203/207/343/202/243/343/203/263/343/202/260/343/201/250/343/203/206/343/202/271/343/203/210/343/202/254/343/202/244/343/203/211.md +715 -715
  244. package/lib/assets/docs/reference//343/203/200/343/202/244/343/203/212/343/203/237/343/203/203/343/202/257/343/202/255/343/203/245/343/203/254/343/203/274/343/202/267/343/203/247/343/203/263/345/260/216/345/205/245/343/202/254/343/202/244/343/203/211.md +191 -0
  245. package/lib/assets/docs/reference//343/203/206/343/202/271/343/203/210/346/210/246/347/225/245/343/202/254/343/202/244/343/203/211.md +1323 -1323
  246. package/lib/assets/docs/reference//343/203/207/343/203/274/343/202/277/343/203/242/343/203/207/343/203/253/350/250/255/350/250/210/343/202/254/343/202/244/343/203/211.md +321 -321
  247. package/lib/assets/docs/reference//343/203/211/343/203/241/343/202/244/343/203/263/343/203/242/343/203/207/343/203/253/350/250/255/350/250/210/343/202/254/343/202/244/343/203/211.md +609 -609
  248. package/lib/assets/docs/reference//343/203/223/343/202/270/343/203/215/343/202/271/343/202/242/343/203/274/343/202/255/343/203/206/343/202/257/343/203/201/343/203/243/345/210/206/346/236/220/343/202/254/343/202/244/343/203/211.md +537 -537
  249. package/lib/assets/docs/reference//343/203/246/343/203/274/343/202/271/343/202/261/343/203/274/343/202/271/344/275/234/346/210/220/343/202/254/343/202/244/343/203/211.md +699 -699
  250. package/lib/assets/docs/reference//343/203/252/343/203/252/343/203/274/343/202/271/343/202/254/343/202/244/343/203/211.md +470 -470
  251. package/lib/assets/docs/reference//343/203/252/343/203/252/343/203/274/343/202/271/343/203/273/343/202/244/343/203/206/343/203/254/343/203/274/343/202/267/343/203/247/343/203/263/350/250/210/347/224/273/343/202/254/343/202/244/343/203/211.md +580 -580
  252. package/lib/assets/docs/reference//343/203/255/343/202/270/343/202/253/343/203/253/343/202/267/343/203/263/343/202/255/343/203/263/343/202/260.md +1376 -1376
  253. package/lib/assets/docs/reference//344/274/201/346/245/255/347/265/214/345/226/266/350/253/226.md +2647 -2647
  254. package/lib/assets/docs/reference//347/222/260/345/242/203/345/244/211/346/225/260/347/256/241/347/220/206/343/202/254/343/202/244/343/203/211.md +675 -675
  255. package/lib/assets/docs/reference//347/265/214/345/226/266/346/210/246/347/225/245/345/210/206/346/236/220/343/202/254/343/202/244/343/203/211.md +575 -575
  256. package/lib/assets/docs/reference//350/246/201/344/273/266/345/256/232/347/276/251/343/202/254/343/202/244/343/203/211.md +1258 -1258
  257. package/lib/assets/docs/reference//350/250/200/350/252/236/345/210/245/351/226/213/347/231/272/343/202/254/343/202/244/343/203/211.md +527 -527
  258. package/lib/assets/docs/reference//351/201/213/345/226/266/347/256/241/347/220/206.md +1492 -1492
  259. package/lib/assets/docs/reference//351/201/213/347/224/250/343/202/271/343/202/257/343/203/252/343/203/227/343/203/210/344/275/234/346/210/220/343/202/254/343/202/244/343/203/211.md +430 -430
  260. package/lib/assets/docs/reference//351/201/213/347/224/250/350/246/201/344/273/266/345/256/232/347/276/251/343/202/254/343/202/244/343/203/211.md +402 -402
  261. package/lib/assets/docs/reference//351/226/213/347/231/272/343/202/254/343/202/244/343/203/211.md +314 -314
  262. package/lib/assets/docs/reference//351/235/236/346/251/237/350/203/275/350/246/201/344/273/266/345/256/232/347/276/251/343/202/254/343/202/244/343/203/211.md +1246 -1246
  263. package/lib/assets/docs/requirements/index.md +17 -17
  264. package/lib/assets/docs/review/index.md +5 -5
  265. package/lib/assets/docs/strategy/index.md +17 -17
  266. package/lib/assets/docs/template/ADR.md +39 -39
  267. package/lib/assets/docs/template/AWS/343/202/271/343/203/206/343/203/274/343/202/270/343/203/263/343/202/260/347/222/260/345/242/203/343/202/273/343/203/203/343/203/210/343/202/242/343/203/203/343/203/227/346/211/213/351/240/206/346/233/270.md +1375 -1375
  268. package/lib/assets/docs/template/AWS/343/203/227/343/203/255/343/203/200/343/202/257/343/202/267/343/203/247/343/203/263/347/222/260/345/242/203/343/202/273/343/203/203/343/203/210/343/202/242/343/203/203/343/203/227/346/211/213/351/240/206/346/233/270.md +643 -643
  269. package/lib/assets/docs/template/README.md +59 -59
  270. package/lib/assets/docs/template/index.md +24 -24
  271. package/lib/assets/docs/template//343/201/276/343/201/232/343/201/223/343/202/214/343/202/222/350/252/255/343/202/202/343/201/206/343/203/252/343/202/271/343/203/210.md +21 -21
  272. package/lib/assets/docs/template//343/202/242/343/203/227/343/203/252/343/202/261/343/203/274/343/202/267/343/203/247/343/203/263/351/226/213/347/231/272/347/222/260/345/242/203/343/202/273/343/203/203/343/203/210/343/202/242/343/203/203/343/203/227/346/211/213/351/240/206/346/233/270.md +556 -556
  273. package/lib/assets/docs/template//343/202/244/343/203/206/343/203/254/343/203/274/343/202/267/343/203/247/343/203/263/345/256/214/344/272/206/345/240/261/345/221/212/346/233/270.md +68 -68
  274. package/lib/assets/docs/template//343/202/244/343/203/206/343/203/254/343/203/274/343/202/267/343/203/247/343/203/263/350/250/210/347/224/273.md +336 -336
  275. package/lib/assets/docs/template//343/202/244/343/203/263/343/202/273/343/203/227/343/202/267/343/203/247/343/203/263/343/203/207/343/203/203/343/202/255.md +22 -22
  276. package/lib/assets/docs/template//343/203/223/343/202/270/343/203/215/343/202/271/343/202/242/343/203/274/343/202/255/343/203/206/343/202/257/343/203/201/343/203/243.md +388 -388
  277. package/lib/assets/docs/template//343/203/252/343/203/252/343/203/274/343/202/271/345/256/214/344/272/206/345/240/261/345/221/212/346/233/270.md +284 -284
  278. package/lib/assets/docs/template//343/203/252/343/203/252/343/203/274/343/202/271/350/250/210/347/224/273.md +289 -289
  279. package/lib/assets/docs/template//344/272/213/344/276/213/345/210/206/346/236/220.md +522 -522
  280. package/lib/assets/docs/template//344/274/201/346/245/255/345/210/206/346/236/220.md +582 -582
  281. package/lib/assets/docs/template//345/256/214/345/205/250/345/275/242/345/274/217/343/201/256/343/203/246/343/203/274/343/202/271/343/202/261/343/203/274/343/202/271.md +69 -69
  282. package/lib/assets/docs/template//350/246/201/344/273/266/345/256/232/347/276/251.md +669 -669
  283. package/lib/assets/docs/template//350/250/255/350/250/210.md +183 -183
  284. package/lib/assets/docs/template//351/226/213/347/231/272/347/222/260/345/242/203/343/202/273/343/203/203/343/203/210/343/202/242/343/203/203/343/203/227/346/211/213/351/240/206/346/233/270.md +697 -697
  285. package/lib/assets/gulpfile.js +29 -29
  286. package/lib/assets/mkdocs.yml +151 -147
  287. package/lib/assets/ops/docker/sonarqube-local/docker-compose.yml +57 -57
  288. package/lib/assets/ops/scripts/journal.js +180 -180
  289. package/lib/assets/ops/scripts/mkdocs.js +82 -82
  290. package/lib/assets/ops/scripts/release.js +431 -431
  291. package/lib/assets/ops/scripts/sonar_local.js +726 -726
  292. package/lib/assets/ops/scripts/ssh.js +190 -190
  293. package/lib/assets/ops/scripts/vault.js +299 -299
  294. package/lib/assets/package-lock.json +1673 -1673
  295. package/lib/assets/package.json +45 -45
  296. package/lib/gulpfile.js +37 -37
  297. package/package.json +41 -41
@@ -1,766 +1,766 @@
1
- ---
2
- type: Reference
3
- title: "BDD導入ガイド"
4
- description: "『Living Documentation』の BDD 論に基づき、スリーアミーゴの会話・フィーチャーファイルの構造・仕様詳細・タグ・プロパティベーステストを整理し、日本語 Gherkin の書き方と Cucumber の処理系選定・インストール・ステップ定義・Red-Green-Refactor・生きたドキュメント公開までの実装手順をまとめた導入ガイド。"
5
- tags: [reference]
6
- status: draft
7
- generated: { by: claude-code/claude-opus-5, at: 2026-09-26T01:38:35Z }
8
- ---
9
-
10
- # BDD導入ガイド
11
-
12
- BDDは追加の作業ではなく、正しく開発するということそのものである。ビジネス言語で書かれたシナリオが、そのままテストになり、常にコードと同期した「生きたドキュメント」になる。
13
-
14
- ## BDDは「会話」がすべて
15
-
16
- BDDをテスト技法だと思っているなら、その認識は忘れるべきである。**BDDは知識を効率的に共有するための手法**であり、ツールがなくても実践できる。何よりもまず、BDDは「スリーアミーゴ(Biz / Dev / Tester)」と呼ばれる3つの役割(またはそれ以上)の間で深い会話を促す。
17
-
18
- この会話では、ビジネスドメインの言葉を使った具体的なシナリオを用いることで、認識のズレや曖昧さを早期に発見できる。
19
-
20
- ```plantuml
21
- @startuml
22
- title スリーアミーゴの会話
23
-
24
- left to right direction
25
-
26
- actor "Biz(ビジネス)" as Biz
27
- actor "Dev(開発)" as Dev
28
- actor "Tester(テスター)" as Tester
29
-
30
- Biz <--> Dev : 具体例で\n意図を確かめる
31
- Dev <--> Tester : 具体例で\n振る舞いを確かめる
32
- Biz <--> Tester : 具体例で\n受け入れ条件を確かめる
33
-
34
- note bottom of Dev
35
- ドメイン言語による具体的なシナリオが
36
- 3 者の共通の成果物になる
37
- end note
38
- @enduml
39
- ```
40
-
41
- ## 自動化を伴うBDDは「生きたドキュメント」そのもの
42
-
43
- 会話だけでも十分価値があるが、自動化の手間をかけることでさらに恩恵が得られる。CucumberやSpecFlowのようなツールを使う場合でも、スリーアミーゴの間でドメイン言語を使い続け、具体例(シナリオ)を重視する点は変わらない。シナリオはツール上でテストになると同時に、生きたドキュメントにもなる。
44
-
45
- ### 冗長性と整合性の照合
46
-
47
- BDDのシナリオはアプリケーションの振る舞いを記述するが、ソースコード自体もその振る舞いを記述している。つまり**シナリオとコードは互いに冗長**な関係にある。
48
-
49
- - 良い面:ドメイン言語で書かれたシナリオは、コードを読めないビジネス側の人にも理解できる。
50
- - 悪い面:シナリオとコードが別々に進化すると、①どちらを信頼すべきか分からなくなる、②両者が同期しているかどうか分からなくなる、という2つの問題が生じる。
51
-
52
- そこで必要になるのが**整合性を照合する仕組み(reconciliation mechanism)**である。CucumberやSpecFlowはこの役割を果たし、シナリオとコードという冗長な知識のバランスを取る「天秤」のように働く。
53
-
54
- ツールはシナリオのGiven/Whenから値を抽出してテスト対象コードのパラメータとして渡し、Thenの値を使って結果をアサーションする。これにより、シナリオとコードが自動テストという形で常に検証され続ける。
55
-
56
- ## フィーチャーファイルの構造
57
-
58
- Cucumber/SpecFlowでシナリオをテスト化する際に作成するのが**フィーチャーファイル(feature file)**。プレーンテキストでソースコードと同様にバージョン管理される。
59
-
60
- ### 意図を示すナラティブ
61
-
62
- フィーチャーファイルの冒頭には、そのファイル内の全シナリオの意図を示すナラティブを書く。「In order to(〜するために)… As a(〜として)… I want(〜したい)…」という形式が一般的。「In order to」から書き始めることで、最も重要な「得たい価値」に焦点を当てられる。
63
-
64
- ```
65
- Feature: Fuel Card Transactions anomalies
66
- In order to detect potential fuel card abnormal behavior by drivers
67
- As a fleet manager
68
- I want to automatically detect anomalies in all fuel card transactions
69
- ```
70
-
71
- 日本語 Gherkin で書くと次のようになります。
72
-
73
- ```
74
- # language: ja
75
- 機能: 燃料カード取引の異常検知
76
- ドライバーによる燃料カードの不正な使われ方を検知するために
77
- 車両管理者として
78
- すべての燃料カード取引の異常を自動的に検知したい
79
- ```
80
-
81
- ### シナリオ(Given/When/Then)
82
-
83
- ファイルの残りには、対応する機能に関連するシナリオを列挙する。各シナリオはタイトルを持ち、「Given...When...Then...」のパターンにほぼ従う。
84
-
85
- ```
86
- Scenario: Fuel transaction with more fuel than the vehicle tank can hold
87
- Given that the tank size of the vehicle 23 is 48L
88
- When a transaction is reported for 52L on the fuel card
89
- associated with vehicle 23
90
- Then an anomaly "The fuel transaction of 52L exceeds the tank
91
- size of 48L" is reported
92
- ```
93
-
94
- 日本語 Gherkin では次のようになります。
95
-
96
- ```
97
- # language: ja
98
- シナリオ: 車両のタンク容量を超える給油取引
99
- 前提 車両 23 のタンク容量が 48L である
100
- もし 車両 23 に紐づく燃料カードで
101
- 52L の取引が報告される
102
- ならば 「52L の給油取引がタンク容量 48L を超えています」
103
- という異常が報告される
104
- ```
105
-
106
- 1つのフィーチャーファイルには通常3〜15個のシナリオがあり、ハッピーパスやその亜種、重要なケースを記述する。他にもアウトライン形式や、共通の前提を切り出すバックグラウンドシナリオといった書き方がある(詳細: [docs.cucumber.io/gherkin/reference](https://docs.cucumber.io/gherkin/reference/))。
107
-
108
- ## 仕様の詳細(Specification Details)
109
-
110
- シナリオだけで十分な場合も多いが、会計や金融のような知識密度の高いビジネスドメインでは、抽象的なルールや計算式も必要になる。こうした追加知識は、Wordファイルや社内Wikiに置くのではなく、**意図(ナラティブ)とシナリオ一覧の間に直接埋め込む**のがよい。
111
-
112
- ```
113
- Feature: Fuel Card Transactions anomalies
114
- In order to detect potential fuel card abnormal behavior by drivers
115
- As a fleet manager
116
- I want to automatically detect anomalies in all fuel card transactions
117
-
118
- Description:
119
- The monitoring detects the following anomalies:
120
- * Fuel leakage: whenever capacity > 1 + tolerance,
121
- where capacity = transaction fuel quantity / vehicle tank size
122
- * Transaction too far from the vehicle: whenever distance to
123
- vehicle > threshold, where distance to vehicle = geo-distance (vehicle
124
- coordinates, gas station coordinates),
125
- and where the vehicle coordinates are provided by the GPS
126
- Tracking by (vehicle, timestamp),
127
- and where the gas station coordinates are provided by
128
- geocoding its post address.
129
-
130
- Scenario: Fuel transaction with no anomaly
131
- When a transaction is reported on the fuel card
132
- ... /// more scenarios here
133
- ```
134
-
135
- 日本語 Gherkin では次のようになります。
136
-
137
- ```
138
- # language: ja
139
- 機能: 燃料カード取引の異常検知
140
- ドライバーによる燃料カードの不正な使われ方を検知するために
141
- 車両管理者として
142
- すべての燃料カード取引の異常を自動的に検知したい
143
-
144
- 説明:
145
- この監視では次の異常を検知します。
146
- * 燃料の漏出: 充填率 > 1 + 許容値 となる場合。
147
- ここで充填率 = 取引の給油量 / 車両のタンク容量
148
- * 車両から離れすぎた取引: 車両までの距離 > 閾値 となる場合。
149
- ここで車両までの距離 = 地理的距離(車両の座標、給油所の座標)
150
- であり、車両の座標は GPS トラッキングから(車両、時刻)で取得し、
151
- 給油所の座標は所在地住所のジオコーディングで取得する。
152
-
153
- シナリオ: 異常のない給油取引
154
- もし 燃料カードで取引が報告される
155
- ... /// ここにシナリオを続ける
156
- ```
157
-
158
- この「仕様詳細」欄はツールからは単なるコメント(自由記述)として無視されるが、シナリオのすぐ近くに置くことで、シナリオを変更する際に一緒に更新される可能性が高まる(「見えないものは忘れられる」の逆)。ただし更新が保証されるわけではない。
159
-
160
- ## フィーチャーファイルのタグ
161
-
162
- 各シナリオには**タグ**を付けられる。タグはドキュメンテーションの一種であり、次のような目的で使われる。
163
-
164
- @wip @sprint-23 @bob @team-red @acceptance-criteria @happy-path @nominal @variant @negative @exception @core @fixedincome @interests
165
-
166
- - **プロジェクト管理の知識**:`@wip`(作業中)、担当者名やスプリント名など。作業完了後に削除される一時的なタグ。
167
- - **重要度**:`@acceptance-criteria`(受け入れ基準)、`@happy-path`、`@nominal`、`@variant`、`@negative`、`@exception`、`@core` など。
168
- - **ビジネスドメインのカテゴリ・概念**:`@fixedincome`、`@interests` など、シナリオが属する業務領域を示す。
169
-
170
- タグ自体も文書化すべきで、同じ場所にあるテキストファイルで全タグと説明を一覧化するとよい。
171
-
172
- ### フィーチャーファイルの整理方法
173
-
174
- フィーチャーファイルが増えたらフォルダで整理する。フォルダ構成自体が知識を伝える手段になる。書籍『Specification by Example』(Gojko Adzic)は3つの整理方法を挙げている。
175
-
176
- 1. **機能領域ごと**(例: Accounting / Reporting Rules / Discounts / Special Offers)— 業務ドメインが重要な場合に推奨
177
- 2. **UIのナビゲーション経路に沿って**(UIを文書化する場合)
178
- 3. **業務プロセスに沿って**(エンドツーエンドのトレーサビリティが必要な場合)
179
-
180
- ## インタラクティブな生きたドキュメントとしてのシナリオ
181
-
182
- シナリオは生きたドキュメントの基礎となるが、さらに一歩進めると、ビルドごとに生成される**インタラクティブなWebサイト**にもなる。SpecFlow向けの **Pickles** はその一例で、フォルダ構成をチャプターとして表示するナビゲーションと、タグ・キーワードによる検索機能を備えた1ページサイトを生成する。
183
-
184
- この検索エンジンにより、タグの2つ目の効果が発揮される:**タグはシナリオの検索を効率的かつ正確にする**。
185
-
186
- ### 紙のドキュメントが必要な場合
187
-
188
- コンプライアンス要件などにより紙の文書(「BPD: Boring Paper Document」)が必要な場合もある。著者の同僚 Arnauld Loyer(@aloyer)が開発した **Tzatziki** というツールは、フィーチャーファイルから美しいPDFを書き出す。さらにMarkdownファイルや画像も取り込み、各機能領域チャプターの冒頭に説明を追加できる。
189
-
190
- BDDは生きたドキュメントの好例である。それは「やるべき仕事」に追加される作業ではなく、正しく仕事をすることそのものの一部である。整合性を照合するツールのおかげで常に同期しており、フィーチャーファイルだけで足りない場合は、生成されたWebサイトがドキュメントを有用・インタラクティブ・検索可能・整理された状態にする方法を示してくれる。
191
-
192
- ## フィーチャーファイルの完全な例
193
-
194
- 金融ドメインを題材にした架空だが現実的な例。1つのアウトラインシナリオと対応するデータテーブルを含む。
195
-
196
- ```
197
- Feature: Calculate compound interests on a principal
198
- In order to manage the company money
199
- As a finance officer
200
- I want to calculate the compound interests on a principal on
201
- my account
202
-
203
- Description:
204
- Compound interest is when the bank pays interest on both the
205
- principal (the original amount of money) and the interest an
206
- account has already earned.
207
-
208
- To calculate compound interest use the formula below.
209
-
210
- In the formula, A represents the final amount in the account
211
- after t years compounded 'n' times at interest rate 'r' with
212
- starting amount 'p'.
213
-
214
- A = P*(1+(r/n))^n*t
215
-
216
- Scenario: Bi-annual compound interests over one year
217
- Given a principal of USD 1000
218
- And interests are compounded bi-annually at a rate of 5%
219
- And the calculation period lasts exactly 1 year
220
- When the calculation period lasts exactly 1 year
221
- Then the amount of money in the account is USD 1053.63
222
-
223
- Scenario: Quarterly compound interests over one year
224
- //... outline scenario
225
-
226
- Examples:
227
- | convention | rate | time | amount | remarks |
228
- |-------------|------|------|-----------|----------------|
229
- | LINEAR | 0.05 | 2 | 0.100000 | (1+rt)-1 |
230
- | COMPOUND | 0.05 | 2 | 0.102500 | (1+r)^t-1 |
231
- | DISCOUNT | 0.05 | 2 | -0.100000 | (1-rt)-1 |
232
- | CONTINUOUS | 0.05 | 2 | 0.105171 | (e^rt)-1 (rare)|
233
- | NONE | 0.05 | 2 | 0 | 0 |
234
- ```
235
-
236
- ツールの支援があれば、すべてのビジネスシナリオは自動テストであると同時に生きたドキュメントになる。シナリオとコードの橋渡しは、**ステップ(step)**という仕組みで行う。各ステップは正規表現でマッチし、シナリオ中のテキストからパラメータを抽出して本番コードを呼び出す。
237
-
238
- ```
239
- "When I buy a book at an ex-VAT price of EUR <exVATPrice>"
240
-
241
- // 対応するグルーコード
242
- Book(number exVATPrice)
243
- Service = LookupOrderService();
244
- Service.sendOrder(exVATPrice);
245
- ```
246
-
247
- 日本語のステップでも同じ仕組みです。ただしパラメータの位置が変わるため、
248
- ステップ定義の正規表現は日本語の文面に合わせて書き直します。
249
-
250
- ```
251
- "もし 税抜価格 EUR <exVATPrice> の本を購入する"
252
-
253
- // 対応するグルーコード
254
- Book(number exVATPrice)
255
- Service = LookupOrderService();
256
- Service.sendOrder(exVATPrice);
257
- ```
258
-
259
- ## 日本語 Gherkin で書く
260
-
261
- Gherkin は多言語のキーワードをサポートしており、フィーチャーファイルの先頭に `# language: ja` と書くと日本語のキーワードが使えます。BDD の価値は会話そのものにあるので、シナリオはビジネス側が普段読み書きする言語で書くのが原則です。日本語で業務を語るチームなら、シナリオも日本語で書きます。
262
-
263
- | 英語 | 日本語 |
264
- | :--- | :--- |
265
- | Feature | 機能 |
266
- | Background | 背景 |
267
- | Rule | ルール |
268
- | Scenario | シナリオ |
269
- | Scenario Outline | シナリオテンプレート(シナリオアウトライン) |
270
- | Examples | 例 |
271
- | Given | 前提 |
272
- | When | もし |
273
- | Then | ならば |
274
- | And | かつ |
275
- | But | しかし |
276
-
277
- 前掲の複利計算の例を日本語 Gherkin で書くと次のようになります。英語版と 1 対 1 で読み比べられます。
278
-
279
- ```
280
- # language: ja
281
- 機能: 元本に対する複利の計算
282
- 会社の資金を管理するために
283
- 財務担当者として
284
- 口座の元本に対する複利を計算したい
285
-
286
- 説明:
287
- 複利とは、元本(もともとの金額)と、口座がすでに獲得した利息の
288
- 両方に対して銀行が利息を支払うことをいいます。
289
-
290
- 複利は次の式で計算します。年利 r、年 n 回の複利、元本 P、期間 t 年
291
- のとき、t 年後の口座残高 A は次のとおりです。
292
-
293
- A = P*(1+(r/n))^n*t
294
-
295
- 背景:
296
- 前提 口座の通貨は USD である
297
-
298
- シナリオ: 1 年間の半年複利
299
- 前提 元本が USD 1000 である
300
- かつ 年利 5% で半年ごとに複利計算される
301
- かつ 計算期間がちょうど 1 年である
302
- もし 利息を計算する
303
- ならば 口座の残高は USD 1053.63 である
304
-
305
- シナリオテンプレート: 利息計算方式ごとの利息額
306
- 前提 年利が <利率> である
307
- かつ 計算期間が <期間> 年である
308
- もし 利息計算方式 <方式> で利息を計算する
309
- ならば 利息額は <利息額> である
310
-
311
- 例:
312
- | 方式 | 利率 | 期間 | 利息額 | 備考 |
313
- | 単利 | 0.05 | 2 | 0.100000 | (1+rt)-1 |
314
- | 複利 | 0.05 | 2 | 0.102500 | (1+r)^t-1 |
315
- | 割引 | 0.05 | 2 | -0.100000 | (1-rt)-1 |
316
- | 連続複利 | 0.05 | 2 | 0.105171 | (e^rt)-1(まれ)|
317
- | なし | 0.05 | 2 | 0 | 0 |
318
- ```
319
-
320
- 日本語で書く場合の注意点は 3 つあります。
321
-
322
- - ステップ定義(グルーコード)側の正規表現も、日本語のステップ文字列にマッチするように書きます。パラメータの抽出位置が英語とは異なるため、英語のステップ定義をそのまま流用できません
323
- - 1 つのプロジェクト内で英語と日本語のフィーチャーファイルを混在させません。検索性が落ち、用語の揺れが生まれます
324
- - シナリオで使う用語は、後述の用語集(グロッサリー)と表記を揃えます。「顧客」と「お客様」のような揺れは、そのままドメイン理解の揺れになります
325
-
326
- ## BDDが「生きたドキュメント」の典型例である理由
327
-
328
- BDDは正確なドキュメントが常にコードと同期する状態を実現できることを示した。生きたドキュメントの中核原則は、すべてすでにBDDに備わっている。
329
-
330
- 01
331
-
332
- #### 協働的(Collaborative)
333
-
334
- BDDの主要な手段は「対話」であり、スリーアミーゴ(またはそれ以上)の各役割が必ず参加する。
335
-
336
- 02
337
-
338
- #### 低コスト(Low-effort)
339
-
340
- 具体例をめぐる会話は、何を作るかの合意形成に有用で、少しの追加作業で自動テストと生きたドキュメントの両方になる — 1つの活動で複数の恩恵。
341
-
342
- 03
343
-
344
- #### 信頼できる(Reliable)
345
-
346
- 整合性照合の仕組みのおかげで信頼できる。振る舞いがテキストシナリオと実装コードの両方に記述されるため、CucumberやSpecFlowのようなツールがシナリオとコードの同期を保証(または、ズレを検知)する。これは知識の重複がある場合に必ず必要になる。
347
-
348
- ### 会話がもたらす洞察(Insightful)
349
-
350
- 会話はフィードバックを提供する。シナリオが長すぎたり不自然だったりする場合、それは暗黙の概念が欠けているサインであり、より短くシンプルなシナリオを示唆してくれる。
351
-
352
- ### 対象読者(Targeted audience)
353
-
354
- すべての作業はビジネス要件を議論する際、技術者以外も含む読者を対象としているため、明確で非技術的な言葉遣いに重点を置く。
355
-
356
- ### 知識の沈殿(Idea sedimentation)
357
-
358
- 会話だけで十分なことも多く、すべてを書き留める必要はない。アーカイブや自動化のために書き留めるべきなのは、最も重要なシナリオ(キーシナリオ)だけでよい。
359
-
360
- ### プレーンテキストの文書(Plain-text documents)
361
-
362
- 変化するものをソースコードと一緒にバージョン管理するには、プレーンテキストが非常に便利である。
363
-
364
- ### アクセス可能な公開スナップショット(Accessible published snapshot)
365
-
366
- 誰もがソースコードにアクセスしてシナリオを読めるわけではない。PickleやTzatzikiのようなツールは、ある時点でのシナリオ全体のスナップショットを、インタラクティブなWebサイトや印刷可能なPDF文書としてエクスポートすることで解決する。
367
-
368
- ## ドキュメントを最大限活かすために(さらに一歩先へ)
369
-
370
- フィーチャーファイルは、豊かなドメイン知識を効率よく集める良い場所である。BDDを支援するほとんどのツールは Gherkin 構文という固定フォーマットを理解する。
371
-
372
- ```
373
- Feature: Name of the feature
374
-
375
- In order to... As a... I want...
376
-
377
- Scenario: name of the first scenario
378
- Given...
379
- When...
380
- Then...
381
-
382
- Scenario: name of the second scenario
383
- ...
384
- ```
385
-
386
- 日本語 Gherkin での骨子は次のとおりです。
387
-
388
- ```
389
- # language: ja
390
- 機能: 機能の名前
391
-
392
- 〜するために... 〜として... 〜したい...
393
-
394
- シナリオ: 1 つ目のシナリオの名前
395
- 前提 ...
396
- もし ...
397
- ならば ...
398
-
399
- シナリオ: 2 つ目のシナリオの名前
400
- ...
401
- ```
402
-
403
- 金融や保険のようなリッチなドメインを扱うチームは、冒頭の意図と末尾の具体シナリオだけでは足りないと気づき、中間領域に追加の説明を書き込むようになった。これはツールからは無視されるが、Pickles のようなツールはこの「説明エリア」でMarkdown記法をサポートするよう対応した。
404
-
405
- ### 例:投資の現在価値
406
-
407
- ```
408
- Feature: Investment Present Value
409
-
410
- In order to calculate the breakeven point of the investment
411
- opportunity
412
- As an investment manager
413
- I want to calculate the present value of future cash amounts
414
-
415
- Description
416
- ===========
417
- We need to find the present value *PV* of the given future cash
418
- amount *FV*. The formula for that can be expressed as:
419
-
420
- - Using the negative exponent notation:
421
- PV = FV * (1 + i)^(-n)
422
- - Or in the equivalent form:
423
- PV = FV * (1 / (1 + i)^n)
424
-
425
- Example
426
- -------
427
- For example, n = 2, i = 8%
428
-
429
- FV = $100
430
- |
431
- PV? ------|----------> t (years)
432
- 0 1 2
433
-
434
- Scenario: Present Value of a single cash amount
435
- Given a future cash amount of 100$ in 2 years
436
- And an interest rate of 8%
437
- When we calculate its present value
438
- Then its present value is $85.73
439
- ```
440
-
441
- 日本語 Gherkin では次のようになります。説明エリアも日本語で書けます。
442
-
443
- ```
444
- # language: ja
445
- 機能: 投資の現在価値
446
-
447
- 投資機会の損益分岐点を計算するために
448
- 投資マネージャーとして
449
- 将来のキャッシュ金額の現在価値を計算したい
450
-
451
- 説明
452
- ====
453
- 将来のキャッシュ金額 *FV* に対する現在価値 *PV* を求めます。
454
- 計算式は次のように表せます。
455
-
456
- - 負の指数表記を使う場合:
457
- PV = FV * (1 + i)^(-n)
458
- - 同等の別表記:
459
- PV = FV * (1 / (1 + i)^n)
460
-
461
- 例
462
- --
463
- たとえば n = 2、i = 8% のとき
464
-
465
- FV = $100
466
- |
467
- PV? ------|----------> t(年)
468
- 0 1 2
469
-
470
- シナリオ: 単一のキャッシュ金額の現在価値
471
- 前提 2 年後に受け取る将来キャッシュ金額が 100$ である
472
- かつ 利率が 8% である
473
- もし その現在価値を計算する
474
- ならば 現在価値は $85.73 である
475
- ```
476
-
477
- ベストプラクティス
478
-
479
- 頻繁には変わらない知識は「説明エリア」に、変わりやすい部分は具体的なシナリオの中に置くのがよい戦略である。説明が使う数値はあくまで「サンプル」であり、ある時点の業務プロセスの設定値そのものではないと明示するのも一つの方法。ただし、説明エリアの内容はシナリオと違って本当の意味では「生きて」いない — シナリオを変更すれば近くの説明も更新したくなるはずだが、それが保証されるわけではない。
480
-
481
- PickleやRelish、Tzatzikiのようなツールは、フィーチャーファイルの隣に置かれたMarkdown記法の説明やプレーンなMarkdownファイルを理解できるようになっており、金融業界の規制当局が求めるような、一貫したドメインドキュメントの取りまとめを容易にする。
482
-
483
- ## プロパティベーステストとBDD
484
-
485
- 要件はしばしば「プロパティ(性質)」として自然に表現できる。例:「すべての支払・受取金額の合計は常にゼロでなければならない」「誰も同時に売り手であり買い手でありジャッジであることはできない」。BDDやTDDでは、こうした一般的な性質を具体的な例に落とし込む必要があるが、それは問題やコードを段階的に構築する助けになる。
486
-
487
- 一般的な性質の値を追跡するには、通常フィーチャーファイル内のプレーンテキストコメントとして記述する。しかし、まさにこの「性質をランダム生成サンプルに対して検証する」技術こそが**プロパティベーステスト**であり、Haskellの **QuickCheck** が代表的なフレームワーク(他の言語にも同様のツールが存在)。
488
-
489
- ```
490
- Scenario: The sum of all cash amounts exchanged must be zero
491
- for derivatives
492
-
493
- Given any derivative financial instrument
494
- And a random date during its lifetime
495
- When we generate the related cash flows on this date for the
496
- payer and\
497
- the receiver
498
- Then the sum of the cash flows of the payer and the receiver
499
- is\
500
- exactly zero
501
- ```
502
-
503
- 日本語 Gherkin では次のようになります。
504
-
505
- ```
506
- # language: ja
507
- シナリオ: デリバティブでは授受されるすべての金額の合計がゼロである
508
-
509
- 前提 任意のデリバティブ金融商品がある
510
- かつ その存続期間中の任意の日付がある
511
- もし その日付における支払側と受取側のキャッシュフローを生成する
512
- ならば 支払側と受取側のキャッシュフローの合計は
513
- ちょうどゼロである
514
- ```
515
-
516
- 「given ANY shopping cart...」のような表現は、通常のシナリオでは避けるべき「コードの臭い」だが、プロパティベーステストを補完するプロパティ指向のシナリオでは問題ない。
517
-
518
- ## 用語集(グロッサリー)の作成
519
-
520
- 理想的な用語集はコードから直接抽出される「生きた」ものだが、多くの場合それは不可能で手動作成が必要になる。フィーチャーファイルと同じ場所にMarkdownファイルとして用語集を手作業で作成すれば、他のフィーチャーファイルと一緒に生きたドキュメントサイトに含めることができる。空のダミーのフィーチャーファイルとして作成することも可能。
521
-
522
- ## 非機能的な知識へのリンク
523
-
524
- すべての知識を同じ場所に記述すべきではない。UI固有・レガシー固有の知識をドメイン知識と混在させたくない。そうした関連知識が重要な場合は別の場所に保存し、リンクで関係性を表現し見つけやすくする。3つのリンク方法がある。
525
-
526
- - **URLへの直接リンク** — リンク切れのリスクあり\
527
- `https://en.wikipedia.org/wiki/Present_value`
528
- - **リンクレジストリ経由** — リンク切れを差し替えやすい\
529
- `go/search?q=present+value`
530
- - **ブックマーク検索** — 関連コンテンツを含む場所へのリンク\
531
- `https://en.wikipedia.org/w/index.php?search=present+value`
532
-
533
- 非機能的な知識へのリンクは、関連コンテンツへの堅牢な接続方法を提供するが、その分、読者自身が最も関連性の高い結果を選ぶ手間が発生する。
534
-
535
- ## Cucumber の実装ガイド
536
-
537
- ここまでは Gherkin の書き方を扱ってきました。ここからは、フィーチャーファイルを実際に動く自動テストにするための実装手順を扱います。出典は [Cucumber 公式のインストールガイド](https://cucumber.io/docs/installation/) と [10 Minute Tutorial](https://cucumber.io/docs/guides/10-minute-tutorial/) です。
538
-
539
- ### 処理系を選ぶ
540
-
541
- Cucumber は 30 以上の言語・プラットフォームに実装があります。メンテナンス状況で 3 つに分かれているので、新規採用では公式(Official)か準公式(Semi-official)から選びます。
542
-
543
- | 区分 | 処理系 | 言語 |
544
- | :--- | :--- | :--- |
545
- | 公式 | Cucumber-JS | JavaScript / TypeScript |
546
- | 公式 | Cucumber-JVM | Java / Kotlin |
547
- | 公式 | Cucumber-Ruby | Ruby |
548
- | 公式 | Cucumber-Scala | Scala |
549
- | 公式 | Cucumber.cpp | C++ |
550
- | 準公式 | Behave、Pytest-BDD | Python |
551
- | 準公式 | Behat | PHP |
552
- | 準公式 | Reqnroll | .NET(C# / F# / VB) |
553
- | 準公式 | gocuke | Go |
554
- | 準公式 | Test::BDD::Cucumber | Perl |
555
-
556
- .NET の SpecFlow は開発が終了しており、後継は Reqnroll です。非公式(Cucumber-Rust、GoBDD など)や未メンテナンス(Cucumber-Groovy、Godog など)の処理系は、採用前に最終更新日を確認します。
557
-
558
- ### インストール
559
-
560
- 処理系ごとのインストールは次のとおりです。バージョンは執筆時点のものなので、採用時に最新を確認してください。
561
-
562
- ```
563
- # JavaScript / TypeScript(Cucumber-JS)
564
- npm install --save-dev @cucumber/cucumber
565
-
566
- # Ruby(Cucumber-Ruby)
567
- gem install cucumber
568
-
569
- # Python(Behave / Pytest-BDD)
570
- pip install behave
571
- pip install pytest-bdd
572
-
573
- # .NET(Reqnroll)
574
- dotnet add package Reqnroll.NUnit
575
- ```
576
-
577
- Java の場合は Maven のアーキタイプからプロジェクトを生成できます。
578
-
579
- ```
580
- mvn archetype:generate \
581
- "-DarchetypeGroupId=io.cucumber" \
582
- "-DarchetypeArtifactId=cucumber-archetype" \
583
- "-DarchetypeVersion=8.0.1" \
584
- "-DgroupId=hellocucumber" \
585
- "-DartifactId=hellocucumber" \
586
- "-Dpackage=hellocucumber" \
587
- "-Dversion=1.0.0-SNAPSHOT" \
588
- "-DinteractiveMode=false"
589
- ```
590
-
591
- Cucumber-JS で特に注意すべき落とし穴が 2 つあります。
592
-
593
- - **グローバルインストールしない** — Cucumber-JS は実行中に状態を保持するため、プロジェクトの依存として入れます。グローバルに入れると「You're calling functions (e.g. 'Given') on an instance of Cucumber that isn't running.」というエラーになります
594
- - **依存ツリーに複数バージョンを混在させない** — `npm why @cucumber/cucumber` で重複を確認します。共有ライブラリが Cucumber に依存している場合は peer dependency にします。パッケージ名も旧 `cucumber` ではなく `@cucumber/cucumber` を使います
595
-
596
- ### ディレクトリ構成
597
-
598
- フィーチャーファイルとステップ定義は、処理系が決めた場所に置きます。
599
-
600
- ```
601
- # Cucumber-JS
602
- features/
603
- ├── is_it_friday_yet.feature
604
- └── step_definitions/
605
- └── stepdefs.js
606
-
607
- # Cucumber-JVM(Maven)
608
- src/test/resources/hellocucumber/
609
- └── is_it_friday_yet.feature
610
- src/test/java/hellocucumber/
611
- └── StepDefinitions.java
612
- ```
613
-
614
- フィーチャーファイルが増えたら、前述の「フィーチャーファイルの整理方法」に従って機能領域ごとにフォルダを切ります。
615
-
616
- ### 最小の例
617
-
618
- 公式チュートリアルの「金曜日かどうか」を日本語 Gherkin で書くと次のようになります。
619
-
620
- ```
621
- # language: ja
622
- 機能: もう金曜日?
623
- みんな、いつ金曜日になるのかを知りたい
624
-
625
- シナリオテンプレート: 今日は金曜日である、またはそうでない
626
- 前提 今日は "<曜日>" である
627
- もし 金曜日かどうか尋ねる
628
- ならば "<答え>" と返ってくる
629
-
630
- 例:
631
- | 曜日 | 答え |
632
- | 金曜日 | TGIF |
633
- | 日曜日 | まだ |
634
- | それ以外 | まだ |
635
- ```
636
-
637
- ステップ定義は、シナリオの文面にマッチする関数として書きます。Cucumber-JS の場合は次のとおりです。
638
-
639
- ```
640
- const assert = require('assert');
641
- const { Given, When, Then } = require('@cucumber/cucumber');
642
-
643
- function isItFriday(today) {
644
- return today === '金曜日' ? 'TGIF' : 'まだ';
645
- }
646
-
647
- Given('今日は {string} である', function (today) {
648
- this.today = today;
649
- });
650
-
651
- When('金曜日かどうか尋ねる', function () {
652
- this.actualAnswer = isItFriday(this.today);
653
- });
654
-
655
- Then('{string} と返ってくる', function (expectedAnswer) {
656
- assert.strictEqual(this.actualAnswer, expectedAnswer);
657
- });
658
- ```
659
-
660
- Cucumber-JVM(Java)では、アノテーションでステップを宣言します。
661
-
662
- ```
663
- package hellocucumber;
664
-
665
- import io.cucumber.java.en.Given;
666
- import io.cucumber.java.en.When;
667
- import io.cucumber.java.en.Then;
668
- import static org.assertj.core.api.Assertions.assertThat;
669
-
670
- class IsItFriday {
671
- static String isItFriday(String today) {
672
- return "金曜日".equals(today) ? "TGIF" : "まだ";
673
- }
674
- }
675
-
676
- public class StepDefinitions {
677
- private String today;
678
- private String actualAnswer;
679
-
680
- @Given("今日は {string} である")
681
- public void today_is(String today) {
682
- this.today = today;
683
- }
684
-
685
- @When("金曜日かどうか尋ねる")
686
- public void i_ask_whether_it_s_friday_yet() {
687
- actualAnswer = IsItFriday.isItFriday(today);
688
- }
689
-
690
- @Then("{string} と返ってくる")
691
- public void i_should_be_told(String expectedAnswer) {
692
- assertThat(actualAnswer).isEqualTo(expectedAnswer);
693
- }
694
- }
695
- ```
696
-
697
- 日本語のフィーチャーファイルを使う場合でも、ステップ定義側のアノテーション(`@Given` など)は英語のままで構いません。キーワードの言語(`前提` / `もし` / `ならば`)は `# language: ja` で解決され、アノテーションにはキーワードを除いたステップ本文がマッチします。
698
-
699
- ### 実行する
700
-
701
- ```
702
- # Cucumber-JS
703
- npx cucumber-js
704
-
705
- # Cucumber-JVM(Maven)
706
- mvn test
707
-
708
- # Cucumber-Ruby
709
- cucumber
710
-
711
- # Behave
712
- behave
713
- ```
714
-
715
- ### Red-Green-Refactor で進める
716
-
717
- Cucumber の実行結果は、そのまま TDD のサイクルになります。
718
-
719
- ```plantuml
720
- @startuml
721
- title Cucumber での Red-Green-Refactor
722
-
723
- [*] --> シナリオを書く
724
- シナリオを書く --> Undefined : 実行する
725
- Undefined --> ステップ定義を書く : 提案されたスニペットを貼る
726
- ステップ定義を書く --> Pending
727
- Pending --> Failing : アサーションを書く
728
- Failing --> Passing : 最小限の実装を書く
729
- Passing --> リファクタリング
730
- リファクタリング --> Passing : テストは緑のまま
731
- リファクタリング --> シナリオを書く : 次のシナリオへ
732
- リファクタリング --> [*]
733
-
734
- Undefined : ステップ定義が無い
735
- Pending : 未実装の例外を投げる
736
- Failing : 期待値と一致しない(Red)
737
- Passing : シナリオが通る(Green)
738
- @enduml
739
- ```
740
-
741
- 1. **Undefined** — シナリオだけがある状態。Cucumber は未定義ステップを報告し、貼り付け可能なステップ定義のスニペットを提案します
742
- 2. **Pending** — スニペットを貼った状態。ステップは未実装例外を投げます
743
- 3. **Failing(Red)** — アサーションを書くと、実装がないため落ちます
744
- 4. **Passing(Green)** — 最小限の実装で通します。最初はハードコードで構いません
745
- 5. **Refactor** — 実装をプロダクションコードへ移し、重複を取り除きます。ステップ定義は薄く保ち、業務ロジックを持ち込みません
746
-
747
- この流れは AI-DLC の Bolt におけるステップ計画と対応します。シナリオが受入条件、Cucumber の実行結果が承認ゲートでの検証材料になります。
748
-
749
- ### 生きたドキュメントとして公開する
750
-
751
- フィーチャーファイルを Web サイトや PDF として公開すると、前述の「インタラクティブな生きたドキュメント」になります。
752
-
753
- | ツール | 出力 | 対象 |
754
- | :--- | :--- | :--- |
755
- | Pickles | 検索可能な HTML サイト | Reqnroll / SpecFlow、Cucumber 全般 |
756
- | Relish | ホスティング型の HTML サイト | Cucumber 全般 |
757
- | Tzatziki | PDF | Cucumber 全般 |
758
- | Cucumber Reports | 実行結果レポート | Cucumber 全般 |
759
-
760
- 公開はビルドの一部として自動化します。手作業で生成する運用にすると、すぐに更新されなくなり「生きた」状態を失います。
761
-
762
- ## まとめ
763
-
764
- BDDは生きたドキュメントの典型例である。まず何よりチームメンバー間の頻繁な会話に頼り、それでいてビジネス側にも開発者側にもアクセス可能な形で、プロジェクト中に集めた知識を保存する。コードとシナリオという冗長な知識を生むにもかかわらず、付随するツールがすべてを同期させ続ける。BDDが扱うのはソフトウェアのビジネス上の振る舞いだけだが、以降の章ではこの考え方をソフトウェア開発に関する他の活動、さらにはソフトウェア開発の外にまで拡張していく。
765
-
766
- 出典: *Living Documentation*(Cyrille Martraire 著)第2章「Behavior-Driven Development as an Example of Living Specifications」(p.56–70)の要約
1
+ ---
2
+ type: Reference
3
+ title: "BDD導入ガイド"
4
+ description: "『Living Documentation』の BDD 論に基づき、スリーアミーゴの会話・フィーチャーファイルの構造・仕様詳細・タグ・プロパティベーステストを整理し、日本語 Gherkin の書き方と Cucumber の処理系選定・インストール・ステップ定義・Red-Green-Refactor・生きたドキュメント公開までの実装手順をまとめた導入ガイド。"
5
+ tags: [reference]
6
+ status: draft
7
+ generated: { by: claude-code/claude-opus-5, at: 2026-09-26T01:38:35Z }
8
+ ---
9
+
10
+ # BDD導入ガイド
11
+
12
+ BDDは追加の作業ではなく、正しく開発するということそのものである。ビジネス言語で書かれたシナリオが、そのままテストになり、常にコードと同期した「生きたドキュメント」になる。
13
+
14
+ ## BDDは「会話」がすべて
15
+
16
+ BDDをテスト技法だと思っているなら、その認識は忘れるべきである。**BDDは知識を効率的に共有するための手法**であり、ツールがなくても実践できる。何よりもまず、BDDは「スリーアミーゴ(Biz / Dev / Tester)」と呼ばれる3つの役割(またはそれ以上)の間で深い会話を促す。
17
+
18
+ この会話では、ビジネスドメインの言葉を使った具体的なシナリオを用いることで、認識のズレや曖昧さを早期に発見できる。
19
+
20
+ ```plantuml
21
+ @startuml
22
+ title スリーアミーゴの会話
23
+
24
+ left to right direction
25
+
26
+ actor "Biz(ビジネス)" as Biz
27
+ actor "Dev(開発)" as Dev
28
+ actor "Tester(テスター)" as Tester
29
+
30
+ Biz <--> Dev : 具体例で\n意図を確かめる
31
+ Dev <--> Tester : 具体例で\n振る舞いを確かめる
32
+ Biz <--> Tester : 具体例で\n受け入れ条件を確かめる
33
+
34
+ note bottom of Dev
35
+ ドメイン言語による具体的なシナリオが
36
+ 3 者の共通の成果物になる
37
+ end note
38
+ @enduml
39
+ ```
40
+
41
+ ## 自動化を伴うBDDは「生きたドキュメント」そのもの
42
+
43
+ 会話だけでも十分価値があるが、自動化の手間をかけることでさらに恩恵が得られる。CucumberやSpecFlowのようなツールを使う場合でも、スリーアミーゴの間でドメイン言語を使い続け、具体例(シナリオ)を重視する点は変わらない。シナリオはツール上でテストになると同時に、生きたドキュメントにもなる。
44
+
45
+ ### 冗長性と整合性の照合
46
+
47
+ BDDのシナリオはアプリケーションの振る舞いを記述するが、ソースコード自体もその振る舞いを記述している。つまり**シナリオとコードは互いに冗長**な関係にある。
48
+
49
+ - 良い面:ドメイン言語で書かれたシナリオは、コードを読めないビジネス側の人にも理解できる。
50
+ - 悪い面:シナリオとコードが別々に進化すると、①どちらを信頼すべきか分からなくなる、②両者が同期しているかどうか分からなくなる、という2つの問題が生じる。
51
+
52
+ そこで必要になるのが**整合性を照合する仕組み(reconciliation mechanism)**である。CucumberやSpecFlowはこの役割を果たし、シナリオとコードという冗長な知識のバランスを取る「天秤」のように働く。
53
+
54
+ ツールはシナリオのGiven/Whenから値を抽出してテスト対象コードのパラメータとして渡し、Thenの値を使って結果をアサーションする。これにより、シナリオとコードが自動テストという形で常に検証され続ける。
55
+
56
+ ## フィーチャーファイルの構造
57
+
58
+ Cucumber/SpecFlowでシナリオをテスト化する際に作成するのが**フィーチャーファイル(feature file)**。プレーンテキストでソースコードと同様にバージョン管理される。
59
+
60
+ ### 意図を示すナラティブ
61
+
62
+ フィーチャーファイルの冒頭には、そのファイル内の全シナリオの意図を示すナラティブを書く。「In order to(〜するために)… As a(〜として)… I want(〜したい)…」という形式が一般的。「In order to」から書き始めることで、最も重要な「得たい価値」に焦点を当てられる。
63
+
64
+ ```
65
+ Feature: Fuel Card Transactions anomalies
66
+ In order to detect potential fuel card abnormal behavior by drivers
67
+ As a fleet manager
68
+ I want to automatically detect anomalies in all fuel card transactions
69
+ ```
70
+
71
+ 日本語 Gherkin で書くと次のようになります。
72
+
73
+ ```
74
+ # language: ja
75
+ 機能: 燃料カード取引の異常検知
76
+ ドライバーによる燃料カードの不正な使われ方を検知するために
77
+ 車両管理者として
78
+ すべての燃料カード取引の異常を自動的に検知したい
79
+ ```
80
+
81
+ ### シナリオ(Given/When/Then)
82
+
83
+ ファイルの残りには、対応する機能に関連するシナリオを列挙する。各シナリオはタイトルを持ち、「Given...When...Then...」のパターンにほぼ従う。
84
+
85
+ ```
86
+ Scenario: Fuel transaction with more fuel than the vehicle tank can hold
87
+ Given that the tank size of the vehicle 23 is 48L
88
+ When a transaction is reported for 52L on the fuel card
89
+ associated with vehicle 23
90
+ Then an anomaly "The fuel transaction of 52L exceeds the tank
91
+ size of 48L" is reported
92
+ ```
93
+
94
+ 日本語 Gherkin では次のようになります。
95
+
96
+ ```
97
+ # language: ja
98
+ シナリオ: 車両のタンク容量を超える給油取引
99
+ 前提 車両 23 のタンク容量が 48L である
100
+ もし 車両 23 に紐づく燃料カードで
101
+ 52L の取引が報告される
102
+ ならば 「52L の給油取引がタンク容量 48L を超えています」
103
+ という異常が報告される
104
+ ```
105
+
106
+ 1つのフィーチャーファイルには通常3〜15個のシナリオがあり、ハッピーパスやその亜種、重要なケースを記述する。他にもアウトライン形式や、共通の前提を切り出すバックグラウンドシナリオといった書き方がある(詳細: [docs.cucumber.io/gherkin/reference](https://docs.cucumber.io/gherkin/reference/))。
107
+
108
+ ## 仕様の詳細(Specification Details)
109
+
110
+ シナリオだけで十分な場合も多いが、会計や金融のような知識密度の高いビジネスドメインでは、抽象的なルールや計算式も必要になる。こうした追加知識は、Wordファイルや社内Wikiに置くのではなく、**意図(ナラティブ)とシナリオ一覧の間に直接埋め込む**のがよい。
111
+
112
+ ```
113
+ Feature: Fuel Card Transactions anomalies
114
+ In order to detect potential fuel card abnormal behavior by drivers
115
+ As a fleet manager
116
+ I want to automatically detect anomalies in all fuel card transactions
117
+
118
+ Description:
119
+ The monitoring detects the following anomalies:
120
+ * Fuel leakage: whenever capacity > 1 + tolerance,
121
+ where capacity = transaction fuel quantity / vehicle tank size
122
+ * Transaction too far from the vehicle: whenever distance to
123
+ vehicle > threshold, where distance to vehicle = geo-distance (vehicle
124
+ coordinates, gas station coordinates),
125
+ and where the vehicle coordinates are provided by the GPS
126
+ Tracking by (vehicle, timestamp),
127
+ and where the gas station coordinates are provided by
128
+ geocoding its post address.
129
+
130
+ Scenario: Fuel transaction with no anomaly
131
+ When a transaction is reported on the fuel card
132
+ ... /// more scenarios here
133
+ ```
134
+
135
+ 日本語 Gherkin では次のようになります。
136
+
137
+ ```
138
+ # language: ja
139
+ 機能: 燃料カード取引の異常検知
140
+ ドライバーによる燃料カードの不正な使われ方を検知するために
141
+ 車両管理者として
142
+ すべての燃料カード取引の異常を自動的に検知したい
143
+
144
+ 説明:
145
+ この監視では次の異常を検知します。
146
+ * 燃料の漏出: 充填率 > 1 + 許容値 となる場合。
147
+ ここで充填率 = 取引の給油量 / 車両のタンク容量
148
+ * 車両から離れすぎた取引: 車両までの距離 > 閾値 となる場合。
149
+ ここで車両までの距離 = 地理的距離(車両の座標、給油所の座標)
150
+ であり、車両の座標は GPS トラッキングから(車両、時刻)で取得し、
151
+ 給油所の座標は所在地住所のジオコーディングで取得する。
152
+
153
+ シナリオ: 異常のない給油取引
154
+ もし 燃料カードで取引が報告される
155
+ ... /// ここにシナリオを続ける
156
+ ```
157
+
158
+ この「仕様詳細」欄はツールからは単なるコメント(自由記述)として無視されるが、シナリオのすぐ近くに置くことで、シナリオを変更する際に一緒に更新される可能性が高まる(「見えないものは忘れられる」の逆)。ただし更新が保証されるわけではない。
159
+
160
+ ## フィーチャーファイルのタグ
161
+
162
+ 各シナリオには**タグ**を付けられる。タグはドキュメンテーションの一種であり、次のような目的で使われる。
163
+
164
+ @wip @sprint-23 @bob @team-red @acceptance-criteria @happy-path @nominal @variant @negative @exception @core @fixedincome @interests
165
+
166
+ - **プロジェクト管理の知識**:`@wip`(作業中)、担当者名やスプリント名など。作業完了後に削除される一時的なタグ。
167
+ - **重要度**:`@acceptance-criteria`(受け入れ基準)、`@happy-path`、`@nominal`、`@variant`、`@negative`、`@exception`、`@core` など。
168
+ - **ビジネスドメインのカテゴリ・概念**:`@fixedincome`、`@interests` など、シナリオが属する業務領域を示す。
169
+
170
+ タグ自体も文書化すべきで、同じ場所にあるテキストファイルで全タグと説明を一覧化するとよい。
171
+
172
+ ### フィーチャーファイルの整理方法
173
+
174
+ フィーチャーファイルが増えたらフォルダで整理する。フォルダ構成自体が知識を伝える手段になる。書籍『Specification by Example』(Gojko Adzic)は3つの整理方法を挙げている。
175
+
176
+ 1. **機能領域ごと**(例: Accounting / Reporting Rules / Discounts / Special Offers)— 業務ドメインが重要な場合に推奨
177
+ 2. **UIのナビゲーション経路に沿って**(UIを文書化する場合)
178
+ 3. **業務プロセスに沿って**(エンドツーエンドのトレーサビリティが必要な場合)
179
+
180
+ ## インタラクティブな生きたドキュメントとしてのシナリオ
181
+
182
+ シナリオは生きたドキュメントの基礎となるが、さらに一歩進めると、ビルドごとに生成される**インタラクティブなWebサイト**にもなる。SpecFlow向けの **Pickles** はその一例で、フォルダ構成をチャプターとして表示するナビゲーションと、タグ・キーワードによる検索機能を備えた1ページサイトを生成する。
183
+
184
+ この検索エンジンにより、タグの2つ目の効果が発揮される:**タグはシナリオの検索を効率的かつ正確にする**。
185
+
186
+ ### 紙のドキュメントが必要な場合
187
+
188
+ コンプライアンス要件などにより紙の文書(「BPD: Boring Paper Document」)が必要な場合もある。著者の同僚 Arnauld Loyer(@aloyer)が開発した **Tzatziki** というツールは、フィーチャーファイルから美しいPDFを書き出す。さらにMarkdownファイルや画像も取り込み、各機能領域チャプターの冒頭に説明を追加できる。
189
+
190
+ BDDは生きたドキュメントの好例である。それは「やるべき仕事」に追加される作業ではなく、正しく仕事をすることそのものの一部である。整合性を照合するツールのおかげで常に同期しており、フィーチャーファイルだけで足りない場合は、生成されたWebサイトがドキュメントを有用・インタラクティブ・検索可能・整理された状態にする方法を示してくれる。
191
+
192
+ ## フィーチャーファイルの完全な例
193
+
194
+ 金融ドメインを題材にした架空だが現実的な例。1つのアウトラインシナリオと対応するデータテーブルを含む。
195
+
196
+ ```
197
+ Feature: Calculate compound interests on a principal
198
+ In order to manage the company money
199
+ As a finance officer
200
+ I want to calculate the compound interests on a principal on
201
+ my account
202
+
203
+ Description:
204
+ Compound interest is when the bank pays interest on both the
205
+ principal (the original amount of money) and the interest an
206
+ account has already earned.
207
+
208
+ To calculate compound interest use the formula below.
209
+
210
+ In the formula, A represents the final amount in the account
211
+ after t years compounded 'n' times at interest rate 'r' with
212
+ starting amount 'p'.
213
+
214
+ A = P*(1+(r/n))^n*t
215
+
216
+ Scenario: Bi-annual compound interests over one year
217
+ Given a principal of USD 1000
218
+ And interests are compounded bi-annually at a rate of 5%
219
+ And the calculation period lasts exactly 1 year
220
+ When the calculation period lasts exactly 1 year
221
+ Then the amount of money in the account is USD 1053.63
222
+
223
+ Scenario: Quarterly compound interests over one year
224
+ //... outline scenario
225
+
226
+ Examples:
227
+ | convention | rate | time | amount | remarks |
228
+ |-------------|------|------|-----------|----------------|
229
+ | LINEAR | 0.05 | 2 | 0.100000 | (1+rt)-1 |
230
+ | COMPOUND | 0.05 | 2 | 0.102500 | (1+r)^t-1 |
231
+ | DISCOUNT | 0.05 | 2 | -0.100000 | (1-rt)-1 |
232
+ | CONTINUOUS | 0.05 | 2 | 0.105171 | (e^rt)-1 (rare)|
233
+ | NONE | 0.05 | 2 | 0 | 0 |
234
+ ```
235
+
236
+ ツールの支援があれば、すべてのビジネスシナリオは自動テストであると同時に生きたドキュメントになる。シナリオとコードの橋渡しは、**ステップ(step)**という仕組みで行う。各ステップは正規表現でマッチし、シナリオ中のテキストからパラメータを抽出して本番コードを呼び出す。
237
+
238
+ ```
239
+ "When I buy a book at an ex-VAT price of EUR <exVATPrice>"
240
+
241
+ // 対応するグルーコード
242
+ Book(number exVATPrice)
243
+ Service = LookupOrderService();
244
+ Service.sendOrder(exVATPrice);
245
+ ```
246
+
247
+ 日本語のステップでも同じ仕組みです。ただしパラメータの位置が変わるため、
248
+ ステップ定義の正規表現は日本語の文面に合わせて書き直します。
249
+
250
+ ```
251
+ "もし 税抜価格 EUR <exVATPrice> の本を購入する"
252
+
253
+ // 対応するグルーコード
254
+ Book(number exVATPrice)
255
+ Service = LookupOrderService();
256
+ Service.sendOrder(exVATPrice);
257
+ ```
258
+
259
+ ## 日本語 Gherkin で書く
260
+
261
+ Gherkin は多言語のキーワードをサポートしており、フィーチャーファイルの先頭に `# language: ja` と書くと日本語のキーワードが使えます。BDD の価値は会話そのものにあるので、シナリオはビジネス側が普段読み書きする言語で書くのが原則です。日本語で業務を語るチームなら、シナリオも日本語で書きます。
262
+
263
+ | 英語 | 日本語 |
264
+ | :--- | :--- |
265
+ | Feature | 機能 |
266
+ | Background | 背景 |
267
+ | Rule | ルール |
268
+ | Scenario | シナリオ |
269
+ | Scenario Outline | シナリオテンプレート(シナリオアウトライン) |
270
+ | Examples | 例 |
271
+ | Given | 前提 |
272
+ | When | もし |
273
+ | Then | ならば |
274
+ | And | かつ |
275
+ | But | しかし |
276
+
277
+ 前掲の複利計算の例を日本語 Gherkin で書くと次のようになります。英語版と 1 対 1 で読み比べられます。
278
+
279
+ ```
280
+ # language: ja
281
+ 機能: 元本に対する複利の計算
282
+ 会社の資金を管理するために
283
+ 財務担当者として
284
+ 口座の元本に対する複利を計算したい
285
+
286
+ 説明:
287
+ 複利とは、元本(もともとの金額)と、口座がすでに獲得した利息の
288
+ 両方に対して銀行が利息を支払うことをいいます。
289
+
290
+ 複利は次の式で計算します。年利 r、年 n 回の複利、元本 P、期間 t 年
291
+ のとき、t 年後の口座残高 A は次のとおりです。
292
+
293
+ A = P*(1+(r/n))^n*t
294
+
295
+ 背景:
296
+ 前提 口座の通貨は USD である
297
+
298
+ シナリオ: 1 年間の半年複利
299
+ 前提 元本が USD 1000 である
300
+ かつ 年利 5% で半年ごとに複利計算される
301
+ かつ 計算期間がちょうど 1 年である
302
+ もし 利息を計算する
303
+ ならば 口座の残高は USD 1053.63 である
304
+
305
+ シナリオテンプレート: 利息計算方式ごとの利息額
306
+ 前提 年利が <利率> である
307
+ かつ 計算期間が <期間> 年である
308
+ もし 利息計算方式 <方式> で利息を計算する
309
+ ならば 利息額は <利息額> である
310
+
311
+ 例:
312
+ | 方式 | 利率 | 期間 | 利息額 | 備考 |
313
+ | 単利 | 0.05 | 2 | 0.100000 | (1+rt)-1 |
314
+ | 複利 | 0.05 | 2 | 0.102500 | (1+r)^t-1 |
315
+ | 割引 | 0.05 | 2 | -0.100000 | (1-rt)-1 |
316
+ | 連続複利 | 0.05 | 2 | 0.105171 | (e^rt)-1(まれ)|
317
+ | なし | 0.05 | 2 | 0 | 0 |
318
+ ```
319
+
320
+ 日本語で書く場合の注意点は 3 つあります。
321
+
322
+ - ステップ定義(グルーコード)側の正規表現も、日本語のステップ文字列にマッチするように書きます。パラメータの抽出位置が英語とは異なるため、英語のステップ定義をそのまま流用できません
323
+ - 1 つのプロジェクト内で英語と日本語のフィーチャーファイルを混在させません。検索性が落ち、用語の揺れが生まれます
324
+ - シナリオで使う用語は、後述の用語集(グロッサリー)と表記を揃えます。「顧客」と「お客様」のような揺れは、そのままドメイン理解の揺れになります
325
+
326
+ ## BDDが「生きたドキュメント」の典型例である理由
327
+
328
+ BDDは正確なドキュメントが常にコードと同期する状態を実現できることを示した。生きたドキュメントの中核原則は、すべてすでにBDDに備わっている。
329
+
330
+ 01
331
+
332
+ #### 協働的(Collaborative)
333
+
334
+ BDDの主要な手段は「対話」であり、スリーアミーゴ(またはそれ以上)の各役割が必ず参加する。
335
+
336
+ 02
337
+
338
+ #### 低コスト(Low-effort)
339
+
340
+ 具体例をめぐる会話は、何を作るかの合意形成に有用で、少しの追加作業で自動テストと生きたドキュメントの両方になる — 1つの活動で複数の恩恵。
341
+
342
+ 03
343
+
344
+ #### 信頼できる(Reliable)
345
+
346
+ 整合性照合の仕組みのおかげで信頼できる。振る舞いがテキストシナリオと実装コードの両方に記述されるため、CucumberやSpecFlowのようなツールがシナリオとコードの同期を保証(または、ズレを検知)する。これは知識の重複がある場合に必ず必要になる。
347
+
348
+ ### 会話がもたらす洞察(Insightful)
349
+
350
+ 会話はフィードバックを提供する。シナリオが長すぎたり不自然だったりする場合、それは暗黙の概念が欠けているサインであり、より短くシンプルなシナリオを示唆してくれる。
351
+
352
+ ### 対象読者(Targeted audience)
353
+
354
+ すべての作業はビジネス要件を議論する際、技術者以外も含む読者を対象としているため、明確で非技術的な言葉遣いに重点を置く。
355
+
356
+ ### 知識の沈殿(Idea sedimentation)
357
+
358
+ 会話だけで十分なことも多く、すべてを書き留める必要はない。アーカイブや自動化のために書き留めるべきなのは、最も重要なシナリオ(キーシナリオ)だけでよい。
359
+
360
+ ### プレーンテキストの文書(Plain-text documents)
361
+
362
+ 変化するものをソースコードと一緒にバージョン管理するには、プレーンテキストが非常に便利である。
363
+
364
+ ### アクセス可能な公開スナップショット(Accessible published snapshot)
365
+
366
+ 誰もがソースコードにアクセスしてシナリオを読めるわけではない。PickleやTzatzikiのようなツールは、ある時点でのシナリオ全体のスナップショットを、インタラクティブなWebサイトや印刷可能なPDF文書としてエクスポートすることで解決する。
367
+
368
+ ## ドキュメントを最大限活かすために(さらに一歩先へ)
369
+
370
+ フィーチャーファイルは、豊かなドメイン知識を効率よく集める良い場所である。BDDを支援するほとんどのツールは Gherkin 構文という固定フォーマットを理解する。
371
+
372
+ ```
373
+ Feature: Name of the feature
374
+
375
+ In order to... As a... I want...
376
+
377
+ Scenario: name of the first scenario
378
+ Given...
379
+ When...
380
+ Then...
381
+
382
+ Scenario: name of the second scenario
383
+ ...
384
+ ```
385
+
386
+ 日本語 Gherkin での骨子は次のとおりです。
387
+
388
+ ```
389
+ # language: ja
390
+ 機能: 機能の名前
391
+
392
+ 〜するために... 〜として... 〜したい...
393
+
394
+ シナリオ: 1 つ目のシナリオの名前
395
+ 前提 ...
396
+ もし ...
397
+ ならば ...
398
+
399
+ シナリオ: 2 つ目のシナリオの名前
400
+ ...
401
+ ```
402
+
403
+ 金融や保険のようなリッチなドメインを扱うチームは、冒頭の意図と末尾の具体シナリオだけでは足りないと気づき、中間領域に追加の説明を書き込むようになった。これはツールからは無視されるが、Pickles のようなツールはこの「説明エリア」でMarkdown記法をサポートするよう対応した。
404
+
405
+ ### 例:投資の現在価値
406
+
407
+ ```
408
+ Feature: Investment Present Value
409
+
410
+ In order to calculate the breakeven point of the investment
411
+ opportunity
412
+ As an investment manager
413
+ I want to calculate the present value of future cash amounts
414
+
415
+ Description
416
+ ===========
417
+ We need to find the present value *PV* of the given future cash
418
+ amount *FV*. The formula for that can be expressed as:
419
+
420
+ - Using the negative exponent notation:
421
+ PV = FV * (1 + i)^(-n)
422
+ - Or in the equivalent form:
423
+ PV = FV * (1 / (1 + i)^n)
424
+
425
+ Example
426
+ -------
427
+ For example, n = 2, i = 8%
428
+
429
+ FV = $100
430
+ |
431
+ PV? ------|----------> t (years)
432
+ 0 1 2
433
+
434
+ Scenario: Present Value of a single cash amount
435
+ Given a future cash amount of 100$ in 2 years
436
+ And an interest rate of 8%
437
+ When we calculate its present value
438
+ Then its present value is $85.73
439
+ ```
440
+
441
+ 日本語 Gherkin では次のようになります。説明エリアも日本語で書けます。
442
+
443
+ ```
444
+ # language: ja
445
+ 機能: 投資の現在価値
446
+
447
+ 投資機会の損益分岐点を計算するために
448
+ 投資マネージャーとして
449
+ 将来のキャッシュ金額の現在価値を計算したい
450
+
451
+ 説明
452
+ ====
453
+ 将来のキャッシュ金額 *FV* に対する現在価値 *PV* を求めます。
454
+ 計算式は次のように表せます。
455
+
456
+ - 負の指数表記を使う場合:
457
+ PV = FV * (1 + i)^(-n)
458
+ - 同等の別表記:
459
+ PV = FV * (1 / (1 + i)^n)
460
+
461
+ 例
462
+ --
463
+ たとえば n = 2、i = 8% のとき
464
+
465
+ FV = $100
466
+ |
467
+ PV? ------|----------> t(年)
468
+ 0 1 2
469
+
470
+ シナリオ: 単一のキャッシュ金額の現在価値
471
+ 前提 2 年後に受け取る将来キャッシュ金額が 100$ である
472
+ かつ 利率が 8% である
473
+ もし その現在価値を計算する
474
+ ならば 現在価値は $85.73 である
475
+ ```
476
+
477
+ ベストプラクティス
478
+
479
+ 頻繁には変わらない知識は「説明エリア」に、変わりやすい部分は具体的なシナリオの中に置くのがよい戦略である。説明が使う数値はあくまで「サンプル」であり、ある時点の業務プロセスの設定値そのものではないと明示するのも一つの方法。ただし、説明エリアの内容はシナリオと違って本当の意味では「生きて」いない — シナリオを変更すれば近くの説明も更新したくなるはずだが、それが保証されるわけではない。
480
+
481
+ PickleやRelish、Tzatzikiのようなツールは、フィーチャーファイルの隣に置かれたMarkdown記法の説明やプレーンなMarkdownファイルを理解できるようになっており、金融業界の規制当局が求めるような、一貫したドメインドキュメントの取りまとめを容易にする。
482
+
483
+ ## プロパティベーステストとBDD
484
+
485
+ 要件はしばしば「プロパティ(性質)」として自然に表現できる。例:「すべての支払・受取金額の合計は常にゼロでなければならない」「誰も同時に売り手であり買い手でありジャッジであることはできない」。BDDやTDDでは、こうした一般的な性質を具体的な例に落とし込む必要があるが、それは問題やコードを段階的に構築する助けになる。
486
+
487
+ 一般的な性質の値を追跡するには、通常フィーチャーファイル内のプレーンテキストコメントとして記述する。しかし、まさにこの「性質をランダム生成サンプルに対して検証する」技術こそが**プロパティベーステスト**であり、Haskellの **QuickCheck** が代表的なフレームワーク(他の言語にも同様のツールが存在)。
488
+
489
+ ```
490
+ Scenario: The sum of all cash amounts exchanged must be zero
491
+ for derivatives
492
+
493
+ Given any derivative financial instrument
494
+ And a random date during its lifetime
495
+ When we generate the related cash flows on this date for the
496
+ payer and\
497
+ the receiver
498
+ Then the sum of the cash flows of the payer and the receiver
499
+ is\
500
+ exactly zero
501
+ ```
502
+
503
+ 日本語 Gherkin では次のようになります。
504
+
505
+ ```
506
+ # language: ja
507
+ シナリオ: デリバティブでは授受されるすべての金額の合計がゼロである
508
+
509
+ 前提 任意のデリバティブ金融商品がある
510
+ かつ その存続期間中の任意の日付がある
511
+ もし その日付における支払側と受取側のキャッシュフローを生成する
512
+ ならば 支払側と受取側のキャッシュフローの合計は
513
+ ちょうどゼロである
514
+ ```
515
+
516
+ 「given ANY shopping cart...」のような表現は、通常のシナリオでは避けるべき「コードの臭い」だが、プロパティベーステストを補完するプロパティ指向のシナリオでは問題ない。
517
+
518
+ ## 用語集(グロッサリー)の作成
519
+
520
+ 理想的な用語集はコードから直接抽出される「生きた」ものだが、多くの場合それは不可能で手動作成が必要になる。フィーチャーファイルと同じ場所にMarkdownファイルとして用語集を手作業で作成すれば、他のフィーチャーファイルと一緒に生きたドキュメントサイトに含めることができる。空のダミーのフィーチャーファイルとして作成することも可能。
521
+
522
+ ## 非機能的な知識へのリンク
523
+
524
+ すべての知識を同じ場所に記述すべきではない。UI固有・レガシー固有の知識をドメイン知識と混在させたくない。そうした関連知識が重要な場合は別の場所に保存し、リンクで関係性を表現し見つけやすくする。3つのリンク方法がある。
525
+
526
+ - **URLへの直接リンク** — リンク切れのリスクあり\
527
+ `https://en.wikipedia.org/wiki/Present_value`
528
+ - **リンクレジストリ経由** — リンク切れを差し替えやすい\
529
+ `go/search?q=present+value`
530
+ - **ブックマーク検索** — 関連コンテンツを含む場所へのリンク\
531
+ `https://en.wikipedia.org/w/index.php?search=present+value`
532
+
533
+ 非機能的な知識へのリンクは、関連コンテンツへの堅牢な接続方法を提供するが、その分、読者自身が最も関連性の高い結果を選ぶ手間が発生する。
534
+
535
+ ## Cucumber の実装ガイド
536
+
537
+ ここまでは Gherkin の書き方を扱ってきました。ここからは、フィーチャーファイルを実際に動く自動テストにするための実装手順を扱います。出典は [Cucumber 公式のインストールガイド](https://cucumber.io/docs/installation/) と [10 Minute Tutorial](https://cucumber.io/docs/guides/10-minute-tutorial/) です。
538
+
539
+ ### 処理系を選ぶ
540
+
541
+ Cucumber は 30 以上の言語・プラットフォームに実装があります。メンテナンス状況で 3 つに分かれているので、新規採用では公式(Official)か準公式(Semi-official)から選びます。
542
+
543
+ | 区分 | 処理系 | 言語 |
544
+ | :--- | :--- | :--- |
545
+ | 公式 | Cucumber-JS | JavaScript / TypeScript |
546
+ | 公式 | Cucumber-JVM | Java / Kotlin |
547
+ | 公式 | Cucumber-Ruby | Ruby |
548
+ | 公式 | Cucumber-Scala | Scala |
549
+ | 公式 | Cucumber.cpp | C++ |
550
+ | 準公式 | Behave、Pytest-BDD | Python |
551
+ | 準公式 | Behat | PHP |
552
+ | 準公式 | Reqnroll | .NET(C# / F# / VB) |
553
+ | 準公式 | gocuke | Go |
554
+ | 準公式 | Test::BDD::Cucumber | Perl |
555
+
556
+ .NET の SpecFlow は開発が終了しており、後継は Reqnroll です。非公式(Cucumber-Rust、GoBDD など)や未メンテナンス(Cucumber-Groovy、Godog など)の処理系は、採用前に最終更新日を確認します。
557
+
558
+ ### インストール
559
+
560
+ 処理系ごとのインストールは次のとおりです。バージョンは執筆時点のものなので、採用時に最新を確認してください。
561
+
562
+ ```
563
+ # JavaScript / TypeScript(Cucumber-JS)
564
+ npm install --save-dev @cucumber/cucumber
565
+
566
+ # Ruby(Cucumber-Ruby)
567
+ gem install cucumber
568
+
569
+ # Python(Behave / Pytest-BDD)
570
+ pip install behave
571
+ pip install pytest-bdd
572
+
573
+ # .NET(Reqnroll)
574
+ dotnet add package Reqnroll.NUnit
575
+ ```
576
+
577
+ Java の場合は Maven のアーキタイプからプロジェクトを生成できます。
578
+
579
+ ```
580
+ mvn archetype:generate \
581
+ "-DarchetypeGroupId=io.cucumber" \
582
+ "-DarchetypeArtifactId=cucumber-archetype" \
583
+ "-DarchetypeVersion=8.0.1" \
584
+ "-DgroupId=hellocucumber" \
585
+ "-DartifactId=hellocucumber" \
586
+ "-Dpackage=hellocucumber" \
587
+ "-Dversion=1.0.0-SNAPSHOT" \
588
+ "-DinteractiveMode=false"
589
+ ```
590
+
591
+ Cucumber-JS で特に注意すべき落とし穴が 2 つあります。
592
+
593
+ - **グローバルインストールしない** — Cucumber-JS は実行中に状態を保持するため、プロジェクトの依存として入れます。グローバルに入れると「You're calling functions (e.g. 'Given') on an instance of Cucumber that isn't running.」というエラーになります
594
+ - **依存ツリーに複数バージョンを混在させない** — `npm why @cucumber/cucumber` で重複を確認します。共有ライブラリが Cucumber に依存している場合は peer dependency にします。パッケージ名も旧 `cucumber` ではなく `@cucumber/cucumber` を使います
595
+
596
+ ### ディレクトリ構成
597
+
598
+ フィーチャーファイルとステップ定義は、処理系が決めた場所に置きます。
599
+
600
+ ```
601
+ # Cucumber-JS
602
+ features/
603
+ ├── is_it_friday_yet.feature
604
+ └── step_definitions/
605
+ └── stepdefs.js
606
+
607
+ # Cucumber-JVM(Maven)
608
+ src/test/resources/hellocucumber/
609
+ └── is_it_friday_yet.feature
610
+ src/test/java/hellocucumber/
611
+ └── StepDefinitions.java
612
+ ```
613
+
614
+ フィーチャーファイルが増えたら、前述の「フィーチャーファイルの整理方法」に従って機能領域ごとにフォルダを切ります。
615
+
616
+ ### 最小の例
617
+
618
+ 公式チュートリアルの「金曜日かどうか」を日本語 Gherkin で書くと次のようになります。
619
+
620
+ ```
621
+ # language: ja
622
+ 機能: もう金曜日?
623
+ みんな、いつ金曜日になるのかを知りたい
624
+
625
+ シナリオテンプレート: 今日は金曜日である、またはそうでない
626
+ 前提 今日は "<曜日>" である
627
+ もし 金曜日かどうか尋ねる
628
+ ならば "<答え>" と返ってくる
629
+
630
+ 例:
631
+ | 曜日 | 答え |
632
+ | 金曜日 | TGIF |
633
+ | 日曜日 | まだ |
634
+ | それ以外 | まだ |
635
+ ```
636
+
637
+ ステップ定義は、シナリオの文面にマッチする関数として書きます。Cucumber-JS の場合は次のとおりです。
638
+
639
+ ```
640
+ const assert = require('assert');
641
+ const { Given, When, Then } = require('@cucumber/cucumber');
642
+
643
+ function isItFriday(today) {
644
+ return today === '金曜日' ? 'TGIF' : 'まだ';
645
+ }
646
+
647
+ Given('今日は {string} である', function (today) {
648
+ this.today = today;
649
+ });
650
+
651
+ When('金曜日かどうか尋ねる', function () {
652
+ this.actualAnswer = isItFriday(this.today);
653
+ });
654
+
655
+ Then('{string} と返ってくる', function (expectedAnswer) {
656
+ assert.strictEqual(this.actualAnswer, expectedAnswer);
657
+ });
658
+ ```
659
+
660
+ Cucumber-JVM(Java)では、アノテーションでステップを宣言します。
661
+
662
+ ```
663
+ package hellocucumber;
664
+
665
+ import io.cucumber.java.en.Given;
666
+ import io.cucumber.java.en.When;
667
+ import io.cucumber.java.en.Then;
668
+ import static org.assertj.core.api.Assertions.assertThat;
669
+
670
+ class IsItFriday {
671
+ static String isItFriday(String today) {
672
+ return "金曜日".equals(today) ? "TGIF" : "まだ";
673
+ }
674
+ }
675
+
676
+ public class StepDefinitions {
677
+ private String today;
678
+ private String actualAnswer;
679
+
680
+ @Given("今日は {string} である")
681
+ public void today_is(String today) {
682
+ this.today = today;
683
+ }
684
+
685
+ @When("金曜日かどうか尋ねる")
686
+ public void i_ask_whether_it_s_friday_yet() {
687
+ actualAnswer = IsItFriday.isItFriday(today);
688
+ }
689
+
690
+ @Then("{string} と返ってくる")
691
+ public void i_should_be_told(String expectedAnswer) {
692
+ assertThat(actualAnswer).isEqualTo(expectedAnswer);
693
+ }
694
+ }
695
+ ```
696
+
697
+ 日本語のフィーチャーファイルを使う場合でも、ステップ定義側のアノテーション(`@Given` など)は英語のままで構いません。キーワードの言語(`前提` / `もし` / `ならば`)は `# language: ja` で解決され、アノテーションにはキーワードを除いたステップ本文がマッチします。
698
+
699
+ ### 実行する
700
+
701
+ ```
702
+ # Cucumber-JS
703
+ npx cucumber-js
704
+
705
+ # Cucumber-JVM(Maven)
706
+ mvn test
707
+
708
+ # Cucumber-Ruby
709
+ cucumber
710
+
711
+ # Behave
712
+ behave
713
+ ```
714
+
715
+ ### Red-Green-Refactor で進める
716
+
717
+ Cucumber の実行結果は、そのまま TDD のサイクルになります。
718
+
719
+ ```plantuml
720
+ @startuml
721
+ title Cucumber での Red-Green-Refactor
722
+
723
+ [*] --> シナリオを書く
724
+ シナリオを書く --> Undefined : 実行する
725
+ Undefined --> ステップ定義を書く : 提案されたスニペットを貼る
726
+ ステップ定義を書く --> Pending
727
+ Pending --> Failing : アサーションを書く
728
+ Failing --> Passing : 最小限の実装を書く
729
+ Passing --> リファクタリング
730
+ リファクタリング --> Passing : テストは緑のまま
731
+ リファクタリング --> シナリオを書く : 次のシナリオへ
732
+ リファクタリング --> [*]
733
+
734
+ Undefined : ステップ定義が無い
735
+ Pending : 未実装の例外を投げる
736
+ Failing : 期待値と一致しない(Red)
737
+ Passing : シナリオが通る(Green)
738
+ @enduml
739
+ ```
740
+
741
+ 1. **Undefined** — シナリオだけがある状態。Cucumber は未定義ステップを報告し、貼り付け可能なステップ定義のスニペットを提案します
742
+ 2. **Pending** — スニペットを貼った状態。ステップは未実装例外を投げます
743
+ 3. **Failing(Red)** — アサーションを書くと、実装がないため落ちます
744
+ 4. **Passing(Green)** — 最小限の実装で通します。最初はハードコードで構いません
745
+ 5. **Refactor** — 実装をプロダクションコードへ移し、重複を取り除きます。ステップ定義は薄く保ち、業務ロジックを持ち込みません
746
+
747
+ この流れは AI-DLC の Bolt におけるステップ計画と対応します。シナリオが受入条件、Cucumber の実行結果が承認ゲートでの検証材料になります。
748
+
749
+ ### 生きたドキュメントとして公開する
750
+
751
+ フィーチャーファイルを Web サイトや PDF として公開すると、前述の「インタラクティブな生きたドキュメント」になります。
752
+
753
+ | ツール | 出力 | 対象 |
754
+ | :--- | :--- | :--- |
755
+ | Pickles | 検索可能な HTML サイト | Reqnroll / SpecFlow、Cucumber 全般 |
756
+ | Relish | ホスティング型の HTML サイト | Cucumber 全般 |
757
+ | Tzatziki | PDF | Cucumber 全般 |
758
+ | Cucumber Reports | 実行結果レポート | Cucumber 全般 |
759
+
760
+ 公開はビルドの一部として自動化します。手作業で生成する運用にすると、すぐに更新されなくなり「生きた」状態を失います。
761
+
762
+ ## まとめ
763
+
764
+ BDDは生きたドキュメントの典型例である。まず何よりチームメンバー間の頻繁な会話に頼り、それでいてビジネス側にも開発者側にもアクセス可能な形で、プロジェクト中に集めた知識を保存する。コードとシナリオという冗長な知識を生むにもかかわらず、付随するツールがすべてを同期させ続ける。BDDが扱うのはソフトウェアのビジネス上の振る舞いだけだが、以降の章ではこの考え方をソフトウェア開発に関する他の活動、さらにはソフトウェア開発の外にまで拡張していく。
765
+
766
+ 出典: *Living Documentation*(Cyrille Martraire 著)第2章「Behavior-Driven Development as an Example of Living Specifications」(p.56–70)の要約