// Guides Test-Driven Development for this Neovim plugin project. Use when implementing new features or fixing bugs that require behavioral changes. Includes project-specific tooling (make test/lint/check) and Lua/Busted testing patterns. Follows strict RED-GREEN-REFACTOR cycle.
| name | Implementing Features with TDD |
| description | Guides Test-Driven Development for this Neovim plugin project. Use when implementing new features or fixing bugs that require behavioral changes. Includes project-specific tooling (make test/lint/check) and Lua/Busted testing patterns. Follows strict RED-GREEN-REFACTOR cycle. |
Don't use for: Pure refactoring, documentation, configuration, or exploration.
spec/**/*_spec.lualua/github-actions/**/*.luamake test # 100% pass required
make lint # 0 warnings/errors required
make check # Formatting check
make format # Apply stylua
get_symbols_overview - File structurefind_symbol - Find functions/classesfind_referencing_symbols - Find usagesearch_for_pattern - Search patternsIf anything is unclear, use AskUserQuestion immediately.
Example:
AskUserQuestion({
questions: [{
question: "Which icon should be used?",
header: "Icon",
multiSelect: false,
options: [
{label: "Error icon", description: "🔴 GitHubActionsVersionError"},
{label: "Warning icon", description: "⚠️ GitHubActionsVersionOutdated"}
]
}]
})
Common clarifications: display format, error handling, edge cases, performance.
Add tests to spec/**/*_spec.lua:
describe('module.new_feature', function()
local test_cases = {
{name = 'should handle normal case', input = 'value', expected = 'result'},
{name = 'should handle edge case', input = 'edge', expected = 'edge_result'},
{name = 'should handle nil input', input = nil, expected = 'error'},
}
for _, tc in ipairs(test_cases) do
it(tc.name, function()
assert.are.equal(tc.expected, module.new_feature(tc.input))
end)
end
end)
Verify: make test must show errors.
Add minimum code to pass tests in lua/github-actions/**/*.lua:
---Brief description
---@param input string|nil Input parameter
---@return string result Result value
function M.new_feature(input)
if not input then
return 'error'
end
if input == 'edge' then
return 'edge_result'
end
return 'result'
end
Verify: make test must pass 100%.
After tests are green, refactor for clarity:
function M.new_feature(input)
if not input then
return handle_error_case()
end
return process_input(input)
end
local function handle_error_case()
return 'error'
end
local function process_input(input)
if is_edge_case(input) then
return 'edge_result'
end
return 'result'
end
Verify: make test still passes.
make check # ✅ Must pass
make lint # ✅ 0 warnings/errors
make test # ✅ 100% success
dofile('spec/minimal_init.lua')
describe('module_name', function()
local module = require('github-actions.module_name')
describe('feature_name', function()
local test_cases = { ... }
for _, tc in ipairs(test_cases) do
it(tc.name, function()
-- Test implementation
end)
end
end)
end)
-- Set error in version_info
version_info.error = 'error message'
version_info.is_latest = false
-- Display shows: [🔴] error message
-- Uses: GitHubActionsVersionError highlight
local status = semver.get_version_status(current, latest)
-- Returns: "newer" | "latest" | "outdated" | "invalid"
if status == 'newer' then
-- Treat as error
elseif status == 'latest' then
-- Mark as up-to-date
else
-- Handle outdated/invalid
end
See TDD Implementation Examples for the full "newer than latest" feature implementation showing all phases.
✨ feat: brief description
Detailed explanation of change and why.
Changes:
- Change 1
- Change 2
Why this matters:
Value explanation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Emoji prefixes: ✨ feat, 🐛 fix, ♻️ refactor, ✅ test
make check/lint/test all passRemember: Strict TDD required. Ask when uncertain. Never assume.