NAME

App::Test::Generator::SchemaExtractor - Extract test schemas from Perl modules

VERSION

Version 0.34

SYNOPSIS

use App::Test::Generator::SchemaExtractor;

my $extractor = App::Test::Generator::SchemaExtractor->new(
	input_file => 'lib/MyModule.pm',
	output_dir => 'schemas/',
	verbose	=> 1,
);

my $schemas = $extractor->extract_all();

DESCRIPTION

App::Test::Generator::SchemaExtractor analyzes Perl modules and generates structured YAML schema files suitable for automated test generation by App::Test::Generator. This module employs static analysis techniques to infer parameter types, constraints, and method behaviors directly from your source code.

Analysis Methods

The extractor combines multiple analysis approaches for a comprehensive schema generation:

  • POD Documentation Analysis

    Parses embedded documentation to extract: - Parameter names, types, and descriptions from =head2 sections - Method signatures with positional parameters - Return value specifications from "Returns:" sections - Constraints (ranges, patterns, required/optional status) - Semantic type detection (email, URL, filename)

  • Code Pattern Detection

    Analyzes source code using PPI to identify: - Method signatures and parameter extraction patterns - Type validation (ref(), isa(), blessed()) - Constraint patterns (length checks, numeric comparisons, regex matches) - Return statement analysis and value type inference - Object instantiation requirements and accessor methods

  • Signature Analysis

    Examines method declarations for: - Parameter names and positional information - Instance vs. class method detection - Method modifiers (Moose-style before/after/around) - Various parameter declaration styles (shift, @_ assignment)

  • Heuristic Inference

    Applies Perl-specific domain knowledge: - Boolean return detection from method names (is_*, has_*, can_*) - Common Perl idioms and coding patterns - Context awareness (scalar vs list, wantarray usage) - Object-oriented patterns (constructors, accessors, chaining)

Generated Schema Structure

The extracted schemas follow this YAML structure:

function: method_name
module: Package::Name
input:
  param1:
    type: string
    min: 3
    max: 50
    optional: 0
    position: 0
  param2:
    type: integer
    min: 0
    max: 100
    optional: 1
    position: 1
output:
  type: boolean
  value: 1
new: Package::Name # if object instantiation required
config:
  test_empty: 1
  test_nuls: 0
  test_undef: 0
  test_non_ascii: 0

Advanced Detection Capabilities

  • Accessor Method Detection

    Automatically identifies getter, setter, and combined accessor methods by analyzing common patterns like return $self->{property} and $self->{property} = $value.

  • Boolean Return Inference

    Detects boolean-returning methods through multiple signals: - Method name patterns (is_*, has_*, can_*) - Return patterns (consistent 1/0 returns) - POD descriptions ("returns true on success") - Ternary operators with boolean results

  • Context Awareness

    Identifies methods that use wantarray and can return different values in scalar vs list context.

  • Object Lifecycle Management

    Detects instance methods requiring object instantiation and automatically adds the new field to schemas.

  • Enhanced Object Detection

    The extractor includes sophisticated object detection capabilities that go beyond simple instance method identification:

    • Factory Method Recognition

      Automatically identifies methods that create and return object instances, such as methods named create_*, make_*, build_*, or get_*. Factory methods are correctly classified as class methods that don't require pre-existing objects for testing.

    • Singleton Pattern Detection

      Recognizes singleton patterns through multiple signals: method names like instance or get_instance, static variables holding instance references, lazy initialization patterns ($instance ||= new()), and consistent return of the same instance variable.

    • Constructor Parameter Analysis

      Examines new methods to determine required and optional parameters, validation requirements, and default values. This enables test generators to provide appropriate constructor arguments when object instantiation is needed.

    • Inheritance Relationship Handling

      Detects parent classes through use parent, use base, and @ISA declarations. Identifies when methods use SUPER:: calls and determines whether the current class or a parent class constructor should be used for object instantiation.

    • External Object Dependency Detection

      Identifies when methods create or depend on objects from other classes, enabling proper test setup with mock objects or real dependencies.

    These enhancements ensure that generated test schemas accurately reflect the object-oriented structure of the code, leading to more meaningful and effective test generation.

