view release on metacpan or search on metacpan
use 5.006;
use strict;
use warnings FATAL => 'all';
use Module::Build;
my $builder = Module::Build->new(
module_name => 'APP::REST::RestTestSuite',
license => 'artistic_2',
dist_author => q{Mithun Radhakrishnan <rkmithun@cpan.org>},
dist_version_from => 'lib/APP/REST/RestTestSuite.pm',
dist_abstract => 'rest-client => Test automation tool for restful web services',
release_status => 'stable',
script_files => [
'script/rest-client',
],
meta_merge => {
resources => {
repository => 'https://github.com/rkmithun/APP-REST-RestTestSuite'
}
},
configure_requires => {
'Module::Build' => 0,
},
build_requires => {
'Test::More' => 0,
},
requires => {
'LWP::Parallel::UserAgent' => 0,
'LWP::UserAgent' => 0,
'HTTP::Request' => 0,
'File::Path' => 0,
'File::Basename' => 0,
'Time::HiRes' => 0,
'Getopt::Long' => 0,
},
add_to_cleanup => [ 'APP-REST-RestTestSuite-*' ],
create_makefile_pl => 'traditional',
Revision history for APP-REST-RestTestSuite
0.02 24/02/2014
Integrated all scripts to single rest-client client
Implemented GetOptions in client for easy usage.
updated Build scripts to install the scripts to bin dir.
Made rest-client as a CLI rest client
0.01 20/02/2014
First version, released on an unsuspecting world.
RestTestSuite module with scripts.
Installation to scripts to custom directory.
Changes
ignore.txt
lib/APP/REST/ParallelMyUA.pm
lib/APP/REST/RestTestSuite.pm
Makefile.PL
MANIFEST This list of files
META.json
META.yml
README
README.md
script/rest-client
t/00-load.t
t/boilerplate.t
t/manifest.t
t/pod-coverage.t
t/pod.t
{
"abstract" : "rest-client => Test automation tool for restful web services",
"author" : [
"Mithun Radhakrishnan <rkmithun@cpan.org>"
],
"dynamic_config" : 1,
"generated_by" : "Module::Build version 0.4206",
"license" : [
"artistic_2"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : "2"
},
"name" : "APP-REST-RestTestSuite",
"prereqs" : {
"build" : {
"requires" : {
"Test::More" : "0"
}
},
"configure" : {
"requires" : {
"Module::Build" : "0"
}
},
"runtime" : {
"requires" : {
"File::Basename" : "0",
"File::Path" : "0",
"Getopt::Long" : "0",
"HTTP::Request" : "0",
"LWP::Parallel::UserAgent" : "0",
"LWP::UserAgent" : "0",
"Time::HiRes" : "0"
}
}
},
"APP::REST::ParallelMyUA" : {
"file" : "lib/APP/REST/ParallelMyUA.pm",
"version" : "0.03"
},
"APP::REST::RestTestSuite" : {
"file" : "lib/APP/REST/RestTestSuite.pm",
"version" : "0.03"
}
},
"release_status" : "stable",
"resources" : {
"license" : [
"http://opensource.org/licenses/artistic-license-2.0.php"
],
"repository" : {
"url" : "https://github.com/rkmithun/APP-REST-RestTestSuite"
}
},
"version" : "0.03"
}
---
abstract: 'rest-client => Test automation tool for restful web services'
author:
- 'Mithun Radhakrishnan <rkmithun@cpan.org>'
build_requires:
Test::More: 0
configure_requires:
Module::Build: 0
dynamic_config: 1
generated_by: 'Module::Build version 0.4206, CPAN::Meta::Converter version 2.120921'
license: artistic_2
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: 1.4
name: APP-REST-RestTestSuite
provides:
APP::REST::ParallelMyUA:
file: lib/APP/REST/ParallelMyUA.pm
version: 0.03
APP::REST::RestTestSuite:
file: lib/APP/REST/RestTestSuite.pm
version: 0.03
requires:
File::Basename: 0
File::Path: 0
Getopt::Long: 0
HTTP::Request: 0
LWP::Parallel::UserAgent: 0
LWP::UserAgent: 0
Time::HiRes: 0
resources:
license: http://opensource.org/licenses/artistic-license-2.0.php
repository: https://github.com/rkmithun/APP-REST-RestTestSuite
version: 0.03
Makefile.PL view on Meta::CPAN
# Note: this file was auto-generated by Module::Build::Compat version 0.4206
use ExtUtils::MakeMaker;
WriteMakefile
(
'EXE_FILES' => [
'script/rest-client'
],
'NAME' => 'APP::REST::RestTestSuite',
'PL_FILES' => {},
'PREREQ_PM' => {
'HTTP::Request' => 0,
'File::Path' => 0,
'Time::HiRes' => 0,
'Test::More' => 0,
'Getopt::Long' => 0,
'LWP::Parallel::UserAgent' => 0,
perl Build.PL
./Build
./Build test
./Build install
===================================================
[*] if you see any prerequisites message like below while executing
perl Build.PL command:
checking prerequisites...
requires:
! LWP::Parallel::UserAgent is not installed
- run below command to install any dependent modules.
you need a internet connection for this.
perl Build installdeps
[*] if you get "Net::SSLeay" installation error while installing
'LWP::Parallel::Useragent'
If your Modified Version has been derived from a Modified Version made
by someone other than you, you are nevertheless required to ensure that
your Modified Version complies with the requirements of this license.
This license does not grant you the right to use any trademark, service
mark, tradename, or logo of the Copyright Holder.
This license includes the non-exclusive, worldwide, free-of-charge
patent license to make, have made, use, offer to sell, sell, import and
otherwise transfer the Package with respect to any patent claims
licensable by the Copyright Holder that are necessarily infringed by the
Package. If you institute patent litigation (including a cross-claim or
counterclaim) against any party alleging that the Package constitutes
direct or contributory patent infringement, then this Artistic License
to you shall terminate on the date that such litigation is filed.
Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
APP-REST-RestTestSuite
======================
This is my pet project on creating test automation tool for restfull services
lib/APP/REST/ParallelMyUA.pm view on Meta::CPAN
}
=head2 on_connect
redefine methods: on_connect gets called whenever we're about to
make a a connection
=cut
sub on_connect {
my ( $self, $request, $response, $entry ) = @_;
#print time,"Connecting to ", $request->url, "\n";
print STDERR ".";
$entry->{tick}->{start} = time;
}
=head2 on_failure
on_failure gets called whenever a connection fails right away
(either we timed out, or failed to connect to this address before,
or it's a duplicate). Please note that non-connection based
errors, for example requests for non-existant pages, will NOT call
on_failure since the response from the server will be a well
formed HTTP response!
=cut
sub on_failure {
my ( $self, $request, $response, $entry ) = @_;
print "Failed to connect to ", $request->url, "\n\t", $response->code, ", ",
$response->message, "\n"
if $response;
}
=head2 on_return
on_return gets called whenever a connection (or its callback)
returns EOF (or any other terminating status code available for
callback functions). Please note that on_return gets called for
any successfully terminated HTTP connection! This does not imply
that the response sent from the server is a success!
=cut
sub on_return {
my ( $self, $request, $response, $entry ) = @_;
print ".";
#print time,"Response got from ", $request->url, "\n";
$entry->{tick}->{end} = time;
if ( $response->is_success ) {
#print "\n\nWoa! Request to ",$request->url," returned code ", $response->code,
# ": ", $response->message, "\n";
#print $response->content;
} else {
#print "\n\nBummer! Request to ",$request->url," returned code ", $response->code,
# ": ", $response->message, "\n";
#print $response->error_as_HTML;
}
return;
}
1;
=head1 AUTHOR
Mithun Radhakrishnan, C<< <rkmithun at cpan.org> >>
lib/APP/REST/ParallelMyUA.pm view on Meta::CPAN
If your Modified Version has been derived from a Modified Version made
by someone other than you, you are nevertheless required to ensure that
your Modified Version complies with the requirements of this license.
This license does not grant you the right to use any trademark, service
mark, tradename, or logo of the Copyright Holder.
This license includes the non-exclusive, worldwide, free-of-charge
patent license to make, have made, use, offer to sell, sell, import and
otherwise transfer the Package with respect to any patent claims
licensable by the Copyright Holder that are necessarily infringed by the
Package. If you institute patent litigation (including a cross-claim or
counterclaim) against any party alleging that the Package constitutes
direct or contributory patent infringement, then this Artistic License
to you shall terminate on the date that such litigation is filed.
Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
use warnings FATAL => 'all';
use Data::Dumper;
use HTTP::Request;
use Time::HiRes qw( time sleep );
use File::Path;
use Cwd;
use LWP::UserAgent;
use APP::REST::ParallelMyUA;
use constant LOG_FILE => 'rest_client.log';
use constant ERR_LOG_FILE => 'rest_client_error.log';
use constant LINE => '=' x 50;
$| = 1; #make the pipe hot
$Data::Dumper::Indent = 1;
=head1 NAME
APP::REST::RestTestSuite - Suite for testing restful web services
=head1 VERSION
Version 0.03
=cut
our $VERSION = '0.03';
=head1 SYNOPSIS
use APP::REST::RestTestSuite;
my $suite = APP::REST::RestTestSuite->new();
$suite->execute_test_cases( $suite->get_test_cases() );
my ( $cases_in_config, $executed, $skipped, $passed, $failed ) =
$suite->get_result_summary();
#OR
use APP::REST::RestTestSuite;
# overrides the default config and log file paths
my $suite = APP::REST::RestTestSuite->new(
REST_CONFIG_FILE => <config file>,
LOG_FILE_PATH => <path>,
);
$suite->execute_test_cases( $suite->get_test_cases() );
my ( $cases_in_config, $executed, $skipped, $passed, $failed ) =
$suite->get_result_summary();
=head1 DESCRIPTION
APP::REST::RestTestSuite object is instantiated with the data in config file.
Default config file format is defined in __DATA__ and that can be overridden
by passing the config file as an argument to the class.
Default LOG file path is the current working directory of the script which
calls this module
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
=cut
sub get_sample_config_file {
my ( $self, %args ) = @_;
return $self->{file}->{sample_config_file};
}
=head2 get_result_summary
=cut
sub get_result_summary {
my ( $self, %args ) = @_;
return (
$self->{test_result_log}->{test_cases_in_config},
$self->{test_result_log}->{test_cases_exececuted},
$self->{test_result_log}->{test_cases_skipped},
$self->{test_result_log}->{test_cases_passed},
$self->{test_result_log}->{test_cases_failed},
);
}
=head2 validate_test_cases
=cut
sub validate_test_cases {
my ($self) = shift;
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
return $err if ($err);
my %test_cases = @_;
my @spec = sort qw(
test_case
uri
request_content_type
request_method
request_body
response_status
execute
response_content_type
);
#below two are not mandatory for a test case as of now; if required add them to above array
# response_header
# response_body
foreach my $count ( sort { $a <=> $b } keys(%test_cases) ) {
my $tc = $test_cases{$count};
my @keys = sort keys %{$tc};
no warnings;
$err .= "Test case '$tc->{test_case}' not properly defined\n"
unless ( _compare_arrays( \@spec, \@keys ) );
}
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
my %test_cases = @_;
my $ua = LWP::UserAgent->new;
$ua->agent("RTAT/$VERSION");
$ua->timeout(90); # in seconds
$ua->default_header('Accept' => '*/*'); # to get cross platform support
my ( $config, $total, $total_response_time, $skip, $pass, $fail ) = (0) x 6;
my ( $uri, $method, $req_content_type, $req_body, $status ) = (undef) x 5;
my ( $request, $response ) = (undef) x 2;
my ( $username, $password ) = (undef) x 2;
$username = $self->{username};
$password = $self->{password};
my $fh = $self->get_log_file_handle();
my $err_fh = $self->get_err_log_file_handle();
if ( $self->{html_log_required}
&& ( $self->{html_log_required} =~ /yes/i ) )
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
my $tc = $test_cases{$count};
$config++;
print $fh "\n", LINE, "\n";
if ( $tc->{execute} && ( $tc->{execute} =~ /no/i ) ) {
print $fh "\nSkipping Test case $count => $tc->{test_case} \n";
$skip++;
next;
}
$uri = qq|$self->{rest_uri_base}| . qq|$tc->{uri}|;
$method = uc( $tc->{request_method} );
$req_content_type = $tc->{request_content_type};
$req_body = $tc->{request_body} || 0;
$status = $tc->{response_status};
if ( $tc->{request_method} =~ /get/i ) {
$request = HTTP::Request->new( $method, $uri );
$request->authorization_basic( $username, $password )
if ( $username && $password );
} else {
$request =
HTTP::Request->new( $method, $uri, new HTTP::Headers, $req_body );
$request->authorization_basic( $username, $password )
if ( $username && $password );
$request->content_type($req_content_type);
$request->content_length( length($req_body) );
}
print STDERR "Executing Test case $count => $tc->{test_case}";
print $fh "Executing Test case $count => $tc->{test_case}";
my $start_time = time;
$response = $ua->request($request);
$total++;
my $exec_time = $self->delta_time( start_time => $start_time );
$total_response_time += $exec_time;
$exec_time = sprintf( "%.2f", $exec_time );
print STDERR " [Completed in $exec_time ms]\n";
print $fh " [Completed in $exec_time ms]\n";
$self->_print_logs(
fh => $fh,
uri => $uri,
method => $method,
req_body => $req_body,
);
$self->_print_logs(
fh => $fh,
res => $response,
exec_time => $exec_time,
);
#Level-1 check => check for response status code
#Level-2 check => check for expected response content_type
my $resp_code = $response->code;
if ( $status =~ m/$resp_code/ ) {
my $failed = 0;
if ( defined $tc->{response_content_type} ) {
my $expected_response_content_type =
$tc->{response_content_type};
#my $respose_content_type = $response->{_headers}->content_type;
my $respose_content_type = $response->header('Content-Type');
unless ( defined $respose_content_type ) {
$failed = 1;
} elsif ( $expected_response_content_type !~
m/$respose_content_type/ )
{
$failed = 1;
print $err_fh "\n", LINE, "\n";
print $err_fh
"Executing Test case $count => $tc->{test_case}";
print $err_fh
"\n*********ATTENTION CONTENT TYPE ERROR ******";
print $err_fh
"\n\nExpected content_type is $expected_response_content_type\n";
print $err_fh
"content_type recieved in response is $respose_content_type\n";
print $err_fh
"\n*********ATTENTION CONTENT TYPE ERROR ******";
$self->_print_logs(
fh => $err_fh,
uri => $uri,
method => $method,
req_body => $req_body,
);
$self->_print_logs(
fh => $err_fh,
res => $response,
exec_time => $exec_time,
);
}
}
($failed) ? $fail++ : $pass++;
} else {
$fail++;
print $err_fh "\n", LINE, "\n";
print $err_fh "Executing Test case $count => $tc->{test_case}";
$self->_print_logs(
fh => $err_fh,
uri => $uri,
method => $method,
req_body => $req_body,
);
$self->_print_logs(
fh => $err_fh,
res => $response,
exec_time => $exec_time,
);
}
}
#convert milli seconds to seconds for total_exec_time
$total_response_time = sprintf( "%.2f", $total_response_time / 1000 );
my $avg_response_time =
sprintf( "%.2f", ( $total_response_time * 1000 ) / $total );
print STDERR "\nComplete test case report is in $self->{file}->{log_file}";
print STDERR
"\nFailed test case report is in $self->{file}->{err_log_file}\n\n";
print STDERR
"Response time of $total web service calls => [$total_response_time seconds]\n";
print STDERR
"Average response time of a web service => [$avg_response_time milli seconds]\n\n";
print $fh
"Response time of $total web service calls => [$total_response_time seconds]\n";
print $fh
"Average response time of a web service => [$avg_response_time milli seconds]\n\n";
if ( $self->{html_log_required}
&& ( $self->{html_log_required} =~ /yes/i ) )
{
print $fh qq|</textarea></BODY></HTML>|;
print $err_fh qq|</textarea></BODY></HTML>|;
}
$self->{test_result_log} = {
test_cases_in_config => $config,
test_cases_exececuted => $total,
test_cases_skipped => $skip,
test_cases_passed => $pass,
test_cases_failed => $fail,
};
close($fh);
close($err_fh);
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
# use my customized user agent for parallel invokes
my $pua = APP::REST::ParallelMyUA->new();
$pua->agent("RTAT/$VERSION");
$pua->in_order(1); # handle requests in order of registration
$pua->duplicates(0); # ignore duplicates
$pua->timeout(60); # in seconds
$pua->redirect(1); # follow redirects
$pua->default_header('Accept' => '*/*'); # to get cross platform support
my ( $config, $total, $total_response_time, $skip, $pass, $fail ) = (0) x 6;
my ( $uri, $method, $req_content_type, $req_body, $status ) = (undef) x 5;
my ( $request, $response ) = (undef) x 2;
my ( $username, $password ) = (undef) x 2;
$username = $self->{username};
$password = $self->{password};
my $fh = $self->get_log_file_handle();
if ( $self->{html_log_required}
&& ( $self->{html_log_required} =~ /yes/i ) )
{
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
my $tc = $test_cases{$count};
$config++;
if ( $tc->{execute} =~ /no/i ) {
print $fh "\nSkipping Test case $count => $tc->{test_case} \n";
$skip++;
next;
}
$uri = qq|$self->{rest_uri_base}| . qq|$tc->{uri}|;
#Support only GET methods at present
if ( $tc->{request_method} =~ /get/i ) {
# Create HTTP request pool for later execution by parallel useragent
$method = uc( $tc->{request_method} );
$req_content_type = $tc->{request_content_type};
$req_body = $tc->{request_body} || 0;
$status = $tc->{response_status};
my $request = HTTP::Request->new( $method, $uri );
$request->authorization_basic( $username, $password )
if ( $username && $password );
push( @reqs, $request );
}
$total++;
}
print STDERR "\nRequesting [$total] web services together.\n";
foreach my $req (@reqs) {
# register all requests and wait for them to finish
if ( my $res = $pua->register($req) ) {
print STDERR $res->error_as_HTML;
}
}
print STDERR "Receiving response from web services. Please wait..!\n";
# will return once all forked web services are either completed or timeout
my $entries = $pua->wait();
print STDERR "\n\n";
foreach ( keys %$entries ) {
my $response = $entries->{$_}->response;
my $tick = $entries->{$_}->{tick};
my $exec_time = ( $tick->{end} - $tick->{start} ) * 1000 ;
$total_response_time += $exec_time;
$exec_time = sprintf( "%.2f", $exec_time );
print STDERR "\n", $response->request->url,
"\n ! Response Status [", $response->code,
"]\tResponse Time [$exec_time ms]";
$self->_print_logs(
fh => $fh,
uri => $response->request->url,
method => $response->request->method,
req_body => ''
);
$self->_print_logs(
fh => $fh,
res => $response,
exec_time => $exec_time,
);
}
#convert milli seconds to seconds for total_exec_time
$total_response_time = sprintf( "%.2f", $total_response_time / 1000 );
my $avg_response_time =
sprintf( "%.2f", ( $total_response_time * 1000 ) / $total );
print STDERR
"\n\n\nComplete test case report is in $self->{file}->{log_file}";
print STDERR
"\n\nResponse time of $total web service calls => [$total_response_time seconds]\n";
print STDERR
"Average response time of a web service => [$avg_response_time milli seconds]\n\n";
print $fh
"\n\nResponse time of $total web service calls => [$total_response_time seconds]\n";
print $fh
"Average response time of a web service => [$avg_response_time milli seconds]\n\n";
if ( $self->{html_log_required}
&& ( $self->{html_log_required} =~ /yes/i ) )
{
print $fh qq|</textarea></BODY></HTML>|;
}
$self->{test_result_log} = {
test_cases_in_config => $config,
test_cases_exececuted => $total,
test_cases_skipped => $skip,
test_cases_passed => $pass,
test_cases_failed => $fail,
};
close($fh);
}
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
# Read the config file based on the type of the input file (xml or text)
if ( $args{CONFIG_FILE_TYPE} && ( $args{CONFIG_FILE_TYPE} =~ /xml/i ) ) {
#Implement the xml reading
} else {
$self->_init_read_config(%args);
}
$self->_init_log_file_handle(%args);
$self->_init_rest_base_uri(%args);
}
sub _init_config_file_handle {
my ( $self, %args ) = @_;
$self->_init_config_files(%args);
my $file = $self->{file};
if ( $file->{config_file} ) {
$file->{config_file_handle} =
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
}
if ( $start_case && $end_case ) {
$test_no++;
foreach my $line (@buffer) {
my @val = split( $separator, $line );
$self->{test_cases}->{$test_no}->{ _trim( $val[0] ) } =
_trim( $val[1] );
}
# add all those in between [START] and [END] tage to the respective key
while ( my ( $key, $value ) = each %start_end_hash ) {
$self->{test_cases}->{$test_no}->{$key} = $value;
}
%start_end_hash = ();
@buffer = ();
$start_case = 0;
$end_case = 0;
} elsif ( !$start_case && $end_case ) {
die "ERROR in config file format\n";
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
$start_http_code = 0;
$end_http_code = 0;
} elsif ( !$start_http_code && $end_http_code ) {
die "ERROR in config file format\n";
}
}
close($fh);
}
sub _init_rest_base_uri {
my ( $self, %args ) = @_;
if ( $self->{username} ) {
print STDERR "username configured: $self->{username}\n";
print STDERR "Password: ";
chomp( $self->{password} = <STDIN> );
}
if ( $self->{endpoint} && $self->{port} && $self->{base_uri} ) {
$self->{rest_uri_base} =
qq|http://$self->{endpoint}|
. qq|:$self->{port}|
. qq|$self->{base_uri}|;
return; #use the port and uri in config file and return from sub
} elsif ( $self->{endpoint} && $self->{base_uri} ) {
$self->{rest_uri_base} =
qq|http://$self->{endpoint}| . qq|$self->{base_uri}|;
return; #use the uri in config file and return from sub
} elsif ( $self->{endpoint} && $self->{port} ) {
$self->{rest_uri_base} =
qq|http://$self->{endpoint}| . qq|:$self->{port}|;
return;
} elsif ( $self->{endpoint} ) {
$self->{rest_uri_base} = qq|http://$self->{endpoint}|;
return; #use the endpoint in config file and return from sub
} else {
die qq|Endpoint should be configured in the config file\n|;
}
}
sub _init_config_files {
my ( $self, %args ) = @_;
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
my ( $self, %args ) = @_;
my $separator;
if ( $^O =~ /Win/ ) {
$separator = '\\';
} else {
$separator = '/';
}
my $scfg = getcwd() || $ENV{PWD};
my $scfg_file = $scfg . $separator . 'rest-project-xxxx.txt';
$self->{file}->{sample_config_file} = $scfg_file;
}
sub _init_log_files {
my ( $self, %args ) = @_;
my $separator;
if ( $^O =~ /Win/ ) {
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
return $str;
}
sub _print_logs {
my ( $self, %args ) = @_;
no warnings;
my $fh = $args{fh};
my $res = $args{res};
my $uri = $args{uri};
my $method = $args{method};
my $req_body = $args{req_body};
my $define =
"Definition of status code not available; Please define in config if this is a custom code";
unless ( $args{res} ) {
print $fh "\n";
print $fh "URI => $uri\n";
print $fh "HTTP Method => $method\n";
print $fh "Request Body => \n$req_body\n" if ( $method !~ /get/i );
} else {
print $fh "\n";
print $fh "Response code => ";
print $fh $res->code;
print $fh " [ ";
print $fh ( exists $self->{http_status_code}->{ $res->code } )
? $self->{http_status_code}->{ $res->code }
: $define;
print $fh " ]\n";
print $fh "\n\nResponse Content =>\n";
print $fh $res->content;
print $fh "\n\nTest execution time => ";
print $fh $args{exec_time};
print $fh " milli seconds";
print $fh "\n", LINE, "\n";
}
}
sub _compare_arrays {
my ( $first, $second ) = @_;
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
If your Modified Version has been derived from a Modified Version made
by someone other than you, you are nevertheless required to ensure that
your Modified Version complies with the requirements of this license.
This license does not grant you the right to use any trademark, service
mark, tradename, or logo of the Copyright Holder.
This license includes the non-exclusive, worldwide, free-of-charge
patent license to make, have made, use, offer to sell, sell, import and
otherwise transfer the Package with respect to any patent claims
licensable by the Copyright Holder that are necessarily infringed by the
Package. If you institute patent litigation (including a cross-claim or
counterclaim) against any party alleging that the Package constitutes
direct or contributory patent infringement, then this Artistic License
to you shall terminate on the date that such litigation is filed.
Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
lib/APP/REST/RestTestSuite.pm view on Meta::CPAN
# xml or json or form based
# [END]
################
#Set below values to configure the base URL for all test cases
####################
#START_COMMON_CONFIG
################################################################################
endpoint : www.thomas-bayer.com
port :
base_uri : /sqlrest
html_log_required : no
username :
################################################################################
#END_COMMON_CONFIG
##################
#####################
#START_TEST_CASE
#####################
test_case : get_product
uri : /PRODUCT/49
request_content_type : application/xml
request_method : GET
request_body :
response_status : 200
execute : yes
response_content_type : application/xml
#####################
#END_TEST_CASE
#####################
###########################
#START_HTTP_CODE_DEF
############################
200 : operation successful.
201 : Successful creation of a resource.
202 : The request was received.
204 : The request was processed successfully, but no response body is needed.
301 : Resource has moved.
303 : Redirection.
304 : Resource has not been modified.
400 : Malformed syntax or a bad query.
401 : Action requires user authentication.
403 : Authentication failure or invalid Application ID.
404 : Resource not found.
405 : Method not allowed on resource.
406 : Requested representation not available for the resource.
408 : Request has timed out.
409 : State of the resource doesn't permit request.
410 : The URI used to refer to a resource.
411 : The server needs to know the size of the entity body and it should be specified in the Content Length header.
412 : Operation not completed because preconditions were not met.
413 : The representation was too large for the server to handle.
414 : The URI has more than 2k characters.
415 : Representation not supported for the resource.
416 : Requested range not satisfiable.
500 : Internal server error.
501 : Requested HTTP operation not supported.
502 : Backend service failure (data store failure).
505 : HTTP version not supported.
############################
#END_HTTP_CODE_DEF
############################
####################
script/rest-client view on Meta::CPAN
sub usage {
print STDERR <<HELP;
Usage: $client [options] command [...]
Options:
-h,--help Display this usage.
-V,--version Print the version of the tool.
-c,--configfile=<file> Input the config file with full path.
-l,--logdir=<dir> Input full path of the directory where you want to log the test results.
-t,--test-load=n Test the average response time by simulating 'n' number of requests on the web server.
Commands:
-r,--run-test-suite Test the configured web services defined in the config file.
-g,--get-sample-config Get a sample config file to configure your web services as test suite.
***Note:
By default tool uses the sample-config file. You need to get that and configure the suite.
Examples:
$client --get-sample-config
# Get sample config file for configuring web services in the current directory.
$client --run-test-suite --configfile=<rest_config_file>
# Execute the test suite against the supplied config file.
# Supply the full path of config file if it is not present in current directory.
$client --test-load=10 --configfile=<rest_config_file>
# Send parallel requests (10* number of web services configured in config file).
# Give average response time by simulating huge traffic in the web server.
$client --run-test-suite --configfile=<rest_config_file> --logdir=<log-directory-path>
$client --test-load=10 --configfile=<rest_config_file> --logdir=<log-directory-path>
# Create LOG files in the path specified by executing the test cases.
HELP
exit;
}
print
"\n===============================Rest Test Automation Tool=============================\n";
if ( $^O =~ /Win/ ) {
script/rest-client view on Meta::CPAN
$suite = new APP::REST::RestTestSuite( REST_CONFIG_FILE => $config_file, );
} elsif ($log_dir) {
print <<HELP;
Using log dir as : $log_dir
Using the default test suite. This is just for a demo purpose.
Use below options to specify the config file and log path.
$client --configfile=<rest_config_file> --logdir=<log-directory-path>
HELP
$suite = new APP::REST::RestTestSuite( LOG_FILE_PATH => $log_dir, );
} else {
unless ( $action->{getsampleconfig} ) {
print <<HELP;
Using the default test suite. This is just for a demo purpose.
Use below options to specify the config file and log path.
$client --configfile=<rest_config_file> --logdir=<log-directory-path>
Use below option to get a sample config. Edit the config file to configure your web services
$client --get-sample-config
HELP
}
$suite = new APP::REST::RestTestSuite();
}
if ( $action->{debug} ) {
print Dumper $suite;
exit;
} elsif ( $action->{runtestsuite} ) {
$suite->execute_test_cases( $suite->get_test_cases() );
my ( $config, $total, $skip, $pass, $fail ) = $suite->get_result_summary();
print "=" x 70, "\n";
print "Summary of web service Suite \n";
print "=" x 70, "\n";
print "Total test cases configured : $config\n";
print "Total test cases executed : $total\n";
print "Total test cases skipped : $skip\n";
print "Total test cases pass : $pass\n";
print "Total test cases failed : $fail\n";
print "=" x 70, "\n";
exit;
script/rest-client view on Meta::CPAN
# $Data::Dumper::Indent = 1;
# print Dumper $suite;
# foreach my $num (sort { $a <=> $b } keys(%load_test_cases)) {
# print Dumper $load_test_cases{$num};
# }
# print sort{ $a <=> $b } keys %load_test_cases;
# exit;
$suite->execute_test_cases_in_parallel(%load_test_cases);
my ( $config, $total, $skip, $pass, $fail ) = $suite->get_result_summary();
print "=" x 70, "\n";
print "Summary of web service load test \n";
print "=" x 70, "\n";
print "Total test cases in config: $config\n";
print "Total test cases executed : $total\n";
print "Total test cases skipped : $skip\n";
print "=" x 70, "\n";
exit;
script/rest-client view on Meta::CPAN
$suite->get_sample_test_suite();
print "Sample Config file to configure the web services got created\n";
print "in ", $suite->get_sample_config_file(), "\n";
print "Edit and rename this file as project specific test suite.\n\n";
exit;
} else {
print "\nUse below options to execute the test cases\n\n";
print "$client --configfile=<rest_config_file> --run-test-suite\n\n";
exit;
}
__END__
=head1 NAME
rest-client - Test automation tool for restful web services
=head1 SYNOPSIS
Usage: rest-client [options] command [...]
Options:
-h,--help Display this usage.
-V,--version Print the version of the tool.
-c,--configfile=<file> Input the config file with full path.
-l,--logdir=<dir> Input full path of the directory where you want to log the test results.
-t,--test-load=n Test the average response time by simulating 'n' number of requests on the web server.
Commands:
-r,--run-test-suite Test the configured web services defined in the config file.
-g,--get-sample-config Get a sample config file to configure your web services as test suite.
***Note:
By default tool uses the sample-config file. You need to get that and configure the suite.
Examples:
rest-client --get-sample-config
# Get sample config file for configuring web services in the current directory.
rest-client --run-test-suite --configfile=<rest_config_file>
# Execute the test suite against the supplied config file.
# Supply the full path of config file if it is not present in current directory.
rest-client --test-load=10 --configfile=<rest_config_file>
# Send parallel requests (10* number of web services configured in config file).
# Give average response time by simulating huge traffic in the web server.
rest-client --run-test-suite --configfile=<rest_config_file> --logdir=<log-directory-path>
rest-client --test-load=10 --configfile=<rest_config_file> --logdir=<log-directory-path>
# Create LOG files in the path specified by executing the test cases.
=head1 SEE ALSO
L<https://github.com/rkmithun/APP-REST-RestTestSuite>
=cut