Testing Minder Rules
mindev test is the supported mechanism for verifying rule behavior, designed for integration into CI/CD pipelines as well as standalone local usage. It allows you to write automated unit tests for your custom rule types offline, without needing a live provider or real credentials.
The testing framework is built on Starlark (a Python-like configuration language) and uses mock HTTP responses and mock filesystems to simulate provider APIs and git repositories.
Running Tests Locally
To run Starlark tests in a directory containing *_test.star files:
mindev test .
By default, mindev test . will recursively find and run all *_test.star files in the current directory and its subdirectories.
Generating JUnit Output
For integration with test reporting tools, generate a JUnit XML report with:
mindev test . --junit-file report.xml
Creating a Test File
Test files must be written in Starlark and have a _test.star suffix. By convention, they are placed in the same directory as the rule type definition.
If your rule type is named branch_protection_enforce_admins.yaml, create a test file named branch_protection_enforce_admins_test.star.
A test file consists of one or more functions that start with test_. The mindev test command will discover and run these functions automatically.
Basic example:
# branch_protection_enforce_admins_test.star
ENTITY = {
"owner": "mindersec",
"name": "minder",
"type": "repository",
"default_branch": "main"
}
def build_mock_http(enabled):
return {
"/repos/mindersec/minder/branches/main/protection": body({
"enforce_admins": {"enabled": enabled}
})
}
def test_enforce_admins_pass():
result = eval(
rule="branch_protection_enforce_admins",
entity=ENTITY,
profile={"enforce_admins": True},
mock_http=build_mock_http(True)
)
assert result["status"] == "pass", "Expected rule to pass"
def test_enforce_admins_fail():
result = eval(
rule="branch_protection_enforce_admins",
entity=ENTITY,
profile={"enforce_admins": True},
mock_http=build_mock_http(False)
)
assert result["status"] == "fail", "Expected rule to fail"
Starlark Runtime Reference
The testing environment provides several built-in functions to evaluate rules and mock external data.
eval()
The eval() function executes a rule type against a mock environment and returns a result dictionary.
Arguments:
rule(Required, String): Name or file path of the rule type to evaluate (e.g."branch_protection_enforce_admins").entity(Optional, Dict): The entity object dictionary to evaluate against.profile(Optional, Dict): Profile configuration dictionary to evaluate rule parameters.params(Optional, Dict): Rule parameters dictionary (matches the rule'sparam_schema).mock_http(Optional, Dict): A dictionary mapping URL endpoint paths to mock HTTP responses generated bybody()orcode().mock_fs(Optional, Dict): A dictionary mapping file paths to file content strings forgitingest rules.data_sources(Optional, List): A list of paths to datasource YAML files required by the rule type.
Return Value:
An object dictionary containing:
result["status"]:"pass","fail","skip", or"error"result["message"]: String detailing the evaluation failure, skip reason, or error message (if any).result["output"]: The evaluation output value returned by the rule (if any).
body() and code()
These helpers generate mock HTTP responses for mock_http:
body(payload): Returns a 200 OK HTTP response withpayload(can be a dictionary, list, string, or number).code(status_code): Returns an empty HTTP response with the given status code (e.g.,code(404)orcode(500)).
read_file()
Reads a file relative to the test file directory and returns its content as a string. Useful for reading test fixtures or JSON payloads:
payload = read_file("testdata/response.json")
txtar()
Parses a txtar archive string into a dictionary of file paths to file contents, ideal for mocking multi-file git repositories in mock_fs.
archive = read_file("testdata/repo.txtar")
files = txtar(archive)
result = eval(
rule="check_workflows",
mock_fs=files
)
Running Tests in CI/CD
To run Starlark rule tests automatically in GitHub Actions, use the official mindersec/minder-action/test action:
name: Rule Type Tests
on:
push:
branches: [main]
pull_request:
jobs:
test-rules:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run mindev test
uses: mindersec/minder-action/test@v1
You can also combine this with JUnit report publishing:
- name: Run mindev test with JUnit report
uses: mindersec/minder-action/test@v1
with:
flags: --junit-file report.xml
- name: Publish Test Report
uses: mikepenz/action-junit-report@v4
if: always()
with:
report_paths: 'report.xml'