Как мне написать модульный тест Perl для метода с аргументом хеша? - PullRequest
0 голосов
/ 10 мая 2018

Эта подпрограмма извлекает имя хоста API из среды, применяя к нему регулярное выражение.

Parameters : 
environment (mandatory) - http://m5devacoe01.gcsc.att.com:8174/
Returns :
host : m5devacoe01.gcsc.att.com:28174
########################################################
# Subroutine: _get_api_host_from_environment
#
# Fetches the api host name from environment by applying regex on it
#
# Parameters : 
# environment (mandatory) - http://m5devacoe01.gcsc.att.com:8174/
#                    
# Returns :
# host : m5devacoe01.gcsc.att.com:28174
#####################################################


 sub _get_api_host_from_environment {
        my ($self, %args) = @_;

        $self->missing_params(\%args, qw! environment!)
            and return;

        $args{environment} =~ /([^:\/]+):?([^\/]*)/; #  http://m5devacoe01.gcsc.att.com:8174/
        my $host = $1; # m5devacoe01.gcsc.att.com
        my $port = $2; # 8174

        # If port is provided it means that it's a development server request. So, append 2 in the port
        if ($port) {
            $host .= ':2' . $port;
        } else {
            $host .= ':4040';
        }

        return $host;
    }

Как мне выполнить модульное тестирование этого метода?

1 Ответ

0 голосов
/ 10 мая 2018

Ваш код на самом деле не очень сложный. Вы на самом деле не получаете ничего особенного. Это просто хэш аргументов. Что нужно сделать, это проверить эти случаи:

  • называется без аргументов
  • вызвано с неправильными аргументами
  • вызывается со значением, которое не соответствует шаблону (потерпит неудачу, вы не учитываете это)
  • вызывается с URL с косой чертой с портом
  • вызывается с URL без косой черты с портом
  • вызывается с URL с косой чертой без порта
  • вызывается с URL без косой черты без порта

Все эти тесты довольно просты.

use Test::More;
use strict;
use warnings;

my $foo = Foo->new;

is( $foo->_get_api_host_from_environment(),
    undef, 'return undef without arguments' );
is( $foo->_get_api_host_from_environment( foo => 123 ),
    undef, 'return undef with missing environment' );

{
    local $TODO = 'this check is not implemented yet';

    is(
        $foo->_get_api_host_from_environment(
            environment => 'this is not a URL'
        ),
        undef,
        'environment is not a URL'
    );
}

is(
    $foo->_get_api_host_from_environment(
        environment => 'http://example.org:8174/'
    ),
    'example.org:28174',
    'port number and trailing slash prefixes 2 to the port'
);
is(
    $foo->_get_api_host_from_environment(
        environment => 'http://example.org:8174'
    ),
    'example.org:28174',
    'port number w/o trailing slash prefixes 2 to the port'
);

is(
    $foo->_get_api_host_from_environment(
        environment => 'http://example.org/'
    ),
    'example.org:4040',
    'no port number and trailing slash adds port 4040'
);
is(
    $foo->_get_api_host_from_environment(
        environment => 'http://example.org'
    ),
    'example.org:4040',
    'no port number w/o trailing slash adds port 4040'
);

done_testing;

Обратите внимание, что все мои тесты имеют описательные имена. Хорошие тесты дублируют документацию для разработчика, который будет поддерживать код в будущем (может быть, через год), поэтому убедитесь, что вы действительно говорите о том, что и почему вы тестируете, в своих описаниях.

Там есть $TODO, чтобы показать, что проверка на неправильный URL еще не была построена. Этот тест не пройден, но набор тестов в любом случае пройдет, потому что ожидается его неудача.

Для того, чтобы эти тесты прошли успешно, мне нужно было добавить немного кода к вашему сабвуферу. Это то, что я сделал.

package Foo;
use strict;
use warnings;

sub new { return bless {}, $_[0] }

sub missing_params {
    my $self = shift;
    my $args = shift;

    foreach my $param (@_) {
        return 1 unless exists $args->{$param};
    }

    return;
}

sub _get_api_host_from_environment {
    my ( $self, %args ) = @_;

    $self->missing_params( \%args, qw! environment! )
      and return;

    $args{environment} =~ m{(?:https?://)?([^:\/]+):?([^\/]*)}
      ;    #  http://m5devacoe01.gcsc.att.com:8174/
    my $host = $1;    # m5devacoe01.gcsc.att.com
    my $port = $2;    # 8174

# If port is provided it means that it's a development server request. So, append 2 in the port
    if ($port) {
        $host .= ':2' . $port;
    }
    else {
        $host .= ':4040';
    }

    return $host;
}

Вы заметите, как я изменил ваше регулярное выражение. Это потому, что вы на самом деле ошиблись и не сделали то, что написано в документации. Новый шаблон вводит возможность иметь https вместо http в качестве схемы, для которой у меня не было тестов, а также не иметь схемы вообще. Я не включил тесты для этих случаев, но они действительно должны быть там.

Для этого может быть разумнее использовать модуль URI . Он позволяет вам напрямую изменять порт и дает вам бесплатные проверки работоспособности.

sub _get_api_host_from_environment {
    my ( $self, %args ) = @_;

    $self->missing_params( \%args, qw! environment! )
      and return;

    my $uri = URI->new( $args{environment} ) or return;
    return unless $uri->scheme && $uri->scheme =~ 'http'; # includes https

    my $port = $uri->port;    # 8174

# If port is provided it means that it's a development server request. So, append 2 in the port
    if ($port != 80 and $port != 443) {
        $uri->port( '2' . $port );
    }
    else {
        $uri->port('4040');
    }

    # return $uri->canonical; # this would return http://example.org:28174/
    return $uri->host_port;
}

В этом тесте все те же модульные тесты будут проходить.

...