Skip to content

Commit f7ac0e6

Browse files
WodansSonhqhqhqhqhqhqhqhqhqhqhq
authored andcommitted
[Contributor Documentation]: Add guidance for Acceptance Test PreCheck functions (hashicorp#31519)
1 parent e0ca8e3 commit f7ac0e6

1 file changed

Lines changed: 58 additions & 2 deletions

File tree

contributing/topics/reference-acceptance-testing.md

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,62 @@ As a general rule, the more complex the resource the more tests there are - for
1818

1919
See [Running the Tests](running-the-tests.md).
2020

21+
### PreCheck Helpers
22+
23+
Acceptance tests frequently require additional prerequisites beyond the standard Azure credentials and test locations (for example, access to a real DNS zone, an existing Key Vault/certificate, or other shared infrastructure).
24+
25+
To keep tests reliable (and to avoid creating resources that will inevitably fail), use a **pre-check** to either:
26+
27+
* **Skip** a test when optional external prerequisites are not available (e.g. an environment variable pointing to shared infrastructure is not set).
28+
* **Fail fast** only when the prerequisite is considered mandatory for all acceptance tests in the suite.
29+
30+
#### Global pre-check (mandatory)
31+
32+
The acceptance test framework already includes a global pre-check (`acceptance.PreCheck(t)`) which validates the required Azure authentication and test location environment variables.
33+
34+
This is intended for prerequisites that are required for *all* acceptance tests.
35+
36+
#### Resource/service-specific pre-check (recommended pattern)
37+
38+
For additional, test-specific prerequisites, the common convention in this repository is to implement a receiver method named `preCheck(t *testing.T)` on the test struct (for example `type ExampleResource struct {}`) and call it at the start of each `TestAcc...` that requires it.
39+
40+
When the prerequisites are not met, these pre-checks should typically call `t.Skip(...)` / `t.Skipf(...)` (rather than `t.Fatalf(...)`) so that:
41+
42+
* contributors without the optional infrastructure can still run unrelated tests successfully;
43+
* CI or scheduled runs can provide the prerequisites and run the full suite.
44+
45+
Example:
46+
47+
```go
48+
type ExampleResource struct{}
49+
50+
func TestAccExampleResource_basic(t *testing.T) {
51+
data := acceptance.BuildTestData(t, "azurerm_example_resource", "test")
52+
r := ExampleResource{}
53+
r.preCheck(t)
54+
55+
data.ResourceTest(t, r, []acceptance.TestStep{
56+
{
57+
Config: r.basic(data),
58+
Check: acceptance.ComposeTestCheckFunc(
59+
check.That(data.ResourceName).ExistsInAzure(r),
60+
),
61+
},
62+
data.ImportStep(),
63+
})
64+
}
65+
66+
func (ExampleResource) preCheck(t *testing.T) {
67+
if os.Getenv("ARM_TEST_SOME_PREREQ") == "" {
68+
t.Skip("Skipping as ARM_TEST_SOME_PREREQ is not set")
69+
}
70+
}
71+
```
72+
73+
#### Where to put `preCheck`
74+
75+
Go does not require a specific function order, but for readability it is recommended to place `preCheck` close to the tests that call it (commonly after the `TestAcc...` functions and before the `Exists`/`Destroy` methods), following the pattern used throughout `internal/services/*/*_test.go`.
76+
2177
### Test Package
2278

2379
While tests reside in the same folder as resource and data source .go files, they need to be in a separate test package to prevent circular references. i.e. for the file `./internal/services/aab2c/aadb2c_directory_data_source_test.go` the package should be:
@@ -269,7 +325,7 @@ func TestAccExampleResource_basic(t *testing.T) {
269325
}
270326

271327
func (r ExampleResource) requiresImport(data acceptance.TestData) string {
272-
template := r.basic(data)
328+
template := r.basic(data)
273329
return fmt.Sprintf(`
274330
%[1]s
275331
@@ -320,7 +376,7 @@ However, this doesn't necessarily cover all use-cases for this resource - or may
320376
func TestAccExampleResource_someSetting(t *testing.T) {
321377
data := acceptance.BuildTestData(t, "azurerm_example_resource", "test")
322378
r := ExampleResource{}
323-
379+
324380
data.ResourceTest(t, r, []acceptance.TestStep{
325381
{ // first provision the resource
326382
Config: r.someSetting(data, true),

0 commit comments

Comments
 (0)