ejvar has asked for the wisdom of the Perl Monks concerning the following question:

sub get_detail_team($team,$debug){ my $dbh = connect to databasehandle my sql = get_sql_details($team,$debug) my $sth = $dbh->prepare($sql) $sth->execute() my $result = $sth->fetchall_arrayref(); return get_html_content($result,prama) }
how do i unit test the above subroutine? get_sql_details() is the subroutine which is SQL string. get_html_content() is the Html content both subroutines are in the same package What are the steps that are need to be taken for unit testing?

Replies are listed 'Best First'.
Re: How do i Unit Test a subroutine
by Anonymous Monk on Jan 23, 2015 at 10:24 UTC

    If you're asking about testing in general, then see Test::More. Just one recent simple example of many to be found online (many CPAN modules have test suites) is here (although in your case I assume you'd be importing the sub in from a module instead of defining it in the test file itself).

    If your question is how to test this specific sub, then it'd be better if you could show the actual code, since this is obviously not it. If you're asking how to test the code with a "fake" database, then perhaps one of the modules Test::MockDBI or DBD::Mock could help (disclaimer: I haven't used them but I've seen them recommended).

      This is the actual code
      Package Team use strict: use warnings; use DBI sub get_detail_team{ my ($team,$debug)=@_; my $dbh = connect to databasehandle my sql = get_sql_details($team,$debug) my $sth = $dbh->prepare($sql) $sth->execute() my $result = $sth->fetchall_arrayref(); return get_html_content($result,prama) } sub get_sql_details{ my ($team,$debug) = @_ my sql = "select id ,org,architec from table where team='$team" return $sql } sub get_html_content{ my ($result,$debug) = @_; return '<br><br>Could not locate architects.' if( scalar @$result == 0 + ); my $html =<br> <table> <th>Id</th><th>... foreach my $result_html(@result){ my ($id,$org,$architect) = @result_html $html.= <td>$id>... return $html; }
      this the overview of the code. Now how can we mock this module to test each of the functions.
        Please fix your code tags, your code is quite hard to read. It seems that you probably have the right opening tag, what might be missing is a closing </code> tag at the end of your code snippets.

        Je suis Charlie.
Re: How do i Unit Test a subroutine
by choroba (Cardinal) on Jan 26, 2015 at 18:13 UTC
    Sometimes, to make your code testable, you have to refactor it. The subroutine you showed is a good candidate:

    Testable subroutine should only do one thing. The one you showed does three: connects to a database (read about "mocking"), constructs a SQL string, htmlizes the result.

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: How do i Unit Test a subroutine
by locked_user sundialsvc4 (Abbot) on Jan 23, 2015 at 13:47 UTC

    This is, of course, very much a personal judgment, “not a religion,” but if I were asked to unit-test this (or, as the case may be, if I directed someone else to do so), I would judge this particular routine, itself, to be too trivial to unit-test on its own.   It can be visually inspected and seen to be okay ...

    Except for the questionable bareword, prama.   You do have:

    use strict;
    use warnings;

    ... don’t you?

    I would, instead, test each of the three application-specific subroutines that this one calls.   I would test that it can connect to the database and that the returned object isa() database handle.   This test need be performed only once, and very early in the test suite.   I would have an entirely separate, aggressive test of the other two routines.   These tests would include, for example:

    • That, when given a known (and known-good) $team and $debug, it produces known-good output.
    • That, when given a $team that is not good, it realizes this and raises some kind of exception.
    • Ditto, if $team is undef.

    I would test get_html_content in a similar way, giving it a known-appropriate but completely synthetic input hashref and checking its result through a series of regular-expression pattern tests.   Also, since we know that it might be passed an undef through code that didn’t end its loop appropriately, I would verify that the subroutine detects this possibility and that it throws an exception.

    And, in passing and in closing, I would like to point out something that you have now heard me say several times:   “verify that the subroutine detects this possibility and that it throws an exception.”   In my experience, the hardest thing about debugging is not, “finding the bug.”   The hardest thing is to detect that a bug exists in an application that is not manifesting any surface symptoms (or, that is manifesting it only by incomprehensible behavior).   If a subroutine suspiciously sniffs at its own inputs and mashes the fire-alarm whenever it detects a foul smell, and if it continues to do this even in production, you will uncover the cockroaches that have been silently hiding out in the cupboard all this time (and crawling all over the “clean” ..ugh.. silverware).   If the routines aggressively test their own inputs (and if those tests, themselves, have been tested), then you can eliminate great swaths of the source-code from consideration because, “if such-and-so were happening here, then subroutine-X would have detected it, ergo, such-and-so probably is not happening here.”   This is an unspoken part of the testing rationale, as well.   It naturally yields software that is more robust and serviceable.