You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: website/docs/language/tests/index.mdx
+245-1Lines changed: 245 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,11 +24,12 @@ Each Terraform test lives in a test file. Terraform discovers test files are bas
24
24
25
25
Each test file contains the following root level attributes and blocks:
26
26
27
+
- Zero to one [`test`](#test-block) blocks.
27
28
- One to many [`run`](#run-blocks) blocks.
28
29
- Zero to one [`variables`](#variables) block.
29
30
- Zero to many [`provider`](#providers) blocks.
30
31
31
-
Terraform executes `run` blocks in order, simulating a series of Terraform commands executing directly within the configuration directory. The order of the `variables` and `provider` blocks doesn't matter, Terraform processes all the values within these blocks at the beginning of the test operation. We recommend defining your `variables` and `provider` blocks first, at the beginning of the test file.
32
+
By default, Terraform executes `run` blocks sequentially. To execute `run` blocks in parallel, refer to [`Parallel execution`](#parallel-execution). Each `run` block simulates a series of Terraform commands executing directly within the configuration directory. The order of the `variables` and `provider` blocks doesn't matter, Terraform processes all the values within these blocks at the beginning of the test operation. We recommend defining your `variables` and `provider` blocks first, at the beginning of the test file.
32
33
33
34
### Example
34
35
@@ -75,6 +76,24 @@ run "valid_string_concat" {
75
76
}
76
77
```
77
78
79
+
## Test block
80
+
81
+
The optional `test` block defines the configuration of the test file, allowing you to configure how the framework
82
+
executes its runs. The block has the following fields:
83
+
84
+
| Field or Block Name | Description | Default Value |
|`parallel`| An optional boolean attribute. If `true`, Terraform executes all eligible `run` blocks simultaneously. Refer to [Parallel execution](#parallel-execution) for more information. |`false`|
87
+
88
+
### Example usage
89
+
90
+
```hcl
91
+
# with_config.tftest.hcl
92
+
test {
93
+
parallel = true
94
+
}
95
+
```
96
+
78
97
## Run blocks
79
98
80
99
Each `run` block has the following fields and blocks:
@@ -92,6 +111,7 @@ Each `run` block has the following fields and blocks:
|`parallel`| An optional boolean attribute. |`false`|
95
115
96
116
The `command` attribute and `plan_options` block tell Terraform which command and options to execute for each run block. The default operation, if you do not specify a `command` attribute or the `plan_options` block, is a normal Terraform apply operation.
97
117
@@ -101,6 +121,45 @@ The `plan_options` block allows test authors to customize the [planning mode](/t
101
121
102
122
The `state_key` allows for fine-grained control over which internal state file Terraform uses for a given run block. Refer to [Modules State](#modules-state) for more information.
103
123
124
+
The `parallel` attribute lets you run multiple `run` blocks in parallel. By default, this attribute is set to `false`. When set to `true`, Terraform attempts to execute the `run` block in parallel with other `run` blocks that also have the `parallel` attribute set to `true` and are not dependent on each other.
error_message = "S3 bucket name did not match expected"
157
+
}
158
+
}
159
+
```
160
+
161
+
In the above example, the `first` and `second``run` blocks implicitly have `parallel` set to `true` since the `test` block enables parallel runs. The `third``run` block sets `parallel` to `false` to override the global setting.
162
+
104
163
### Assertions
105
164
106
165
Terraform run block assertions are [Custom Conditions](/terraform/language/expressions/custom-conditions), consisting of a [condition](/terraform/language/expressions/custom-conditions#condition-expressions) and an [error message](/terraform/language/expressions/custom-conditions#error-messages).
@@ -766,3 +825,188 @@ There are instances when Terraform does not execute a custom condition during th
766
825
Other kinds of failure _besides_ the specified expected failures in the checkable object still result in the overall test failing. For example, a variable that expects a boolean value as input fails the surrounding test if Terraform provides the wrong kind of value, even if that variable is included in an `expect_failures` attribute.
767
826
768
827
The `expect_failures` attribute is included to allow authors to test their configuration and any logic defined within. A type mismatch, as in the previous example, is not something Terraform authors should have to worry about testing as Terraform itself will handle enforce type constraints. As such, you can only `expect_failures` in custom conditions.
828
+
829
+
## Parallel execution
830
+
831
+
By default, Terraform executes `run` blocks sequentially. However, you can set the `parallel` attribute to `true` in the optional `test` block or in individual `run` blocks to enable parallel execution.
832
+
833
+
Two or more `run` blocks can be executed in parallel if:
834
+
835
+
- They do not reference outputs from each other.
836
+
- They do not share the same state file. The state file is determined by the state key or the module source when the state key is not set. If two `run` blocks that share the same module configuration, they must specify different state keys to be executed in parallel.
837
+
- They both have the `parallel` attribute set to `true`.
838
+
839
+
### Example usage
840
+
841
+
```hcl
842
+
# parallel.tftest.hcl
843
+
844
+
test {
845
+
// This would set the parallel flag to true in all runs
846
+
parallel = true
847
+
}
848
+
849
+
variables {
850
+
foo = "foo"
851
+
}
852
+
853
+
854
+
run "primary_db" {
855
+
// This is the first run block, and it is available to be executed right away.
856
+
state_key = "primary"
857
+
module {
858
+
source = "./setup"
859
+
}
860
+
861
+
variables {
862
+
input = "foo"
863
+
}
864
+
865
+
assert {
866
+
condition = output.value == var.foo
867
+
error_message = "bad"
868
+
}
869
+
}
870
+
871
+
run "secondary_db" {
872
+
// This run block can be executed in parallel with the `primary_db` run block, because it does not reference its
873
+
// output and has a different state key.
874
+
state_key = "secondary"
875
+
module {
876
+
source = "./setup"
877
+
}
878
+
879
+
variables {
880
+
input = "foo"
881
+
}
882
+
883
+
assert {
884
+
condition = output.value == var.foo
885
+
error_message = "bad"
886
+
}
887
+
}
888
+
889
+
run "site_one" {
890
+
// This run block can only be executed after the `primary_db` run block is completed, because it references the output of the `primary_db` run block.
891
+
state_key = "unique_2"
892
+
variables {
893
+
input = run.primary_db.value
894
+
}
895
+
896
+
assert {
897
+
condition = output.value == var.foo
898
+
error_message = "double bad"
899
+
}
900
+
}
901
+
902
+
run "site_two" {
903
+
// This run block can only be executed after the `primary_db` run block is completed, because it references the output of the `primary_db` run block.
904
+
// After that, it can be executed in parallel with the `site_one` run block.
905
+
state_key = "unique_3"
906
+
variables {
907
+
input = run.primary_db.value
908
+
}
909
+
910
+
assert {
911
+
condition = output.value == var.foo
912
+
error_message = "double bad"
913
+
}
914
+
}
915
+
916
+
run "using_external_db" {
917
+
// This run block does not reference the output of any other run block, and it has a different state key from its
918
+
// preceding runs, so it can be executed in parallel with runs `primary_db` and `secondary_db`.
919
+
state_key = "unique_4"
920
+
variables {
921
+
input = "externally_created_db"
922
+
}
923
+
924
+
assert {
925
+
condition = output.value == var.foo
926
+
error_message = "double bad"
927
+
}
928
+
}
929
+
930
+
run "site_four" {
931
+
// This run block has set `parallel = false`.
932
+
// Therefore, it will wait for all preceding runs to complete before it can be executed.
933
+
state_key = "unique_5"
934
+
935
+
// This overrides the global parallel flag.
936
+
parallel = false
937
+
variables {
938
+
input = run.secondary_db.value
939
+
}
940
+
941
+
assert {
942
+
condition = output.value == var.foo
943
+
error_message = "double bad"
944
+
}
945
+
}
946
+
947
+
run "site_five" {
948
+
// This run block will wait for the run `site_four` to complete, because run `site_four` has the `parallel` attribute set to `false`.
949
+
state_key = "unique_6"
950
+
variables {
951
+
input = run.secondary_db.value
952
+
}
953
+
954
+
assert {
955
+
condition = output.value == var.foo
956
+
error_message = "double bad"
957
+
}
958
+
}
959
+
960
+
run "site_six" {
961
+
// This run block can only be executed after the run `site_five` is completed, because it references the output of the run `site_five`.
962
+
state_key = "unique_7"
963
+
variables {
964
+
input = run.site_five.value
965
+
}
966
+
967
+
assert {
968
+
condition = output.value == var.foo
969
+
error_message = "double bad"
970
+
}
971
+
}
972
+
973
+
run "same_state" {
974
+
// This run block uses an existing state key "unique_7", so it will wait for the run `site_six` to complete.
975
+
state_key = "unique_7"
976
+
variables {
977
+
input = "another_external_db"
978
+
}
979
+
980
+
assert {
981
+
condition = output.value == var.foo
982
+
error_message = "double bad"
983
+
}
984
+
}
985
+
986
+
run "site_eight" {
987
+
// This run block is entirely unrelated to the other run blocks, however, because `site_four`,
988
+
// which is one of its preceding runs has the `parallel` attribute set to `false`,
989
+
// it cannot run until site_four is completed. It can be executed in parallel with `site_five` and `site_six`.
990
+
state_key = "unique_7"
991
+
variables {
992
+
input = "yet_another_external_db"
993
+
}
994
+
995
+
assert {
996
+
condition = output.value == var.foo
997
+
error_message = "double bad"
998
+
}
999
+
}
1000
+
```
1001
+
1002
+
-> **Note:** When you configure a series of runs that have `parallel=true` in a test file and include a single run with `parallel=false` you create synchronization point that divides the workflow into two groups. All runs before the `parallel=false` run must complete first. Then, after the run with `parallel=false` completes, the subsequent runs begin.
1003
+
1004
+
```
1005
+
Run A (parallel: true)
1006
+
Run B (parallel: true)
1007
+
Run C (parallel: false)
1008
+
Run D (parallel: true)
1009
+
Run E (parallel: true)
1010
+
```
1011
+
1012
+
Runs A and B execute simultaneously. Run C waits until both A and B are done before starting. Finally, runs D and E run in parallel, but only after C completes.
0 commit comments