skills/terraform-test/SKILL.md
Write and review OpenTofu tests using .tftest.hcl files and the tofu test command. Use when creating module tests, validating plan or apply behavior, checking outputs and validations, or troubleshooting OpenTofu test syntax and execution. In this repository, prefer OpenTofu commands and be cautious with apply-based tests against live OCI resources.
npx skillsauth add ederheisler/agent-skills terraform-testInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use OpenTofu's built-in test framework to verify module behavior without relying on ad hoc shell scripts.
In this repository, test guidance should be OpenTofu-first. Use tofu test, not terraform test, unless the user explicitly asks for Terraform.
tests/ directory when the module or root config is large enough to justify it..tftest.hcl files.terraform/.cd terraform
tofu test
tofu test -test-directory=tests
tofu test -filter=tests/main.tftest.hcl
tofu test -verbose
tofu test -json
If module structure or providers changed, run tofu init before tofu test.
OpenTofu tests are built from run blocks plus assertions.
run "defaults" {
module {
source = "./"
}
assert {
condition = output.instance_shape == "VM.Standard.E6.Flex"
error_message = "The default instance shape should match the expected profile."
}
}
Prefer plan mode when you want to validate expressions, defaults, validation rules, and derived outputs without creating resources.
run "server_defaults_plan" {
command = "plan"
module {
source = "./"
}
variables {
project_name = "im"
compartment_ocid = "ocid1.compartment.oc1..example"
servers = {
api = {
compartment = "compute"
shape_profile = "x86_small"
}
}
}
assert {
condition = length(output.server_public_ips) == 1
error_message = "One server definition should produce one public IP output entry."
}
}
Use plan mode for:
Use apply mode only when you need real provider interaction.
run "integration_apply" {
module {
source = "./"
}
assert {
condition = output.instance_id != ""
error_message = "The applied instance should expose a non-empty instance_id output."
}
}
In this repo, avoid apply-based tests against OCI unless the user explicitly wants live integration coverage and accepts the cost and credential requirements.
Use variables blocks to set test inputs.
variables {
region = "sa-vinhedo-1"
}
run "custom_input" {
command = "plan"
module {
source = "./"
}
variables {
project_name = "im-test"
}
assert {
condition = var.project_name == "im-test"
error_message = "The run-specific variable override should be visible to the test."
}
}
Use outputs from one run as inputs to another when the scenario genuinely needs staged behavior.
run "first_run" {
module {
source = "./modules/server"
}
output "instance_id" {
value = "ocid1.instance.oc1..example"
}
}
run "second_run" {
command = "plan"
module {
source = "./modules/server"
}
variables {
existing_instance_id = run.first_run.output.instance_id
}
}
Keep assertions specific and business-meaningful.
Good assertions:
Weak assertions:
assert {
condition = can(regex("^im-", output.server_names["api"]))
error_message = "Server names should be prefixed with the project name."
}
Use expect_failures when the purpose of the test is to confirm validation rejects an invalid input.
run "reject_missing_compartment" {
command = "plan"
module {
source = "./"
}
variables {
project_name = "im"
compartment_ocid = "ocid1.compartment.oc1..example"
servers = {
api = {
shape_profile = "x86_small"
}
}
}
expect_failures = [
var.servers,
]
}
This pattern is especially useful in this repo for alias validation, compartment resolution, and shape-profile validation.
Prefer tests that exercise the repository's real invariants:
server_defaults are applied consistentlyPrefer not to test:
For automated validation, prefer this order:
cd terraform
tofu fmt -check -recursive
tofu init
tofu validate
tofu test -verbose
tofu init again.Before claiming a test change is complete:
tofu fmt -recursive if you edited HCL.tofu test for the affected scope.documentation
Compact the current conversation into a handoff document for another agent to pick up.
testing
Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
development
Analyzes code diffs and files to identify bugs, security vulnerabilities (SQL injection, XSS, insecure deserialization), code smells, N+1 queries, naming issues, and architectural concerns, then produces a structured review report with prioritized, actionable feedback. Use when reviewing pull requests, conducting code quality audits, identifying refactoring opportunities, or checking for security issues. Invoke for PR reviews, code quality checks, refactoring suggestions, review code, code quality. Complements specialized skills (security-reviewer, test-master) by providing broad-scope review across correctness, performance, maintainability, and test coverage in a single pass.
development
Generates, formats, and validates technical documentation — including docstrings, OpenAPI/Swagger specs, JSDoc annotations, doc portals, and user guides. Use when adding docstrings to functions or classes, creating API documentation, building documentation sites, or writing tutorials and user guides. Invoke for OpenAPI/Swagger specs, JSDoc, doc portals, getting started guides.