# `AshGrant.PolicyTest.Runner`
[🔗](https://github.com/jhlee111/ash_grant/blob/v0.14.1/lib/ash_grant/policy_test/runner.ex#L1)

Executes policy tests and collects results.

The runner provides two main functions:

- `run_module/1` - Run all tests in a single module
- `run_all/1` - Run tests across multiple modules with summary statistics

## Examples

    # Run a single module
    results = Runner.run_module(MyApp.PolicyTests.DocumentTest)

    # Run multiple modules
    summary = Runner.run_all(modules: [DocumentTest, PostTest])

    # Run with discovery (finds all policy test modules)
    summary = Runner.run_all(path: "test/policy_tests/")

# `summary`

```elixir
@type summary() :: %{
  passed: non_neg_integer(),
  failed: non_neg_integer(),
  results: [AshGrant.PolicyTest.Result.t()]
}
```

# `discover_modules`

```elixir
@spec discover_modules(String.t()) :: [module()]
```

Discovers policy test modules from a path.

Finds all modules that `use AshGrant.PolicyTest` in the given path.

# `run_all`

```elixir
@spec run_all(keyword()) :: summary()
```

Runs tests across multiple modules and returns a summary.

## Options

- `:modules` - List of modules to run tests from
- `:path` - Path to directory containing policy test files (discovers modules)

## Examples

    # Run specific modules
    summary = Runner.run_all(modules: [DocumentTest, PostTest])

    # Discover and run all policy tests in a directory
    summary = Runner.run_all(path: "test/policy_tests/")

## Returns

    %{
      passed: 10,
      failed: 2,
      results: [%Result{}, ...]
    }

# `run_module`

```elixir
@spec run_module(module()) :: [AshGrant.PolicyTest.Result.t()]
```

Runs all tests in a policy test module.

Returns a list of `Result` structs, one for each test.

## Examples

    results = Runner.run_module(MyApp.PolicyTests.DocumentTest)

    Enum.each(results, fn result ->
      if result.passed do
        IO.puts("✓ #{result.test_name}")
      else
        IO.puts("✗ #{result.test_name}: #{result.message}")
      end
    end)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
