caseweave

    Deterministic constrained combinatorial test matrix generator for MoonBit.

    testing
    pairwise
    covering-array
    constraints
    ci
    Download zip
    Author
    Version
    0.1.1
    License
    MIT
    Last updated
    2 months ago
    Downloads
    38

    No dependencies

    #CaseWeave

    MoonBit package documentation lives in README.md.

    CasePattern

    pub(all) struct CasePattern {
    choices : Array[NamedChoice]
    } derive(Eq,
    Debug
    )

    A partial assignment such as os=linux, browser=chrome.

    CasePattern::matches

    fn CasePattern::matches(self : CasePattern, model : Model, test_case : TestCase) -> Result[Bool, CaseWeaveError]

    CasePattern::to_case

    fn CasePattern::to_case(self : CasePattern, model : Model, line_no? : Int) -> Result[TestCase, CaseWeaveError]

    CasePattern::to_exclusion_constraint

    fn CasePattern::to_exclusion_constraint(self : CasePattern, label : String) -> Result[Constraint, CaseWeaveError]

    CasePattern::to_text

    fn CasePattern::to_text(self : CasePattern) -> String

    CasePattern::validate

    fn CasePattern::validate(self : CasePattern, model : Model) -> Result[Unit, CaseWeaveError]

    CaseRisk

    pub(all) struct CaseRisk {
    score : Int
    reasons : Array[String]
    } derive(Eq,
    Debug
    )

    Risk score for one concrete case.

    CaseWeaveError

    pub(all) enum CaseWeaveError {
    EmptyModel
    EmptyParameterName(Int)
    DuplicateParameter(String)
    EmptyValues(String)
    EmptyValue(String, Int)
    DuplicateValue(String, String)
    InvalidStrength(Int, Int)
    InvalidCandidateLimit(Int)
    InvalidSuggestionLimit(Int)
    CandidateLimitExceeded(Int)
    NoValidCases
    UncoverableInteraction
    ParseError(Int, String)
    UnknownParameter(String)
    UnknownValue(String, String)
    InvalidCaseWidth(Int, Int)
    InvalidCaseValue(String, String)
    ConstraintViolation(Int, String)
    } derive(Eq,
    Debug
    )

    Errors returned by model validation, constraint parsing, generation and coverage analysis. Public operations return Result so callers can report input problems without relying on panics.

    Constraint

    pub(all) struct Constraint {
    label : String
    expression : ConstraintExpr
    } derive(Eq,
    Debug
    )

    Constraint::matches

    fn Constraint::matches(self : Constraint, model : Model, test_case : TestCase) -> Result[Bool, CaseWeaveError]

    Constraint::new

    fn Constraint::new(label : String, expression : ConstraintExpr) -> Constraint

    Constraint::parse

    fn Constraint::parse(label : String, source : String) -> Result[Constraint, CaseWeaveError]

    Constraint::validate

    fn Constraint::validate(self : Constraint, model : Model) -> Result[Unit, CaseWeaveError]

    ConstraintExpr

    pub(all) enum ConstraintExpr {
    Equal(String, String)
    NotEqual(String, String)
    OneOf(String, Array[String])
    NoneOf(String, Array[String])
    And(ConstraintExpr, ConstraintExpr)
    Or(ConstraintExpr, ConstraintExpr)
    Implies(ConstraintExpr, ConstraintExpr)
    Not(ConstraintExpr)
    Always
    Never
    } derive(Eq,
    Debug
    )

    Boolean constraint language used to exclude impossible or unwanted test combinations. Atoms address parameters and values by name, keeping models readable and independent from internal indexes.

    CoverageReport

    pub(all) struct CoverageReport {
    strength : Int
    case_count : Int
    total_interactions : Int
    covered_interactions : Int
    coverage_percent : Double
    missing : Array[MissingInteraction]
    } derive(
    Debug
    )

    Coverage audit for an arbitrary suite. Missing interactions are named so they can be printed directly in CI diagnostics.

    CoverageReport::is_complete

    fn CoverageReport::is_complete(self : CoverageReport) -> Bool

    CoverageReport::missing_text

    fn CoverageReport::missing_text(self : CoverageReport) -> String

    Render missing interactions as readable lines.

    CoverageReport::summary

    fn CoverageReport::summary(self : CoverageReport) -> String

    One-line coverage summary suitable for CI logs.

    GateFailure

    pub(all) struct GateFailure {
    kind : GateFailureKind
    message : String
    } derive(Eq,
    Debug
    )

    GateFailureKind

    pub(all) enum GateFailureKind {
    IncompleteCoverage(Int, Int)
    TooManyMissingInteractions(Int, Int)
    TooFewCases(Int, Int)
    TooManyCases(Int, Int)
    TopRiskTooLow(Int, Int)
    TooFewPositiveRiskCases(Int, Int)
    ScenarioWarnings(Int)
    } derive(Eq,
    Debug
    )

    GateReport

    pub(all) struct GateReport {
    passed : Bool
    failures : Array[GateFailure]
    warnings : Array[SpecWarning]
    coverage : CoverageReport
    case_count : Int
    top_risk_score : Int
    positive_risk_cases : Int
    }

    GateReport::failure_text

    fn GateReport::failure_text(self : GateReport) -> String

    GateReport::is_passed

    fn GateReport::is_passed(self : GateReport) -> Bool

    GateReport::summary

    fn GateReport::summary(self : GateReport) -> String

    GateReport::to_markdown

    fn GateReport::to_markdown(self : GateReport) -> String

    GateReport::warning_text

    fn GateReport::warning_text(self : GateReport) -> String

    GenerationOptions

    pub(all) struct GenerationOptions {
    strength : Int
    max_candidates : Int
    minimize : Bool
    } derive(Eq,
    Debug
    )

    Controls covering-array generation. max_candidates bounds the exhaustive candidate phase; constraints are evaluated during enumeration so invalid branches are pruned early.

    GenerationOptions::default

    GenerationOptions::pairwise

    fn GenerationOptions::pairwise(max_candidates? : Int) -> GenerationOptions

    GenerationStats

    pub(all) struct GenerationStats {
    cartesian_size : Int64
    examined_candidates : Int
    feasible_candidates : Int
    required_interactions : Int
    selected_cases : Int
    removed_redundant_cases : Int
    } derive(Eq,
    Debug
    )

    InteractionRisk

    pub(all) struct InteractionRisk {
    pattern : CasePattern
    weight : Int
    note : String
    } derive(Eq,
    Debug
    )

    A risk attached to an interaction pattern.

    MissingInteraction

    pub(all) struct MissingInteraction {
    choices : Array[NamedChoice]
    } derive(Eq,
    Debug
    )

    Model

    pub struct Model {
    parameters : Array[Parameter]
    }

    A validated ordered collection of parameters.

    Model::combination_count

    fn Model::combination_count(self : Model) -> Int64

    Model::new

    fn Model::new(parameters : Array[Parameter]) -> Result[Model, CaseWeaveError]

    Model::parameter

    fn Model::parameter(self : Model, index : Int) -> Parameter?

    Model::parameter_count

    fn Model::parameter_count(self : Model) -> Int

    Model::parameter_index

    fn Model::parameter_index(self : Model, name : String) -> Int?

    Model::parameters

    fn Model::parameters(self : Model) -> Array[Parameter]

    Model::validate_case

    fn Model::validate_case(self : Model, test_case : TestCase) -> Result[Unit, CaseWeaveError]

    Model::value_index

    fn Model::value_index(self : Model, parameter_index : Int, value : String) -> Int?

    NamedChoice

    pub(all) struct NamedChoice {
    parameter : String
    value : String
    } derive(Eq,
    Debug
    )

    Parameter

    pub(all) struct Parameter {
    name : String
    values : Array[String]
    } derive(Eq,
    Debug
    )

    One dimension in the input space. Values are kept in declaration order so generation and exported output remain deterministic.

    Parameter::new

    fn Parameter::new(name : String, values : Array[String]) -> Parameter

    RankedCase

    pub(all) struct RankedCase {
    rank : Int
    index : Int
    test_case : TestCase
    score : Int
    reasons : Array[String]
    } derive(Eq,
    Debug
    )

    A generated case ordered by descending risk score.

    RepairGate

    pub(all) struct RepairGate {
    require_complete : Bool
    max_additions : Int
    max_final_missing : Int
    min_largest_gain : Int
    }

    RepairGate::best_effort

    fn RepairGate::best_effort(max_additions : Int, max_final_missing : Int) -> RepairGate

    RepairGate::budget

    fn RepairGate::budget(max_additions : Int) -> RepairGate

    RepairGate::default

    fn RepairGate::default() -> RepairGate

    RepairGate::normalize

    fn RepairGate::normalize(self : RepairGate) -> RepairGate

    RepairGateFailure

    pub(all) struct RepairGateFailure {
    kind : RepairGateFailureKind
    message : String
    } derive(Eq,
    Debug
    )

    RepairGateFailureKind

    pub(all) enum RepairGateFailureKind {
    RepairIncomplete(Int)
    TooManyRepairAdditions(Int, Int)
    TooManyRemainingInteractions(Int, Int)
    LargestGainTooLow(Int, Int)
    } derive(Eq,
    Debug
    )

    RepairGateReport

    pub(all) struct RepairGateReport {
    passed : Bool
    failures : Array[RepairGateFailure]
    additions : Int
    initial_missing : Int
    final_missing : Int
    largest_gain : Int
    complete : Bool
    }

    RepairGateReport::failure_text

    fn RepairGateReport::failure_text(self : RepairGateReport) -> String

    RepairGateReport::is_passed

    fn RepairGateReport::is_passed(self : RepairGateReport) -> Bool

    RepairGateReport::summary

    fn RepairGateReport::summary(self : RepairGateReport) -> String

    RepairGateReport::to_markdown

    fn RepairGateReport::to_markdown(self : RepairGateReport) -> String

    RepairOptions

    pub(all) struct RepairOptions {
    strength : Int
    max_candidates : Int
    max_suggestions : Int
    }

    Options for repairing an incomplete suite. The planner uses the same interaction model as audit, then greedily proposes additional feasible cases that cover the largest number of currently missing interactions.

    RepairOptions::default

    fn RepairOptions::default() -> RepairOptions

    RepairOptions::from_generation

    fn RepairOptions::from_generation(options : GenerationOptions, max_suggestions? : Int) -> RepairOptions

    RepairOptions::normalize

    fn RepairOptions::normalize(self : RepairOptions) -> RepairOptions

    RepairOptions::pairwise

    fn RepairOptions::pairwise(max_candidates? : Int, max_suggestions? : Int) -> RepairOptions

    RepairPlan

    pub(all) struct RepairPlan {
    model : Model
    original_cases : Array[TestCase]
    additions : Array[TestCase]
    merged_cases : Array[TestCase]
    original_report : CoverageReport
    final_report : CoverageReport
    steps : Array[RepairStep]
    complete : Bool
    initial_missing : Int
    final_missing : Int
    }

    RepairPlan::addition_count

    fn RepairPlan::addition_count(self : RepairPlan) -> Int

    RepairPlan::additions

    fn RepairPlan::additions(self : RepairPlan) -> Array[TestCase]

    RepairPlan::additions_markdown

    fn RepairPlan::additions_markdown(self : RepairPlan) -> String

    RepairPlan::evaluate_repair_gate

    fn RepairPlan::evaluate_repair_gate(self : RepairPlan, gate? : RepairGate) -> RepairGateReport

    RepairPlan::highest_risk_step

    fn RepairPlan::highest_risk_step(self : RepairPlan) -> RepairStep?

    RepairPlan::is_complete

    fn RepairPlan::is_complete(self : RepairPlan) -> Bool

    RepairPlan::largest_gain_step

    fn RepairPlan::largest_gain_step(self : RepairPlan) -> RepairStep?

    RepairPlan::largest_repair_gain

    fn RepairPlan::largest_repair_gain(self : RepairPlan) -> Int

    RepairPlan::merged_cases

    fn RepairPlan::merged_cases(self : RepairPlan) -> Array[TestCase]

    RepairPlan::merged_markdown

    fn RepairPlan::merged_markdown(self : RepairPlan) -> String

    RepairPlan::missing_after_text

    fn RepairPlan::missing_after_text(self : RepairPlan) -> String

    RepairPlan::risk_summary

    fn RepairPlan::risk_summary(self : RepairPlan) -> String

    RepairPlan::steps

    fn RepairPlan::steps(self : RepairPlan) -> Array[RepairStep]

    RepairPlan::steps_markdown

    fn RepairPlan::steps_markdown(self : RepairPlan, top? : Int) -> String

    RepairPlan::summary

    fn RepairPlan::summary(self : RepairPlan) -> String

    RepairPlan::to_markdown

    fn RepairPlan::to_markdown(self : RepairPlan) -> String

    RepairStep

    pub(all) struct RepairStep {
    index : Int
    test_case : TestCase
    newly_covered : Array[MissingInteraction]
    remaining_missing : Int
    risk_score : Int
    reasons : Array[String]
    } derive(Eq,
    Debug
    )

    ScenarioGate

    pub(all) struct ScenarioGate {
    require_complete_coverage : Bool
    max_missing_interactions : Int
    min_cases : Int
    max_cases : Int
    min_top_risk_score : Int
    min_positive_risk_cases : Int
    allow_warnings : Bool
    }

    CI-oriented policy for generated scenario runs. It turns coverage, risk and scenario-lint facts into a small pass/fail report that can be printed in a release job.

    ScenarioGate::coverage_only

    fn ScenarioGate::coverage_only() -> ScenarioGate

    ScenarioGate::default

    fn ScenarioGate::default() -> ScenarioGate

    ScenarioGate::describe

    fn ScenarioGate::describe(self : ScenarioGate) -> String

    ScenarioGate::normalize

    fn ScenarioGate::normalize(self : ScenarioGate) -> ScenarioGate

    ScenarioGate::strict

    fn ScenarioGate::strict() -> ScenarioGate

    ScenarioGate::with_case_budget

    fn ScenarioGate::with_case_budget(min_cases : Int, max_cases : Int) -> ScenarioGate

    ScenarioGate::with_risk_floor

    fn ScenarioGate::with_risk_floor(min_top_risk_score : Int, min_positive_risk_cases : Int) -> ScenarioGate

    ScenarioRun

    pub(all) struct ScenarioRun {
    spec_name : String
    model : Model
    suite : Suite
    cases : Array[TestCase]
    included_case_count : Int
    coverage : CoverageReport
    ranked_cases : Array[RankedCase]
    }

    End-to-end execution result for a parsed scenario spec.

    ScenarioRun::cases_markdown

    fn ScenarioRun::cases_markdown(self : ScenarioRun) -> String

    ScenarioRun::evaluate_gate

    fn ScenarioRun::evaluate_gate(self : ScenarioRun, spec : ScenarioSpec, gate? : ScenarioGate) -> GateReport

    ScenarioRun::evaluate_normalized_gate

    fn ScenarioRun::evaluate_normalized_gate(self : ScenarioRun, spec : ScenarioSpec, gate : ScenarioGate) -> GateReport

    ScenarioRun::positive_risk_case_count

    fn ScenarioRun::positive_risk_case_count(self : ScenarioRun) -> Int

    ScenarioRun::risk_markdown

    fn ScenarioRun::risk_markdown(self : ScenarioRun, top? : Int) -> String

    ScenarioRun::summary

    fn ScenarioRun::summary(self : ScenarioRun) -> String

    ScenarioRun::top_risk_score

    fn ScenarioRun::top_risk_score(self : ScenarioRun) -> Int

    ScenarioSpec

    pub(all) struct ScenarioSpec {
    name : String
    model : Model
    constraints : Array[Constraint]
    options : GenerationOptions
    included_cases : Array[TestCase]
    excluded_patterns : Array[CasePattern]
    value_risks : Array[ValueRisk]
    interaction_risks : Array[InteractionRisk]
    }

    A compact, line-oriented scenario format for teams that want to keep their covering-array model beside design docs, issues or CI configuration.

    ScenarioSpec::generate_suite

    fn ScenarioSpec::generate_suite(self : ScenarioSpec) -> Result[Suite, CaseWeaveError]

    ScenarioSpec::lint

    ScenarioSpec::lint_text

    fn ScenarioSpec::lint_text(self : ScenarioSpec) -> String

    ScenarioSpec::parse

    fn ScenarioSpec::parse(source : String) -> Result[ScenarioSpec, CaseWeaveError]

    ScenarioSpec::plan_repair

    fn ScenarioSpec::plan_repair(self : ScenarioSpec, cases : Array[TestCase], options? : RepairOptions) -> Result[RepairPlan, CaseWeaveError]

    ScenarioSpec::rank_cases

    fn ScenarioSpec::rank_cases(self : ScenarioSpec, cases : Array[TestCase]) -> Result[Array[RankedCase], CaseWeaveError]

    ScenarioSpec::run

    ScenarioSpec::score_case

    fn ScenarioSpec::score_case(self : ScenarioSpec, test_case : TestCase) -> Result[CaseRisk, CaseWeaveError]

    ScenarioSpec::summary

    fn ScenarioSpec::summary(self : ScenarioSpec) -> String

    SpecWarning

    pub(all) struct SpecWarning {
    kind : SpecWarningKind
    message : String
    } derive(Eq,
    Debug
    )

    SpecWarningKind

    pub(all) enum SpecWarningKind {
    NoConstraints
    NoRiskHints
    NoIncludedCases
    StrengthOne
    CandidateLimitBelowCartesian(Int64, Int)
    SingleValueParameter(String)
    } derive(Eq,
    Debug
    )

    Non-blocking quality hints for scenario specifications.

    Suite

    pub struct Suite {
    cases : Array[TestCase]
    strength : Int
    stats : GenerationStats
    }

    Generated cases plus reproducibility and compression statistics.

    Suite::cases

    fn Suite::cases(self : Suite) -> Array[TestCase]

    Suite::length

    fn Suite::length(self : Suite) -> Int

    Suite::stats

    fn Suite::stats(self : Suite) -> GenerationStats

    Suite::strength

    fn Suite::strength(self : Suite) -> Int

    Suite::summary

    fn Suite::summary(self : Suite) -> String

    One-line generation summary suitable for CLI output.

    Suite::to_csv

    fn Suite::to_csv(self : Suite, model : Model) -> String

    Render a generated suite as CSV with a header row in model order.

    Suite::to_json

    fn Suite::to_json(self : Suite, model : Model) -> String

    Render a generated suite as a compact JSON document.

    Suite::to_markdown

    fn Suite::to_markdown(self : Suite, model : Model) -> String

    Render a generated suite as a Markdown table for READMEs and issue reports.

    TestCase

    pub(all) struct TestCase {
    values : Array[String]
    } derive(Eq,
    Debug
    )

    A concrete test vector in model order.

    TestCase::assignment_text

    fn TestCase::assignment_text(self : TestCase, model : Model) -> String

    TestCase::get

    fn TestCase::get(self : TestCase, index : Int) -> String?

    TestCase::new

    fn TestCase::new(values : Array[String]) -> TestCase

    TestCase::value_for

    fn TestCase::value_for(self : TestCase, model : Model, parameter : String) -> String?

    ValueRisk

    pub(all) struct ValueRisk {
    choice : NamedChoice
    weight : Int
    note : String
    } derive(Eq,
    Debug
    )

    A risk attached to one parameter value.

    audit

    fn audit(model : Model, cases : Array[TestCase], strength? : Int, constraints? : Array[Constraint], max_candidates? : Int) -> Result[CoverageReport, CaseWeaveError]

    cases_to_csv

    fn cases_to_csv(model : Model, cases : Array[TestCase]) -> String

    Render arbitrary cases as CSV. This is useful when callers load a suite from another source and want the same escaping rules as generated suites.

    cases_to_markdown

    fn cases_to_markdown(model : Model, cases : Array[TestCase]) -> String

    Render arbitrary cases as a Markdown table.

    generate

    fn generate(model : Model, constraints? : Array[Constraint], options? : GenerationOptions) -> Result[Suite, CaseWeaveError]

    Generate a deterministic constrained covering array. Candidate order, greedy tie-breaking, and redundancy elimination are stable, so identical inputs always produce identical suites.

    parse_scenario_spec

    fn parse_scenario_spec(source : String) -> Result[ScenarioSpec, CaseWeaveError]

    plan_repair

    fn plan_repair(model : Model, cases : Array[TestCase], constraints? : Array[Constraint], options? : RepairOptions) -> Result[RepairPlan, CaseWeaveError]

    version

    let version : String

    CaseWeave builds deterministic covering arrays for configuration-heavy software tests. The public API is split across the files in this package; this file intentionally keeps the package-level overview close to the generated interface.