tags:

views:

56

answers:

2

I want to test a script I have written in Perl and specifically check what output it writes to file. I wrote it some time ago and don't want to modify it to the extent of turning it into a module but would like to regression test it before adding some small functional changes.

So far I have

use Test::Command tests => 10;

exit_is_num($cmd, 0);
....

But the command produces some files and I want to check those files are the same as I expect (either equal or match some regexp). Any suggestions

+2  A: 

OK, I'll go with the brute force DIY approach (however it's possible there's already some test module with file checking API - I just never bumped into one as flexible/generic as what we needed and wrote ourselves and never felt the compelling need to search deeper :).

I'll describe a fairly generic testing setup, you may want/need only very specific file testing aspects of it.

What we do in this case is literally what your functional spec above states, as part of overall testing framework:

  • Have a testing library with two methods (among others) - test_file_identical() and test_grep_file(). If you need help writing those two, please drop a comment and i'll offer some hints (we use different comparators, including a combination of -e, comparisons of various stat attributes, comparing content strings of tested file vs. benchmark file obtained via File::Slurp and doing grep of the file, line by line or via slurped contents for small files, including comparison of massaged grep results to a benchmark file.

  • Have your tests cases organized into sub-directories (or tarballs), one per test, and each test consists of 2 directories - input files and expected output files.

  • Have the test engine script loop over test cases (which for us are meta-described either by a Perl datastructure or better yet, an XML file so business analysts can fiddle with them if needed).

  • If a test case specifies that the test needs to match (exactly or via grep), the test engine finds appropriate files (either hard-coded names, or via name pattern specified in test case), apply those file testing methods mentioned in the first bullet point

DVK
+1  A: 

There's nothing magic about a test. Read the files in, check they have the right contents. Bog simple.

open my $fh, $file;
my $have = join '', <$fh>;

is $have, <<'WANT', "contents of $file";
The quick brown fox
jumped over the lazy grey dog.
WANT

Nothing ground breaking there. Test::File::Contents will provide you with some utility functions so you don't have to write that over and over again.

If you're testing a bunch of files, you can make the process data driven.

my %file_tests;
$file_tests{"expected_filename"} = <<'WANT';
Expected content
WANT
... and so on ...

for my $file (keys %file_tests) {
    my $want = $file_tests{$file};

    file_contents_is($file, $want, "contents of $file");
}

If the contents are large you may want to stick the expected output into files and use files_contents_identical().

Finally, if you want to make sure the program ONLY produced the files you expect and there are no strays, make a temp directory, chdir into that, run the program from there, and check the directory only contains the files you expect. I'll leave that as an exercise for the reader.

Schwern