Confidence Scoring

Each generated schema includes detailed confidence assessments:

  • High Confidence

    Multiple independent analysis sources converge on consistent, well-constrained parameters with explicit validation logic and comprehensive documentation.

  • Medium Confidence

    Reasonable evidence from code patterns or partial documentation, but may lack comprehensive constraints or have some ambiguities.

  • Low Confidence

    Minimal evidence - primarily based on naming conventions, default assumptions, or single-source analysis.

  • Very Low Confidence

    Barely any detectable signals - schema should be thoroughly reviewed before use in test generation.

Use Cases

  • Automated Test Generation

    Generate comprehensive test suites with App::Test::Generator using extracted schemas as input. The schemas provide the necessary structure for generating both positive and negative test cases.

  • API Documentation Generation

    Supplement existing documentation with automatically inferred interface specifications, parameter requirements, and return types.

  • Code Quality Assessment

    Identify methods with poor documentation, inconsistent parameter handling, or unclear interfaces that may benefit from refactoring.

  • Refactoring Assistance

    Detect method dependencies, object instantiation requirements, and parameter usage patterns to inform refactoring decisions.

  • Legacy Code Analysis

    Quickly understand the interface contracts of legacy Perl codebases without extensive manual code reading.

Integration with Testing Ecosystem

The generated schemas are specifically designed to work with the App::Test::Generator ecosystem:

# Extract schemas from your module
my $extractor = App::Test::Generator::SchemaExtractor->new(...);
my $schemas = $extractor->extract_all();

# Use with test generator (typically as separate steps)
# fuzz-harness-generator -r schemas/method_name.yml

Limitations and Considerations

  • Dynamic Code Patterns

    Highly dynamic code (string evals, AUTOLOAD, symbolic references) may not be fully detected by static analysis.

  • Complex Validation Logic

    Sophisticated validation involving multiple parameters or external dependencies may require manual schema refinement.

  • Confidence Heuristics

    Confidence scores are based on heuristics and should be reviewed by developers familiar with the codebase.

  • Perl Idiom Recognition

    Some Perl-specific idioms may require custom pattern recognition beyond the built-in detectors.

  • Documentation Dependency

    Analysis quality improves significantly with comprehensive POD documentation following consistent patterns.

Best Practices for Optimal Results

  • Comprehensive POD Documentation

    Write detailed POD with explicit parameter documentation using consistent patterns like $param - type (constraints), description.

  • Consistent Coding Patterns

    Use consistent parameter validation patterns and method signatures throughout your codebase.

  • Schema Review Process

    Review and refine automatically generated schemas, particularly those with low confidence scores.

  • Descriptive Naming

    Use descriptive method and parameter names that clearly indicate purpose and expected types.

  • Progressive Enhancement

    Start with automatically generated schemas and progressively refine them based on test results and code understanding.

The module is particularly valuable for large codebases where manual schema creation would be prohibitively time-consuming, and for maintaining test coverage as code evolves through continuous integration pipelines.

Advanced Type Detection

The schema extractor includes enhanced type detection capabilities that identify specialized Perl types beyond basic strings and integers. DateTime and Time::Piece objects are detected through isa() checks and method call patterns, while date strings (ISO 8601, YYYY-MM-DD) and UNIX timestamps are recognized through regex validation and numeric range checks. File handles and file paths are identified via I/O operations and file test operators, coderefs are detected through ref() checks and invocation patterns, and enum-like parameters are extracted from validation code including regex patterns (/^(a|b|c)$/), hash lookups, grep statements, and if/elsif chains. These detected types are preserved in the generated YAML schemas with appropriate semantic annotations, enabling test generators to create more accurate and meaningful test cases.

Example Advanced Type Schema

For a method like:

sub process_event {
    my ($self, $timestamp, $status, $callback) = @_;
    croak unless $timestamp > 1000000000;
    croak unless $status =~ /^(active|pending|complete)$/;
    croak unless ref($callback) eq 'CODE';
    $callback->($timestamp, $status);
}

