<?xml version="1.0" encoding="windows-1252"?>
<node id="243173" title="Unit Testing CGI Programs" created="2003-03-14 15:41:56" updated="2005-08-12 06:29:12">
<type id="115">
perlquestion</type>
<author id="137285">
Wally Hartshorn</author>
<data>
<field name="doctext">
&lt;p&gt;I'm attempting to Do The Right Thing (tm), i.e. unit test my programs. I've been reading about unit testing, and it sounds like a very good idea -- I'm sold on the concept! Unfortunately, I've been having problems figuring out &lt;b&gt;how&lt;/b&gt; to do it. Nearly all of the programming I do involves database and CGI stuff.&lt;/p&gt;

&lt;p&gt;Most of the information I've found about Test::Harness, Test::Simple, Test::More, etc, seem to focus on examples like this:&lt;/p&gt;
&lt;code&gt;
is ( add_numbers(2, 2), 4);
is ( get_initials("John F. Kennedy"), "JFK");
&lt;/code&gt;

&lt;p&gt;I can understand how to write that kind of test, but I'm having trouble figuring out how to write a test for code that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Retrieves data from a web form (via CGI.pm).&lt;/li&gt;
&lt;li&gt;Retrieves the corresponding row from the database.&lt;/li&gt;
&lt;li&gt;Fills in the template (via HTML::Template).
&lt;li&gt;Returns the HTML output (for display by CGI::Application).&lt;/li&gt;
&lt;/ol&gt;&lt;/p&gt;

&lt;p&gt;My suspicion is that I need to modify my program to make testing easier.&lt;/p&gt;
&lt;readmore&gt;
&lt;p&gt;Suppose the original code is like this:&lt;/p&gt;

&lt;code&gt;
sub show_record {
    my $self = shift;
    my $cgi = $self-&gt;query();
    my $emp_no = $cgi-&gt;param("emp_no");
    ...
    # code to access the database omitted
    ...
    my $emp_rec = $sth-&gt;fetchrow_hashref;
    ...
    # code to fiddle with the data omitted
    ...
    my $template = $self-&gt;load_tmpl(emp_detail.tmpl.html');
    $template-&gt;param( $emp_rec );
    return $template-&gt;output;
}
&lt;/code&gt;

&lt;p&gt;As it is now, I can't figure out how to write a test that would verify that the web page displayed for employee number "12345" is correct. How would I cause $cgi-&gt;param("emp_no") to return "12345"? How would I compare the web page to the expected value? When someone changes the format of the web page, the test would break. Etc.&lt;/p&gt;

&lt;p&gt;As I thought about it, I realized that testing for the value of the web page would not be Doing The Right Thing. Instead, I should probably have a subroutine that gets the &lt;b&gt;data&lt;/b&gt; ready for display, then test &lt;b&gt;that&lt;/b&gt; routine instead. In other words, something more like this:

&lt;code&gt;
sub show_record {
    my $self = shift;
    my $cgi = $self-&gt;query();
    my $emp_no = $cgi-&gt;param("emp_no");

    my $emp_rec = get_emp_data($emp_no);

    my $template = $self-&gt;load_tmpl(emp_detail.tmpl.html');
    $template-&gt;param( $emp_rec );
    return $template-&gt;output;
}

sub get_emp_data {
    my ($emp_no) = (@_);
    ...
    # code to access the database omitted
    ...
    my $emp_rec = $sth-&gt;fetchrow_hashref;
    ...
    # code to fiddle with the data omitted
    ...
    return $emp_rec;
}
&lt;/code&gt;

&lt;p&gt;With the above changes, I wouldn't do unit tests of show_record(), on the theory that it is pretty much all presentation code, not logic (although if anyone has suggestions on how to write unit tests for that, I'm interested). Instead, I would just test get_emp_rec().&lt;/p&gt;

&lt;p&gt;Does that sound like Doing The Right Thing, or is there some nifty trick out there that I'm missing?&lt;/p&gt;

&lt;p&gt;Wally Hartshorn&lt;br&gt;&lt;br&gt;
(Plug: Visit [http://javajunkies.org/|JavaJunkies], PerlMonks for Java)&lt;/p&gt;</field>
</data>
</node>
