APGRMF has asked for the wisdom of the Perl Monks concerning the following question:
I've written a unit test script to test various functions in a process. All seems OK - if I run the unit test script all tests pass. However, if I run it a number of times it ends up failing.
The behavior is inconsistent and I don't understand why. I haven't written that many perl scripts or tests so I'm sure my understanding is at fault somewhere.
Anyway, I've narrowed the issue down to a single unit test that uses is_deeply to test an array returned by the function "get_files_in_watched_directory" against an array populated with the expected result.
The error message states that the "The structures begin differing at filename line 85" which is the end of the "get_files_in_watched_directory" subtest. If I print the expected and actual array contents to the screen they appear to be identical.
I'm clearly missing something.
Any thoughts would be greatly appreciated.
unit test code
use strict; use warnings; use Test::More tests => 2; #'no_plan'; use Test::Exception; use Test::Builder; use Test::Directory; use File::Temp qw( tempfile tempdir ); use File::Basename; use File::Path; my $builder = Test::More->builder->output('results.txt'); # Call the perl script under test note "Check perl script under test loaded OK"; ok( require( '../apg-problem-perl.pl' ), 'loaded file okay' ) or exit; note "\nTest function: get_files_in_watched_directory"; subtest 'get_files_in_watched_directory' => sub { my @got_files; my @expected_files; my $project_name = 'default'; # create a temporary directory my $temp_dir = tempdir( CLEANUP => 1 ); # create some temporary files in the directory my ($temp_file1_handle, $temp_file1) = tempfile(DIR => $temp_dir); my ($temp_file2_handle, $temp_file2) = tempfile(DIR => $temp_dir); # create an array populated with the names of the temporary files th +at we expectd to see push (@expected_files, basename($temp_file1)); push (@expected_files, basename($temp_file2)); # now pass the temporary directory to the the function # the function should return an array @got_files with the names of t +he files in the directory @got_files = get_files_in_watched_directory($temp_dir, $project_name +); message_log ("\n\nGOT", "high"); foreach my $this_file (sort @got_files) { message_log ("\n $this_file", "high"); } message_log ("\n\nEXPECTED", "high"); foreach my $this_file (sort @expected_files) { message_log ("\n $this_file", "high"); } #compare the two arrays is_deeply(\@got_files, \@expected_files, 'Function should return a l +ist of directory contents that will be processed'); }; done_testing();
Code under test
use strict; use warnings; use Getopt::Std; use FileHandle; use File::Find; use File::Path; use File::Copy; use File::Basename; use Archive::Zip qw( :ERROR_CODES :CONSTANTS); use XML::LibXML; use XML::Simple; use XML::Parser; use Data::Dumper; use DateTime; use Net::FTP; ###################################################################### +################################# # disable output buffering (I think) $|=1; ###################################################################### +################################# # # GLOBAL VARIABLES # ###################################################################### +################################# my $path_to_process ; my $ftp_target_folder; my $project_name; my $process_root_dir; my $target_ftp_site; my $in_progress_dir; # location of zipped content to b +e sent via FTP my $archived_dir; # location of zipped content alre +ady sent via FTP my $archived_success_dir; # root location of processed file +s my $archived_failed_dir; # root location of processed file +s my $archived_not_attempted_dir; my $Fail_Message_Prefix; # Standardised message following +a script failure my $log_dir; # location of logs files my $log_file; # log file name my $log_fh; # log file handle my $lock_fh; # "in progress" file handle my $environment; # wkuk environment type: live, qa +, test, test-local my $server; # wkuk server type: ukkinhmrc01, +productionbuild, localhost my $process_root_path; # process root path my $dctm_export_path; # documentum smart content export + path my $debug_default_mode = "normal"; # debug mode my $debug_mode; # debug mode my $datestamp; ###################################################################### +################################# # # INITIALISE VARIABLES # ###################################################################### +################################# $Fail_Message_Prefix = "\n\nScript Failure:\n"; ###################################################################### +################################# # # START # ###################################################################### +################################# # call main subroutine eveything is kicked off from there main( @ARGV ) unless caller(); ###################################################################### +################################# # # Main subroutine # ###################################################################### +################################# sub main { } ###################################################################### +################################## sub get_files_in_watched_directory { my ($directory_to_check, $project_name) = @_; my @problem_files; my @content_to_process; my $this_file; message_log ("\n\nCalled Function: get_files_in_watched_directory", +"low"); message_log ("\n Checking $directory_to_check", "low"); chdir ($directory_to_check) || die "cannot chdir to directory $direc +tory_to_check: $!"; # Get everything - files and directories - and decide what to do wit +h each one opendir(DIR,$directory_to_check) || die "cannot open directory $dire +ctory_to_check: $!"; while (defined($this_file = readdir(DIR))) { my $full_file_name = $directory_to_check . '/' . $this_file; # ignore the special directories "." and '.." if ($this_file =~ /^\.\.?$/) { next } elsif ($project_name eq 'topics') { if (is_valid_topic_directory($full_file_name)) { push (@content_to_process, $this_file) } } elsif ($project_name eq 'resources') { if (is_valid_resources_directory($full_file_name)) { push (@content_to_process, $this_file) } } # wite anything else (file or directory) to an array to be process +ed later else { message_log ("\n found: $this_file", "normal"); push (@content_to_process, $this_file) } } return @content_to_process; } ###################################################################### +################################## sub is_valid_topic_directory { # Check is this is valid topic content. # To be valid the content must: # - be a directory # - be a recognised directory name # - contain a complete file to show that the export from documentum +has completed my ($content_dir) = shift; message_log ("\nCalled function: is_valid_topic_directory", "normal" +); # must be a directory and contain a complete file if (-d $content_dir && -e $content_dir . '/' . 'complete') { # must be valid name for topic cntent # this can include topic, training module, pubdb and orgdb content if (basename($content_dir) =~ /^mini-[^-]+?-topics-\d+$/ || basename($content_dir) =~ /^mini-(:?orgdb|pubdb)-smart-databas +e+$/) { message_log ("\n apg 001: basename($content_dir)", "normal"); return 1; } } # fail by default return 0; } ############################################ sub is_valid_resources_directory { # Check is this is valid news and resources content. # To be valid the content must: # - be a directory # - be a recognised directory name # - contain a complete file to show that the export from documentum +has completed my ($content_dir) = shift; message_log ("\nCalled function: is_valid_resources_directory", "nor +mal"); message_log ("\n apg 001: basename($content_dir)", "normal"); # must be a directory and contain a complete file if (-d $content_dir && -e $content_dir . '/' . 'complete') { # must be valid name for news and resources cntent # this can include full or delta exports, training module, pubdb a +nd orgdb content # for example: recent-briefings, recent-news # all-gold-briefings, all-gold-news if (basename($content_dir) =~ /^(:?recent|all-gold)-(:?briefings|c +asereports|features|legtrackers|news|questions|wnupdates)$/) { message_log ("\n apg 002: basename($content_dir)", "normal"); return 1; } } # fail by default return 0; } ###################################################################### +################################# sub message_log { # write a message to the screen and the log # what gets written depends on the script debug mode and message imp +ortance # -message importance: low, normal, high # -script mode: normal, silent, debug #What to write and when: # - silent mode : write message only if it's high importance # - normal mode : write message if it's high or normal importance # - debug mode : write everything # tis needs some work..... my ($message, $importance) = @_; #Important information #- always print to stdout #- print to the log is it's open if ($importance eq lc"high") { print "$message"; if (defined $log_fh) { print $log_fh "$message"; } } #Debugging information #- never print to stdout #- print to the log if it's open and the script is in debug mode elsif ($importance eq lc"low") { if (defined $log_fh) { if (defined $debug_mode && $debug_mode eq lc"debug") { print $log_fh "$message"; } } } # Anything else # -print to the log if it's open # -otherwise print to stdout because the meassage will otherwise be +lost else { if (defined $log_fh) { print $log_fh "$message"; } else { print "$message"; } } } ########################################### # # END # ########################################### # return true 1;
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: inconistent test results when using is_deeply to test an array returned from a function
by kennethk (Abbot) on Sep 24, 2014 at 16:29 UTC | |
by APGRMF (Novice) on Sep 25, 2014 at 10:00 UTC | |
by APGRMF (Novice) on Sep 25, 2014 at 10:21 UTC | |
by Anonymous Monk on Sep 25, 2014 at 10:54 UTC | |
by APGRMF (Novice) on Sep 25, 2014 at 11:19 UTC | |
| |
by APGRMF (Novice) on Sep 25, 2014 at 07:38 UTC |