The extractor generates:

    ---
    function: process_event
    module: MyModule
    input:
      timestamp:
        type: integer
        # min: 0
        # max: 2147483647
        position: 0
        _note: Unix timestamp
	semantic: unix_timestamp
      status:
        type: string
        enum:
          - active
          - pending
          - complete
        position: 1
        _note: 'Must be one of: active, pending, complete'
      callback:
        type: coderef
        position: 2
        _note: 'CODE reference - provide sub { } in tests'

RELATIONSHIP DETECTION

The schema extractor detects relationships and dependencies between parameters, enabling more sophisticated validation and test generation.

Relationship Types

  • mutually_exclusive

    Parameters that cannot be used together.

    die if $file && $content;  # Can't specify both

    Generated schema:

    relationships:
      - type: mutually_exclusive
        params: [file, content]
        description: Cannot specify both file and content
  • required_group

    At least one parameter from the group must be specified (OR logic).

    die unless $id || $name;  # Must provide one

    Generated schema:

    relationships:
      - type: required_group
        params: [id, name]
        logic: or
        description: Must specify either id or name
  • conditional_requirement

    If one parameter is specified, another becomes required (IF-THEN logic).

    die if $async && !$callback;  # async requires callback

    Generated schema:

    relationships:
      - type: conditional_requirement
        if: async
        then_required: callback
        description: When async is specified, callback is required
  • dependency

    One parameter depends on another being present.

    die "Port requires host" if $port && !$host;

    Generated schema:

    relationships:
      - type: dependency
        param: port
        requires: host
        description: port requires host to be specified
  • value_constraint

    Specific value requirements between parameters.

    die if $ssl && $port != 443;  # ssl requires port 443

    Generated schema:

    relationships:
      - type: value_constraint
        if: ssl
        then: port
        operator: ==
        value: 443
        description: When ssl is specified, port must equal 443
  • value_conditional

    Parameter required when another has a specific value.

    die if $mode eq 'secure' && !$key;

    Generated schema:

    relationships:
      - type: value_conditional
        if: mode
        equals: secure
        then_required: key
        description: When mode equals 'secure', key is required

Default Value Extraction

The extractor comprehensively extracts default values from both code and POD documentation:

Code Pattern Recognition

Extracts defaults from multiple Perl idioms:

  • Logical OR operator: $param = $param || 'default'

  • Defined-or operator: $param //= 'default'

  • Ternary operator: $param = defined $param ? $param : 'default'

  • Unless conditional: $param = 'default' unless defined $param

  • Chained defaults: $param = $param || $self-{_default} || 'fallback'>

  • Multi-line patterns: $param = {} unless $param

POD Pattern Recognition

Extracts defaults from documentation:

  • Standard format: Default: 'value'

  • Alternative format: Defaults to: 'value'

  • Inline format: Optional, default: 'value'

  • Parameter lists: $param - type, default 'value'

Value Processing

Properly handles:

  • String literals with quotes and escape sequences

  • Numeric values (integers and floats)

  • Boolean values (true/false converted to 1/0)

  • Empty data structures ([] and {})

  • Special values (undef, __PACKAGE__)

  • Complex expressions (preserved as-is when unevaluatable)

  • Quote operators (q{}, qq{}, qw{})

Type Inference

When a parameter has a default value but no explicit type annotation, the type is automatically inferred from the default:

$options = {}        # inferred as hashref
$items = []          # inferred as arrayref
$count = 42          # inferred as integer
$ratio = 3.14        # inferred as number
$enabled = 1         # inferred as boolean

Context-Aware Return Analysis

The extractor provides comprehensive analysis of method return behavior, including context sensitivity, error handling conventions, and method chaining patterns.

List vs Scalar Context Detection

Automatically detects methods that return different values based on calling context:

sub get_items {
    my $self = $_[0];
    return wantarray ? @items : scalar(@items);
}

Detection captures:

  • _context_aware flag - Method uses wantarray

  • _list_context - Type returned in list context (e.g., 'array')

  • _scalar_context - Type returned in scalar context (e.g., 'integer')

Recognizes both ternary operator patterns and conditional return patterns.

