APP-REST-RestTestSuite

 view release on metacpan or  search on metacpan

lib/APP/REST/RestTestSuite.pm  view on Meta::CPAN

  #specification; validate that before trying to execute them.
    my $err = $self->validate_test_cases(@_);

    die "ERROR: $err\n" if ($err);

    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 ) )
    {
        print $fh
          qq|<HTML> <HEAD> <TITLE>LOG for $self->{endpoint}</TITLE> </HEAD>|
          . qq|<BODY><textarea rows="999999" cols="120" style="border:none;">|;
        print $err_fh
qq|<HTML> <HEAD> <TITLE>ERROR LOG for $self->{endpoint}</TITLE> </HEAD>|
          . qq|<BODY><textarea rows="999999" cols="120" style="border:none;">|;
    }

    print STDERR "\nTest Suite executed on $self->{endpoint}\n";
    print $fh "\nTest Suite executed on $self->{endpoint}\n";
    print $err_fh "\nTest Suite executed on $self->{endpoint}\n";

    foreach my $count ( sort { $a <=> $b } keys(%test_cases) ) {

        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,

lib/APP/REST/RestTestSuite.pm  view on Meta::CPAN

    die "ERROR: $err\n" if ($err);

    my %test_cases = @_;

    # 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 ) )
    {
        print $fh
          qq|<HTML> <HEAD> <TITLE>LOG for $self->{endpoint}</TITLE> </HEAD>|
          . qq|<BODY><textarea rows="999999" cols="120" style="border:none;">|;
    }

    print STDERR "\nTest Suite executed on $self->{endpoint}\n";
    print $fh "\nTest Suite executed on $self->{endpoint}\n";

    my @reqs;

    foreach my $count ( sort { $a <=> $b } keys(%test_cases) ) {

        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";

lib/APP/REST/RestTestSuite.pm  view on Meta::CPAN


=cut

1;    # End of APP::REST::RestTestSuite

__DATA__

# RestTestSuite supports config file of below format.
# All values in LHS of ':' are case sensitive. 
# Every test case should be within the '#START_TEST_CASE' and '#END_TEST_CASE' block.
# Create application specific config file in below format and pass the 
# full path of file as an argument to the constructor
# for POST and PUT methods you need to supply the request body within
# [START] and [END] tags
#   request_body             :
#   [START] 
#   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
############################

####################
#END_OF_CONFIG_FILE
####################



( run in 0.912 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )