App-Test-Generator

 view release on metacpan or  search on metacpan

lib/App/Test/Generator/SchemaExtractor.pm  view on Meta::CPAN

=item * B<Singleton Pattern Detection>

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

=item * B<Constructor Parameter Analysis>

Examines C<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.

=item * B<Inheritance Relationship Handling>

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

=item * B<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.

=back

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

=back

lib/App/Test/Generator/SchemaExtractor.pm  view on Meta::CPAN

# _check_inheritance_for_constructor
#
# Purpose:    Determine whether the current package
#             uses an inherited constructor from a
#             parent class, by examining use parent,
#             use base, and @ISA declarations.
#
# Entry:      $current_package - current package
#                                name string.
#             $method_body     - method source string
#                                (checked for SUPER::
#                                calls).
#
# Exit:       Returns an inheritance_info hashref
#             if any inheritance information is
#             found, or undef otherwise.
#             The hashref may contain:
#             parent_statements, isa_array,
#             uses_super, calls_super_new,
#             has_own_constructor,
#             use_parent_constructor, parent_class.

lib/App/Test/Generator/SchemaExtractor.pm  view on Meta::CPAN

	foreach my $stmt (@$statements) {
		my $content = $stmt->content;
		if ($content =~ /\@ISA\s*=\s*qw?[\(\[]?(.+?)[\)\]]?/) {
			my $parents = $1;
			my @isa_parents = split(/\s+/, $parents);
			push @parent_classes, @isa_parents;
			$inheritance_info{isa_array} = \@isa_parents;
		}
	}

	# 3. Check if method uses SUPER:: calls
	if ($method_body && $method_body =~ /SUPER::/) {
		$inheritance_info{uses_super} = 1;
		if ($method_body =~ /SUPER::new/) {
			$inheritance_info{calls_super_new} = 1;
		}
	}

	# 4. Check if current package has its own new method
	my $has_own_new = $doc->find(sub {
		$_[1]->isa('PPI::Statement::Sub') &&
		$_[1]->name eq 'new'
	});

t/function.t  view on Meta::CPAN

	ok(-e $file, 'the schema file is created at output_dir/<method_name>.yml');

	open my $fh, '<', $file or die "Cannot read $file: $!";
	my $contents = do { local $/; <$fh> };
	close $fh;

	like($contents, qr/function: greet/, 'the written YAML includes the function name');
	like($contents, qr/name:/, 'the written YAML includes the input parameter name');
};

subtest 'SchemaExtractor::_check_inheritance_for_constructor - detects use parent and SUPER:: usage' => sub {
	my $src = "package Child;\nuse parent 'Parent';\nsub greet { my \$self = shift; return \$self->SUPER::greet(); }\n1;\n";
	my $e = bless { _document => PPI::Document->new(\$src) }, 'App::Test::Generator::SchemaExtractor';

	my $info = $e->_check_inheritance_for_constructor('Child', 'sub greet { my $self = shift; return $self->SUPER::greet(); }');
	ok($info, 'returns inheritance info when a parent class is declared');
	is_deeply($info->{parent_statements}, ['Parent'], 'the declared parent class is captured');
	ok($info->{uses_super}, 'SUPER:: usage in the method body is detected');
	ok(!$info->{has_own_constructor}, 'Child has no own new() method');
	ok($info->{use_parent_constructor}, 'falls back to the parent constructor since Child has none of its own');
	is($info->{parent_class}, 'Parent', 'the first declared parent is selected as the constructor source');

	returns_ok($info, { type => 'hashref' }, '_check_inheritance_for_constructor() returns a hashref');
	memory_cycle_ok($info, '_check_inheritance_for_constructor() result is free of circular references');
};

subtest 'SchemaExtractor::_check_inheritance_for_constructor - returns undef when there is no _document' => sub {
	my $e = bless {}, 'App::Test::Generator::SchemaExtractor';

t/object_detection.t  view on Meta::CPAN


# Test 4: Inheritance detection
subtest 'Inheritance Detection' => sub {
	my $module = <<'END_MODULE';
package Test::Inheritance;
use parent 'Parent::Class';
use base 'Another::Parent';
@ISA = qw(Base::Class Another::Base);
sub method_using_super {
	my $self = shift;
	my $result = $self->SUPER::some_method();
	return $result;
}
sub new { bless {}, shift }
END_MODULE

	my $extractor = create_extractor($module);
	$extractor->{_document} = PPI::Document->new($extractor->{input_file});

	# Test inheritance detection
	my $method_body = 'my $self = shift; my $result = $self->SUPER::some_method(); return $result;';
	my $inheritance_info = $extractor->_check_inheritance_for_constructor('Test::Inheritance', $method_body);

	ok($inheritance_info, 'Inheritance info found');
	ok($inheritance_info->{parent_statements}, 'Found parent statements') if $inheritance_info;

	done_testing();
};

# Test 5: Constructor requirements detection
subtest 'Constructor Requirements Detection' => sub {



( run in 0.751 second using v1.01-cache-2.11-cpan-3c2a17b8caa )