Void Context Methods

Identifies methods that don't return meaningful values:

  • Setters (set_* methods)

  • Mutators (add_*, remove_*, delete_*, clear_*, reset_*, update_*)

  • Loggers (log, debug, warn, error, info)

  • Methods with only empty returns

Example:

sub set_name {
    my ($self, $name) = @_;
    $self->{name} = $name;
    return;  # Void context
}

Sets _void_context flag and type => 'void'.

Method Chaining Detection

Identifies chainable methods that return $self for fluent interfaces:

sub set_width {
    my ($self, $width) = @_;
    $self->{width} = $width;
    return $self;  # Chainable
}

Detection provides:

  • _returns_self - Returns invocant for chaining

  • class - The class name being returned

Also detects chaining documentation in POD (keywords: "chainable", "fluent interface", "returns self", "method chaining").

Error Return Conventions

Analyzes how methods signal errors:

Pattern Detection:

  • undef_on_error - Explicit return undef if/unless condition

  • implicit_undef - Bare return if/unless condition

  • empty_list - return () for list context errors

  • zero_on_error - Returns 0/false for boolean error indication

  • exception_handling - Uses eval blocks with error checking

Example Analysis:

sub fetch_user {
    my ($self, $id) = @_;

    return undef unless $id;        # undef_on_error
    return undef if $id < 0;        # undef_on_error

    return $self->{users}{$id};
}

Results in:

_error_return: 'undef'
_success_failure_pattern: 1
_error_handling: {
    undef_on_error: ['$id', '$id < 0']
}

Success/Failure Pattern:

Methods that return different types for success vs. failure are flagged with _success_failure_pattern. Common patterns:

  • Returns value on success, undef on failure

  • Returns true on success, false on failure

  • Returns data on success, empty list on failure

Success Indicator Detection

Methods that always return true (typically for side effects):

sub update_status {
    my ($self, $status) = @_;
    $self->{status} = $status;
    return 1;  # Success indicator
}

Sets _success_indicator flag when method consistently returns 1.

Schema Output

Enhanced return analysis adds these fields to method schemas:

output:
  type: boolean              # Inferred return type
  _context_aware: 1           # Uses wantarray
  _list_context:
    type: array
  _scalar_context:
    type: integer
  _returns_self: 1               # Returns $self
  _void_context: 1            # No meaningful return
  _success_indicator: 1       # Always returns true
  _error_return: undef        # How errors are signaled
  _success_failure_pattern: 1 # Mixed return types
  _error_handling:            # Detailed error patterns
    undef_on_error: [...]
    exception_handling: 1

This comprehensive analysis enables:

  • Better test generation (testing both contexts, error paths)

  • Documentation generation (clear error conventions)

  • API design validation (consistent error handling)

  • Contract specification (precise return behavior)

Example

For a method like:

sub connect {
    my ($self, $host, $port, $ssl, $file, $content) = @_;

    die if $file && $content;                    # mutually exclusive
    die unless $host || $file;                   # required group
    die "Port requires host" if $port && !$host; # dependency
    die if $ssl && $port != 443;                 # value constraint

    # ... connection logic
}

The extractor generates:

relationships:
  - type: mutually_exclusive
    params: [file, content]
    description: Cannot specify both file and content
  - type: required_group
    params: [host, file]
    logic: or
    description: Must specify either host or file
  - type: dependency
    param: port
    requires: host
    description: port requires host to be specified
  - type: value_constraint
    if: ssl
    then: port
    operator: ==
    value: 443
    description: When ssl is specified, port must equal 443

MODERN PERL FEATURES

This module adds support for:

Subroutine Signatures (Perl 5.20+)

sub connect($host, $port = 3306, %options) {
    ...
}

Extracts: required params, optional params with defaults, slurpy params

Type Constraints (Perl 5.36+)

sub calculate($x :Int, $y :Num) {
    ...
}

Recognizes: Int, Num, Str, Bool, ArrayRef, HashRef, custom classes

Subroutine Attributes

sub get_value :lvalue :Returns(Int) {
    ...
}

Detects: :lvalue, :method, :Returns(Type), custom attributes

