PropertyDamage.Analysis (PropertyDamage v0.1.0)
View SourceAdvanced failure analysis tools for understanding and debugging test failures.
This module provides tools that go beyond basic shrinking to help users understand why a failure occurs and what specifically triggers it.
Features
- Causal Explanation: Understand why each command in the shrunk sequence is needed
- Trigger Isolation: Find the minimal change that eliminates the failure
- Test Generation: Generate reproducible test code from failures
Usage
{:error, failure} = PropertyDamage.run(model: M, adapter: A)
# Understand why each command is needed
PropertyDamage.Analysis.explain(failure)
# Find what triggers the bug
PropertyDamage.Analysis.isolate_trigger(failure)
# Generate a test case
PropertyDamage.Analysis.generate_test(failure, format: :exunit)
Summary
Functions
Explain why each command in the shrunk sequence is needed for the failure.
Format an explanation as a human-readable string.
Generate a reproducible test case from a failure.
Find the minimal change that eliminates the failure.
Functions
@spec explain(PropertyDamage.FailureReport.t()) :: map()
Explain why each command in the shrunk sequence is needed for the failure.
Returns a structured explanation showing:
- The dependency graph between commands
- Which command triggers the failure
- Why each other command must be present
Example
PropertyDamage.Analysis.explain(failure)
# Returns:
# %{
# commands: [
# %{index: 0, command: "CreateAccount", role: :dependency,
# reason: "Creates account used by command 2"},
# %{index: 1, command: "CreateAuthorization", role: :dependency,
# reason: "Creates pending hold affecting available balance"},
# %{index: 2, command: "CreditAccount", role: :trigger,
# reason: "Causes currency_consistency check to fail"}
# ],
# failure: %{type: :check_failed, check: :currency_consistency, ...}
# }
Format an explanation as a human-readable string.
@spec generate_test( PropertyDamage.FailureReport.t(), keyword() ) :: String.t()
Generate a reproducible test case from a failure.
Creates runnable code that reproduces the failure, suitable for adding to a test suite or sharing with colleagues.
Options
:format- Output format (:exunit,:script,:markdown). Default::exunit:module_name- Module name for ExUnit tests. Default: "ReproductionTest":include_setup- Include model/adapter setup code. Default: true
Example
PropertyDamage.Analysis.generate_test(failure, format: :exunit)
# Generates ExUnit test code
@spec isolate_trigger( PropertyDamage.FailureReport.t(), keyword() ) :: {:ok, map()} | {:error, term()}
Find the minimal change that eliminates the failure.
This performs differential analysis to identify exactly what triggers the bug. It tries variations of the failing command to find the smallest change that makes the failure disappear.
Returns
A map containing:
:trigger_command- The command that triggers the failure:changes- List of changes that eliminate the failure:likely_cause- Inferred cause based on the changes
Example
PropertyDamage.Analysis.isolate_trigger(failure)
# %{
# trigger_command: %CreditAccount{...},
# changes: [
# %{field: :currency, original: "EUR", fixed: "USD",
# description: "Changing currency from EUR to USD eliminates failure"}
# ],
# likely_cause: "Currency mismatch: account currency (USD) differs from operation currency (EUR)"
# }