Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use best practice package name in test examples #6731

Merged
merged 1 commit into from
May 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 66 additions & 40 deletions docs/content/policy-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ profile.

```live:example:module:read_only,openable
package authz

import rego.v1

allow if {
Expand All @@ -50,23 +51,26 @@ To test this policy, we will create a separate Rego file that contains test case
**example_test.rego**:

```live:example/test:module:read_only
package authz
package authz_test

import rego.v1

import data.authz

test_post_allowed if {
allow with input as {"path": ["users"], "method": "POST"}
authz.allow with input as {"path": ["users"], "method": "POST"}
}

test_get_anonymous_denied if {
not allow with input as {"path": ["users"], "method": "GET"}
not authz.allow with input as {"path": ["users"], "method": "GET"}
}

test_get_user_allowed if {
allow with input as {"path": ["users", "bob"], "method": "GET", "user_id": "bob"}
authz.allow with input as {"path": ["users", "bob"], "method": "GET", "user_id": "bob"}
}

test_get_another_user_denied if {
not allow with input as {"path": ["users", "bob"], "method": "GET", "user_id": "alice"}
not authz.allow with input as {"path": ["users", "bob"], "method": "GET", "user_id": "alice"}
}
```

Expand All @@ -81,10 +85,10 @@ To exercise the policy, run the `opa test` command in the directory containing t

```console
$ opa test . -v
data.authz.test_post_allowed: PASS (1.417µs)
data.authz.test_get_anonymous_denied: PASS (426ns)
data.authz.test_get_user_allowed: PASS (367ns)
data.authz.test_get_another_user_denied: PASS (320ns)
data.authz_test.test_post_allowed: PASS (1.417µs)
data.authz_test.test_get_anonymous_denied: PASS (426ns)
data.authz_test.test_get_user_allowed: PASS (367ns)
data.authz_test.test_get_another_user_denied: PASS (320ns)
--------------------------------------------------------------------------------
PASS: 4/4
```
Expand All @@ -97,19 +101,19 @@ Try exercising the tests a bit more by removing the first rule in **example.rego
$ opa test . -v
FAILURES
--------------------------------------------------------------------------------
data.authz.test_post_allowed: FAIL (277.306µs)
data.authz_test.test_post_allowed: FAIL (277.306µs)

query:1 Enter data.authz.test_post_allowed = _
example_test.rego:3 | Enter data.authz.test_post_allowed
example_test.rego:4 | | Fail data.authz.allow with input as {"method": "POST", "path": ["users"]}
query:1 | Fail data.authz.test_post_allowed = _
query:1 Enter data.authz_test.test_post_allowed = _
example_test.rego:3 | Enter data.authz_test.test_post_allowed
example_test.rego:4 | | Fail data.authz_test.allow with input as {"method": "POST", "path": ["users"]}
query:1 | Fail data.authz_test.test_post_allowed = _

SUMMARY
--------------------------------------------------------------------------------
data.authz.test_post_allowed: FAIL (277.306µs)
data.authz.test_get_anonymous_denied: PASS (124.287µs)
data.authz.test_get_user_allowed: PASS (242.2µs)
data.authz.test_get_another_user_denied: PASS (131.964µs)
data.authz_test.test_post_allowed: FAIL (277.306µs)
data.authz_test.test_get_anonymous_denied: PASS (124.287µs)
data.authz_test.test_get_user_allowed: PASS (242.2µs)
data.authz_test.test_get_another_user_denied: PASS (131.964µs)
--------------------------------------------------------------------------------
PASS: 3/4
FAIL: 1/4
Expand All @@ -118,12 +122,15 @@ FAIL: 1/4
## Test Format

Tests are expressed as standard Rego rules with a convention that the rule
name is prefixed with `test_`.
name is prefixed with `test_`. It's a good practice for tests to be placed in a package suffixed with `_test`, but not a requirement.

```live:example_format:module:read_only
package mypackage
package mypackage_test

import rego.v1

import data.mypackage

test_some_descriptive_name if {
# test logic
}
Expand Down Expand Up @@ -153,9 +160,12 @@ by zero condition) the test result is marked as an `ERROR`. Tests prefixed with
**pass_fail_error_test.rego**:

```live:example_results:module:read_only
package example
package example_test

import rego.v1

import data.example

# This test will pass.
test_ok if true

Expand All @@ -167,7 +177,7 @@ test_error if 1 / 0

# This test will be skipped.
todo_test_missing_implementation if {
allow with data.roles as ["not", "implemented"]
example.allow with data.roles as ["not", "implemented"]
}
```

Expand All @@ -176,8 +186,8 @@ of the tests that failed or errored.