Postfix Dereferencing (Perl 5.20+)

my @array = $arrayref->@*;
my %hash = $hashref->%*;
my @slice = $arrayref->@[1,3,5];

Tracks usage of modern dereferencing syntax

Field Declarations (Perl 5.38+)

field $host :param = 'localhost';
field $port :param(port_number) = 3306;
field $logger :param :isa(Log::Any);

Extracts fields and maps them to parameters

Modern Perl Features Support

The schema extractor supports modern Perl syntax introduced in versions 5.20, 5.36, and 5.38+.

Subroutine Signatures (Perl 5.20+)

Automatically extracts parameters from native Perl signatures:

use feature 'signatures';

sub connect($host, $port = 3306, $database = undef) {
    ...
}

Extracted schema includes:

  • Parameter positions

  • Optional vs required parameters

  • Default values from signature

  • Slurpy parameters (@array, %hash)

Example:

# Signature with defaults
sub process($file, %options) { ... }

# Extracts:
# $file: position 0, required
# %options: position 1, optional, slurpy hash

Type Constraints in Signatures (Perl 5.36+)

Recognizes type constraints in signature parameters:

sub calculate($x :Int, $y :Num, $name :Str = "result") {
    return $x + $y;
}

Supported constraint types:

  • :Int, :Integer -> integer

  • :Num, :Number -> number

  • :Str, :String -> string

  • :Bool, :Boolean -> boolean

  • :ArrayRef, :Array -> arrayref

  • :HashRef, :Hash -> hashref

  • :ClassName -> object with isa constraint

Type constraints are combined with defaults when both are present.

Subroutine Attributes

Extracts and documents subroutine attributes:

sub get_value :lvalue {
    my $self = shift;
    return $self->{value};
}

sub calculate :Returns(Int) :method {
    my ($self, $x, $y) = @_;
    return $x + $y;
}

Recognized attributes stored in _attributes field:

  • :lvalue - Method can be assigned to

  • :method - Explicitly marked as method

  • :Returns(Type) - Declares return type

  • Custom attributes with values: :MyAttr(value)

Postfix Dereferencing (Perl 5.20+)

Detects usage of postfix dereferencing syntax:

use feature 'postderef';

sub process_array {
    my ($self, $arrayref) = @_;
    my @array = $arrayref->@*;        # Array dereference
    my @slice = $arrayref->@[1,3,5];  # Array slice
    return @array;
}

sub process_hash {
    my ($self, $hashref) = @_;
    my %hash = $hashref->%*;          # Hash dereference
    return keys %hash;
}

Tracked features stored in _modern_features:

  • array_deref - Uses ->@*

  • hash_deref - Uses ->%*

  • scalar_deref - Uses ->$*

  • code_deref - Uses ->&*

  • array_slice - Uses ->@[...]

  • hash_slice - Uses ->%{...}

Field Declarations (Perl 5.38+)

Extracts field declarations from class syntax and maps them to method parameters:

use feature 'class';

class DatabaseConnection {
    field $host :param = 'localhost';
    field $port :param = 3306;
    field $username :param(user);
    field $password :param;
    field $logger :param :isa(Log::Any);

    method connect() {
        # Fields available as instance variables
    }
}

Field attributes:

  • :param - Field is a constructor parameter (uses field name)

  • :param(name) - Field maps to parameter with different name

  • :isa(Class) - Type constraint for the field

  • Default values in field declarations

Extracted schema includes both field information in _fields and merged parameter information in input, allowing proper validation of class constructors.

Mixed Modern and Traditional Syntax

The extractor handles code that mixes modern and traditional syntax:

sub modern($x, $y = 5) {
    # Modern signature with default
}

sub traditional {
    my ($self, $x, $y) = @_;
    $y //= 5;  # Traditional default in code
    # Both extract same parameter information
}

Priority order for parameter information:

1. Signature declarations (highest priority)
2. Field declarations (for class methods)
3. POD documentation
4. Code analysis (lowest priority)

This ensures that explicit declarations in signatures take precedence over inferred information from code analysis.

Backwards Compatibility

