Terraform 1.13 beta makes test input types explicit
Terraform 1.13.0-beta3 previews test-file variable declarations and separate test-run concurrency controls, alongside filesystem consistency checks.
A test input should not acquire a different interpretation merely because the next run block tests a different module. That is the problem behind one of the changes included in Terraform 1.13.0-beta3, published on July 30. Test files can declare external variables directly, giving their inputs a type outside the context of an individual run. This is a preview release, so the changes describe the beta available today rather than a completed stable release.
I use Terraform both as a configuration author and as a provider author. Tests need an understandable input contract in both roles. A test file that drives several configurations should explain its own external inputs without requiring the reader to infer them from whichever module executes first.
Input evaluation previously depended on a run's module
The variable-definition patch explains the earlier implementation. Terraform delayed evaluation of external test variables until a run executed, then used the variable definitions in that run's module to interpret them. The patch identifies the consequence that a variable's value could effectively change between runs.
The new optional variable blocks allow the test file to declare the type of an external input itself. The implementation describes this as preparation for moving variable evaluation into the test graph. It also prevents a name declared through these definition blocks from being supplied through the file-level variables block at the same time. These are distinct ways of expressing test input, with distinct roles.
The change is useful when a test file does more than call one module with one set of simple values. A file-level contract gives the reader a stable place to look for the interpretation of external data. The module under test can still declare its own interface, but that declaration no longer has to serve as the only explanation of the test file's input.
A declaration can supply a default and a type
The beta's test fixture demonstrates two string declarations with defaults. The accompanying command test supplies an external value for one of them. This exercises both the default and the override behavior, rather than checking only whether the parser accepts the new block.
A small declaration in a test file looks like this. It states the input's interpretation and the value to use when the caller supplies none.
variable "input_one" {
type = string
default = "hello"
}
The beta changelog makes a compatibility distinction here. The definition block is optional, but users with complex external values may encounter diagnostics without the additional declaration. That makes it relevant to existing test suites as well as new tests adopting the syntax deliberately.
This is a change in input interpretation, so a useful comparison retains the same external input while making its type explicit. Replacing the input with a simpler value at the same time could remove the condition that exposed the difference. The declaration should document the intended type, not merely whichever type makes a particular run pass.
Test-run concurrency is separate from resource concurrency
The deadlock correction included in the beta introduces a separate run-parallelism argument and carries it into test execution. Its regression case executes with a run limit of one while the tested configuration contains multiple resource instances. The case checks that limiting concurrent test runs does not prevent the resources inside a run from completing.
The distinction is visible in the implementation's two fields. Operation parallelism limits work during a run's plan or apply. Run parallelism limits concurrent runs within a test file. A single value applied indiscriminately to both levels can constrain the scheduling machinery in unintended ways, especially when one level waits for work scheduled by the other.
For a provider author, this separation makes a test suite's concurrency assumptions easier to assess. Serializing test runs is a different request from serializing every resource operation. A test can require one while still needing the other to behave normally. The regression case gives that expectation a concrete execution scenario.
Filesystem reads remain inputs to the operation
The beta also checks filesystem function results for consistency across planning and application. The file function documentation in this version explains the underlying constraint. file reads UTF-8 text from an existing file, and functions do not participate in Terraform's dependency graph.
Consequently, a file generated during the operation is not an ordinary dependency that file can wait for. Reading it through a function does not establish the ordering relationship a managed resource would need. A configuration that depends on changing filesystem contents can therefore undermine the relationship between what was planned and what application observes.
The preview combines more explicit test inputs with stronger checks on another input source. Both changes make assumptions visible at the place Terraform evaluates them. For the test file, that place is a variable declaration with a type. For filesystem functions, it is the requirement that their observations remain consistent with the planned operation.