```console
$ opa test pass_fail_error_test.rego
data.example.test_failure: FAIL (253ns)
data.example.test_error: ERROR (289ns)
data.example_test.test_failure: FAIL (253ns)
data.example_test.test_error: ERROR (289ns)
pass_fail_error_test.rego:15: eval_builtin_error: div: divide by zero
--------------------------------------------------------------------------------
PASS: 1/3
Expand All @@ -200,7 +210,7 @@ opa test --format=json pass_fail_error_test.rego
"row": 4,
"col": 1
},
"package": "data.example",
"package": "data.example_test",
"name": "test_ok",
"duration": 618515
},
Expand All @@ -210,7 +220,7 @@ opa test --format=json pass_fail_error_test.rego
"row": 9,
"col": 1
},
"package": "data.example",
"package": "data.example_test",
"name": "test_failure",
"fail": true,
"duration": 322177
Expand All @@ -221,7 +231,7 @@ opa test --format=json pass_fail_error_test.rego
"row": 14,
"col": 1
},
"package": "data.example",
"package": "data.example_test",
"name": "test_error",
"error": {
"code": "eval_internal_error",
Expand Down Expand Up @@ -255,6 +265,7 @@ Below is a simple policy that depends on the data document.

```live:with_keyword:module:read_only,openable
package authz

import rego.v1

allow if {
Expand All @@ -271,14 +282,17 @@ Below is the Rego file to test the above policy.
**authz_test.rego**:

```live:with_keyword/tests:module:read_only
package authz
package authz_test

import rego.v1

import data.authz

policies := [{"name": "test_policy"}]
roles := {"admin": ["alice"]}

test_allow_with_data if {
allow with input as {"user": "alice", "role": "admin"}
authz.allow with input as {"user": "alice", "role": "admin"}
with data.policies as policies
with data.roles as roles
}
Expand All @@ -288,7 +302,7 @@ To exercise the policy, run the `opa test` command.

```console
$ opa test -v authz.rego authz_test.rego
data.authz.test_allow_with_data: PASS (697ns)
data.authz_test.test_allow_with_data: PASS (697ns)
--------------------------------------------------------------------------------
PASS: 1/1
```
Expand All @@ -299,6 +313,7 @@ Below is an example to replace a **rule without arguments**.

```live:with_keyword_rules:module:read_only
package authz

import rego.v1

allow1 if allow2
Expand All @@ -309,17 +324,20 @@ allow2 if 2 == 1
**authz_test.rego**:

```live:with_keyword_rules/tests:module:read_only
package authz
package authz_test

import rego.v1

import data.authz

test_replace_rule if {
allow1 with allow2 as true
authz.allow1 with authz.allow2 as true
}
```

```console
$ opa test -v authz.rego authz_test.rego
data.authz.test_replace_rule: PASS (328ns)
data.authz_test.test_replace_rule: PASS (328ns)
--------------------------------------------------------------------------------
PASS: 1/1
```
Expand All @@ -330,6 +348,7 @@ Here is an example to replace a rule's **built-in function** with a user-defined

```live:with_keyword_builtins:module:read_only
package authz

import rego.v1

import data.jwks.cert
Expand All @@ -342,22 +361,25 @@ allow if {
**authz_test.rego**:

```live:with_keyword_builtins/tests:module:read_only
package authz
package authz_test

import rego.v1

import data.authz

mock_decode_verify("my-jwt", _) := [true, {}, {}]
mock_decode_verify(x, _) := [false, {}, {}] if x != "my-jwt"

test_allow if {
allow with input.headers["x-token"] as "my-jwt"
authz.allow with input.headers["x-token"] as "my-jwt"
with data.jwks.cert as "mock-cert"
with io.jwt.decode_verify as mock_decode_verify
}
```

```console
$ opa test -v authz.rego authz_test.rego
data.authz.test_allow: PASS (458.752µs)
data.authz_test.test_allow: PASS (458.752µs)
--------------------------------------------------------------------------------
PASS: 1/1
```
Expand All @@ -366,7 +388,7 @@ In simple cases, a function can also be replaced with a value, as in

```live:with_keyword_builtins/tests/value:module:read_only
test_allow_value if {
allow
authz.allow
with input.headers["x-token"] as "my-jwt"
with data.jwks.cert as "mock-cert"
with io.jwt.decode_verify as [true, {}, {}]
Expand All @@ -383,6 +405,7 @@ function by a built-in function.

```live:with_keyword_funcs:module:read_only
package authz

import rego.v1

replace_rule if {
Expand All @@ -397,17 +420,20 @@ replace(label) if {
**authz_test.rego**:

```live:with_keyword_funcs/tests:module:read_only
package authz
package authz_test

import rego.v1

import data.authz

test_replace_rule if {
replace_rule with input.label as "does-not-matter" with replace as true
authz.replace_rule with input.label as "does-not-matter" with replace as true
}
```

```console
$ opa test -v authz.rego authz_test.rego
data.authz.test_replace_rule: PASS (648.314µs)
data.authz_test.test_replace_rule: PASS (648.314µs)
--------------------------------------------------------------------------------
PASS: 1/1
```
Expand Down