---
title: "Test infrastructure modules · Agent Wranglers"
url: https://agentwranglers.se/playbook/infrastructure/policy-as-code/test-infrastructure-modules
updated: 2026-10-20
licence: "All rights reserved"
---

# Test infrastructure modules

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Recommended
- Chapter: [Policy as code](https://agentwranglers.se/playbook/infrastructure/policy-as-code)
- Rule: Give every shared module tests that check its plan, and run them in CI on every change to the module.
- How: Test what the module promises, such as encryption on, no public address and the right tags. Plan-only tests run in seconds and need no cloud account. Use the built-in `test` command of OpenTofu and Terraform, or Pulumi's unit tests with mocks. Run a slower test that creates and destroys the module in a sandbox account before each release.
- Check: Remove the encryption setting from the module in a test branch. A module test fails.

Example:

```hcl
# tests/bucket.tftest.hcl
run "bucket_is_private" {
  command = plan
  variables {
    name = "test-bucket"
  }
  assert {
    condition     = aws_s3_bucket_public_access_block.this.restrict_public_buckets == true
    error_message = "The bucket must block public access."
  }
}
```

```ts
// Pulumi unit test in TypeScript with mocks: no cloud account needed
import * as pulumi from '@pulumi/pulumi';
import { test } from 'node:test';
import assert from 'node:assert/strict';

pulumi.runtime.setMocks({
  newResource: args => ({ id: `${args.name}-id`, state: args.inputs }),
  call: args => args.inputs,
});

test('the database has no public address', async () => {
  const { database } = await import('./database.js');
  const isPublic = await new Promise(resolve => database.publiclyAccessible.apply(resolve));
  assert.equal(isPublic, false);
});
```

```python
# Pulumi unit test in Python with mocks
import pulumi

class Mocks(pulumi.runtime.Mocks):
    def new_resource(self, args):
        return [f"{args.name}-id", args.inputs]

    def call(self, args):
        return {}

pulumi.runtime.set_mocks(Mocks())
import database  # noqa: E402, the module must load after the mocks

@pulumi.runtime.test
def test_database_is_private():
    return database.database.publicly_accessible.apply(lambda is_public: assert_private(is_public))

def assert_private(is_public):
    assert is_public is False
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers infrastructure playbook: https://agentwranglers.se/playbook/infrastructure/policy-as-code/test-infrastructure-modules`.

- Previous: [Let every exception expire](https://agentwranglers.se/playbook/infrastructure/policy-as-code/expiring-policy-exceptions)
- [Policy as code](https://agentwranglers.se/playbook/infrastructure/policy-as-code)