All modern Perl feature detection is optional and automatic:

  • Traditional sub declarations continue to work

  • Code without modern features extracts parameters as before

  • Modern features are additive - they enhance rather than replace existing extraction

  • Schemas include _source field indicating where parameter info came from

_yamltest_hints

Each method schema returned by "extract_all" now optionally includes a _yamltest_hints key, which provides guidance for automated test generation based on the code analysis.

This is intended to help App::Test::Generator create meaningful tests, including boundary and invalid input cases, without manually specifying them.

The structure is a hashref with the following keys:

  • boundary_values

    An arrayref of numeric values that represent boundaries detected from comparisons in the code. These are derived from literals in statements like $x < 0 or $y = 255>. The generator can use these to create boundary tests.

    Example:

    _yamltest_hints:
      boundary_values: [0, 1, 100, 255]
  • invalid_inputs

    An arrayref of values that are likely to be rejected by the method, based on checks like defined, empty strings, or numeric validations.

    Example:

    _yamltest_hints:
      invalid_inputs: [undef, '', -1]
  • equivalence_classes

    An arrayref intended to capture detected equivalence classes or patterns among inputs. Currently this is empty by default, but future enhancements may populate it based on detected input groupings.

    Example:

    _yamltest_hints:
      equivalence_classes: []

Usage

When calling extract_all, each method schema will include _yamltest_hints if any hints were detected:

my $schemas = $extractor->extract_all;
my $hints  = $schemas->{example_method}->{_yamltest_hints};

You can then feed these hints into automated test generators to produce negative tests, boundary tests, and parameter-specific test cases.

Notes

  • Hints are inferred heuristically from code and validation statements.

  • Not all inputs are guaranteed to be detected; the feature is additive and will never remove information from the schema.

  • Currently, equivalence classes are not populated, but the field exists for future extension.

  • Boundary and invalid input hints are deduplicated to avoid repeated test values.

Examples

Given a method like:

sub example {
    my ($x) = @_;
    die "negative" if $x < 0;
    return unless defined($x);
    return $x * 2;
}

After running:

my $extractor = App::Test::Generator::SchemaExtractor->new(
    input_file => 'TestHints.pm',
    output_dir => '/tmp',
    quiet    => 1,
);

my $schemas = $extractor->extract_all;

The schema for the method "example" will include:

$schemas->{example} = {
    function => 'example',
    _confidence => {
        input  => 'unknown',
        output => 'unknown',
    },
    input => {
        x => {
            type     => 'scalar',
            optional => 0,
        }
    },
    output => {
        type => 'scalar',
    },
    _yamltest_hints => {
        boundary_values => [0, 1],
        invalid_inputs  => [undef, -1],
        equivalence_classes => [],
    },
    _notes => '...',
    _analysis => {
        input_confidence  => 'low',
        output_confidence => 'unknown',
        confidence_factors => {
            input  => {...},
            output => {...},
        },
        overall_confidence => 'low',
    },
    _fields => {},
    _modern_features => {},
    _attributes => {},
};

METHODS

new

Construct a new SchemaExtractor for a given Perl source file.

my $extractor = App::Test::Generator::SchemaExtractor->new(
    input_file           => 'lib/MyModule.pm',  # Required
    output_dir           => 'schemas/',         # Optional - only needed if writing schemas
    verbose              => 1,                  # Default: 0
    include_private      => 1,                  # Default: 0
    max_parameters       => 50,                 # Default: 20
    confidence_threshold => 0.7,               # Default: 0.5
    strict_pod           => 0|1|2,              # Default: 0 (off)
);

Arguments

  • input_file

    Path to the Perl source file to analyse. Required. Must exist on disk.

  • output_dir

    Directory to write generated schema YAML files. Optional - only required if _write_schema will be called. Callers passing no_write => 1 to extract_all do not need to supply it.

  • verbose

    Print progress messages to stdout during analysis. Optional, default 0.

  • include_private

    Include methods whose names begin with _ in the analysis. Optional, default 0. Methods named _new, _init, and _build are always included regardless of this setting.

  • max_parameters

    Safety limit on the number of parameters analysed per method to prevent runaway processing on pathological code. Optional, default 20.

  • confidence_threshold

    Minimum confidence score (0.0-1.0) below which a schema is marked with _low_confidence => 1. Optional, default 0.5.

  • strict_pod

    Controls POD/code agreement validation. 0 disables validation, 1 emits warnings, 2 croaks on first disagreement. Also accepts the strings off, warn, and fatal. Optional, default 0.

