一键导入
tdd-new-fn
Build a new devPTIpack function test-first — ask contract questions via AskUserQuestion, write failing tests (RED), then implement via Codex (GREEN).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Build a new devPTIpack function test-first — ask contract questions via AskUserQuestion, write failing tests (RED), then implement via Codex (GREEN).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | tdd-new-fn |
| description | Build a new devPTIpack function test-first — ask contract questions via AskUserQuestion, write failing tests (RED), then implement via Codex (GREEN). |
Build any new exported function or substantial (>~20-line) internal helper using strict test-first development. Small private helpers tested indirectly by their callers are exempt.
YAML-only registry additions are NOT exempt: write the failing integration test against the full pipeline first, then add the YAML.
Before writing a single line of test or code, call AskUserQuestion
with 3–4 questions specific to this function. Design the questions
around four axes:
| Axis | What to ask |
|---|---|
| Output shape | Return type, key columns/names, length constraint on success |
| Error conditions | Which invalid inputs must produce cli_abort() or an error |
| Edge cases | Which boundary inputs are in scope (empty, NA, single element) |
| Out of scope | What reasonable-sounding behaviour should the function NOT do |
fetch_hex_data(), one option
is "tibble keyed by hex_id").AskUserQuestion(questions = list(
list(
question = "What should hex_fetch_source_timeseries() return on success?",
header = "Return type",
multiSelect = FALSE,
options = list(
list(label = "Wide tibble keyed by hex_id (one col per period)",
description = "Mirrors the flat output of hex_fetch_source_rest()."),
list(label = "Long tibble (hex_id | period | value)",
description = "Easier to pivot later; caller reshapes.")
)
),
list(
question = "Which inputs must produce an error?",
header = "Error cases",
multiSelect = TRUE,
options = list(
list(label = "hex_ids is empty", description = "length(hex_ids) == 0"),
list(label = "No fields resolve", description = "Template yields 0 columns after year expansion"),
list(label = "httr2 not installed", description = "Dependency guard"),
list(label = "API returns non-200", description = "HTTP error passthrough")
)
)
))
Using the contract answers, write a test_that() block per contract
point in the appropriate test file (append; never overwrite):
Use mockery::stub() for network calls; use httptest2::with_mock_api()
when real fixture data matters (record the fixture before writing
assertions so the fixture hash is known).
Run:
Rscript -e 'devtools::load_all(quiet=TRUE)
testthat::test_file("tests/testthat/test-<area>.R")'
All new tests must fail (or error with "could not find function"). If any pass unexpectedly, the test is too weak — strengthen it before continuing.
Do not proceed to Phase 3 until RED is confirmed.
Write an integration test that calls use_hex_vars("<canonical_name>")
and fetch_hex_data(hex_ids, vars, ...) against a mock/fixture for the
new variable. Confirm the test fails because the YAML entry does not
exist yet. THEN add the YAML entry and confirm the test turns GREEN.
Brief Codex with:
Rscript command to run after implementationAfter Codex returns:
R CMD check --no-manual if any exported symbol changed.Fix single-line issues inline; do not re-invoke Codex for typos.
Same as tdd-permanent-fn steps 6–7:
Tests row for the test file, Code row for the
implementation).PLAN.md — tick the relevant box, add sub-bullets for new
files, update the progress log with the PR/branch.