Как я могу получить 100% тестовое покрытие в модуле Perl, который использует DBI? - PullRequest
6 голосов
/ 18 марта 2010

Я немного новичок в модуле Devel :: Cover, но нашел его очень полезным, чтобы убедиться, что я не пропускаю тесты.

Проблема, с которой я сталкиваюсь - это понимание отчета от Devel :: Cover. Я посмотрел документацию, но не могу понять, что мне нужно проверить, чтобы получить 100% покрытие.

Редактировать - Я должен дать понять, что я не говорю, что мне нужно 100% покрытие, потому что, как указывают несколько человек, 100% покрытие это свободный срок, делает не означает, что мой код не содержит ошибок, и не всегда может быть полностью необходимо. Так как я новичок в Devel :: Обложка, мне интересно знать почему мой код не покрывает 100%, в случае, если я пропускаю некоторые важные тесты.

Вот вывод из отчета с обложки:

line  err   stmt   bran   cond    sub    pod   time   code
...
36                                                    sub connect_database {
37             3                    3      1   1126       my $self = shift;
38             3    100                          24       if ( !$self->{dsn} ) {
39             1                                  7           croak 'dsn not supplied - cannot connect';
40                                                        }
41    ***      2            33                   21       $self->{dbh} = DBI->connect( $self->{dsn}, q{}, q{} )
42                                                          || croak "$DBI::errstr";
43             1                                 11       return $self;
44                                                    }
...
line  err      %      l  !l&&r !l&&!r   expr
----- --- ------ ------ ------ ------   ----
41    ***     33      1      0      0   'DBI'->connect($$self{'dsn'}, '', '') || croak("$DBI::errstr")

А вот и пример моего кода, который тестирует эту конкретную строку:

my $database = MyModule::Database->new( { dsn => 'Invalid DSN' });
throws_ok( sub { $database->connect_database() }, 
   qr/Can't connect to data source/, 
   'Test connection exception (invalid dsn)' );

Этот тест пройден - соединение вызывает ошибку и выполняет мой тест throws_ok.

У меня есть несколько тестов, которые проверяют успешное соединение, поэтому я думаю, что у меня 33% покрытия, но если я правильно его читаю, Cover считает, что я не тестирую часть "|| croak" заявление. Я думал, что с тестом throws_ok, но, очевидно, я что-то упустил.

У кого-нибудь есть советы, как я могу успешно проверить мой DBI-> соединительный провод?

Спасибо!

Edit:

Брайан сообщил мне об отчете в формате HTML и таблице истинности, которая объясняет, почему строка № 41 не проходит. Единственная проблема в том, что я не могу понять, что это говорит мне. Я предполагаю, что реальная суть моего вопроса заключается в том, почему эта конкретная линия не проходит покрытие.

Вот таблица истинности:

LINE # %  # coverage    # condition
41   # 33 # A | B | dec # 'DBI'->connect($$self{'dsn'}, '', '') || croak("$DBI::errstr")
     #    # 0 | 0 | 0   #
     #    # 0 | 1 | 1   #
     #    # 1 | X | 1   # (THIS LINE IS Green - the rest are red)

Если бы кто-нибудь мог помочь объяснить эту таблицу истинности, я был бы признателен. Также было упомянуто, что для прохождения покрытия мне нужен фиктивный объект базы данных, но я не совсем понимаю, как что-то в покрытии приводит к тому, что я могу это понять.

Еще раз спасибо!

Ответы [ 2 ]

10 голосов
/ 18 марта 2010

Кроме того, не зацикливайтесь на 100% тестовом освещении. Цель состоит в том, чтобы полностью протестировать ваше приложение, а не получить отличные результаты в Devel :: Cover. Смотрите сообщения Овидия на эту тему:

В вашем случае, похоже, что вы не покрываете все ветви, поэтому вы не получаете идеальных результатов. Вам нужно пройти тесты, которые выполняют обе стороны этого ||. Вы получаете 33% -ное покрытие, потому что вы обрабатываете только одну треть случаев по этой линии. HTML-отчет от Devel :: Cover показывает таблицу истинности и пропущенные случаи.

Таблица истинности показывает вам возможные состояния, которые вы должны охватить для ветвления. 1 показывает вам условие, которое является истинным, 0 показывает вам условие, которое является ложным, а X показывает вам условие, которого вы не достигнете. Вы должны проверить все комбинации, которые могут быть выполнены. Поскольку || является оператором короткого замыкания, вам не нужно проверять условия, когда один из них проходит:

 0 || 1     connect to database fails and croak succeeds
 0 || 0     connect to database fails and croak fails (unlikely)
 1 || X     connect to database succeeds, so short circuit

Это немного не связано с вашей конкретной проблемой, но я считаю, что она часто встречается в этих проблемах. Хотя Эффективное программирование на Perl - это месяц того, чтобы не попасть на полки, Джош МакАдамс потратил довольно много времени на обсуждение внедрения зависимости в Perl. Если вы испытываете трудности с тестированием своего кода, у вас обычно есть проблемы с дизайном. Например, если вы генерируете объекты базы данных в подпрограммах, вы рисуете себя в углу. Вот почему это может быть трудно проверить. Это может не быть проблемой в вашем случае, но об этом стоит подумать.

5 голосов
/ 18 марта 2010

Вы должны смоделировать библиотеку DBI (или любую другую внешнюю зависимость), чтобы полностью покрыть ваши модульные тесты.

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

Также см. в этой статье специально для насмешек над DBI.

Также убедитесь, что вы используете последнюю версию Devel :: Cover. Однажды я потратил 3 дня на борьбу с модульным тестом, пока не понял, что ошибка не в моем коде, и не в моем модульном тесте, а в более старой версии Devel :: Cover, которую установила моя компания. Он буквально игнорировал определенные пути кода в случаях «A || B».

...