Returns

A blessed hashref. Croaks if input_file is missing or does not exist on disk.

Side effects

Reads and parses the input file using PPI at construction time.

API specification

input

{
    input_file           => { type => SCALAR },
    output_dir           => { type => SCALAR,  optional => 1 },
    verbose              => { type => SCALAR,  optional => 1 },
    include_private      => { type => SCALAR,  optional => 1 },
    max_parameters       => { type => SCALAR,  optional => 1 },
    confidence_threshold => { type => SCALAR,  optional => 1 },
    strict_pod           => { type => SCALAR,  optional => 1 },
}

output

{
    type => OBJECT,
    isa  => 'App::Test::Generator::SchemaExtractor',
}

extract_all

Extract schemas for all qualifying methods in the module and return them as a hashref.

my $schemas = $extractor->extract_all();

# Suppress writing .yml files to disk
my $schemas = $extractor->extract_all(no_write => 1);

Arguments

  • no_write

    When true, schema files are not written to output_dir. The returned hashref is still fully populated. Useful when the caller wants to inspect or augment schemas before deciding whether to write them. Optional, default 0.

Returns

A hashref mapping method name strings to schema hashrefs. Each schema contains at minimum the keys function, module, input, output, and _analysis. See "Generated Schema Structure" for the full structure.

Side effects

Parses the input file with PPI. Writes one YAML file per method to output_dir unless no_write is set. Creates output_dir if it does not exist and writing is enabled.

Notes

Private methods (names beginning with _) are excluded unless include_private => 1 was passed to new. Duplicate method names are deduplicated with a warning logged to stdout in verbose mode.

POD/code agreement validation is applied if strict_pod was set in new. At level 2 (fatal), the first disagreement causes an immediate croak.

API specification

input

{
    self     => { type => OBJECT, isa => 'App::Test::Generator::SchemaExtractor' },
    no_write => { type => SCALAR, optional => 1 },
}

output

{
    type => HASHREF,
    keys => {
        '*' => {
            type => HASHREF,
            keys => {
                function  => { type => SCALAR  },
                module    => { type => SCALAR  },
                input     => { type => HASHREF },
                output    => { type => HASHREF },
                _analysis => { type => HASHREF },
            },
        },
    },
}

generate_pod_validation_report

Generate a human-readable report of all POD/code disagreements found across a set of extracted schemas.

my $schemas = $extractor->extract_all(no_write => 1);
my $report  = $extractor->generate_pod_validation_report($schemas);
print $report;

Arguments

  • $schemas

    A hashref of method name to schema hashref as returned by extract_all. Required.

Returns

A string containing the full validation report, or a single line confirming all methods passed if no disagreements were found.

Side effects

None.

Notes

Only methods whose schemas contain a _pod_validation_errors key (populated when strict_pod is 1 or 2) appear in the report. If strict_pod was 0 when extract_all was called, this method will always return the all-passed message.

API specification

input

{
    self    => { type => OBJECT,  isa => 'App::Test::Generator::SchemaExtractor' },
    schemas => { type => HASHREF },
}

output

{ type => SCALAR }

_log

Log a message if verbose mode is on.

NOTES

This is pre-pre-alpha proof of concept code. Nevertheless, it is useful for creating a template which you can modify to create a working schema to pass into App::Test::Generator.

SEE ALSO

  • App::Test::Generator - Generate fuzz and corpus-driven test harnesses

    Output from this module serves as input to that module. So with well-documented code, you can automatically create your tests.

  • App::Test::Generator::Template - Template of the file of tests created by App::Test::Generator

AUTHOR

Nigel Horne, <njh at nigelhorne.com>

Portions of this module's initial design and documentation were created with the assistance of AI.