The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Test::TestUtil - functions that support Test::STDmaker

SYNOPSIS

  use Test::TestUtil

  $data          = Test::TestUtil->fin( $file_name )
  $success       = Test::TestUtil->fout($file_name, $data)

  $package       = Test::TestUtil->is_package_loaded($package)
  $error         = Test::TestUtil->load_package($package)
  $errors        = Test::TestUtil->pod_errors($package)

  $scrubbed_text = Test::TestUtil->scrub_date_version($script_text)
  $scrubbed_text = Test::TestUtil->scrub_file_line($script_text)
  $scrubbed_text = Test::TestUtil->scrub_test_file($script_text)
  $scrubbed_text = Test::TestUtil->scrub_date_ticket($script_text)

  $date          = Test::TestUtil->get_date( )

  $table         = Test::TestUtil->format_hash_table(\%hash, \@width, \@header)
  $table         = Test::TestUtil->format_array_table(\@array, \@width, \@header)

  $file          = Test::TestUtil->fspec2fspec($from_fspec, $to_fspec $fspec_file, [$nofile])
  $os_file       = Test::TestUtil->fspec2os($fspec, $file, [$no_file])
  $fspec_file    = Test::TestUtil->os2fspec($fspec, $file, [$no_file])
  $pm_file       = Test::TestUtil->fspec2pm( $fspec, $file )
  $file          = Test::TestUtil->pm2file($pm_file)
  $file          = Test::TestUtil->pm2require($pm_file)

  ($file, $path) = Test::TestUtil->find_in_path($fspec, $file, [\@path])
  @INC           = Test::TestUtil->test_lib2inc()
  @t_path        = Test::TestUtil->find_t_paths()

  $fh            = Test::TestUtil->pm2datah($pm_file)
  $data          = Test::TestUtil->pm2data($pm_file)

  $success       = Test::TestUtil->replace_variables( \$template, \%variable_hash, \@variable)

  @drivers       = Test::TestUtil->drivers($base_file, @dirs)
  $driver        = Test::TestUtil->is_driver($driver, @drivers)

  @globed_files  = Test::TestUtil->fspec_glob($fspec, @files)

DESCRIPTION

The methods in the Test::TestUtil package are designed to support the Test::STDmaker and the ExtUtils::SVDmaker package. This is the focus and no other focus. Since Test::TestUtil is a separate package, the methods may be used elsewhere. In all likehood, any revisions will maintain backwards compatibility with previous revisions. However, support and the performance of the Test::STDmaker and ExtUtils::SVDmaker packages has priority over backwards compatibility.

The methods in this package are designed to work properly on different operating systmes. Different operating systems have different file specifications. File structures are basically the same but the notation to identify files in a file structure are different from one operating system to another operating system.

The input variable $fspec tells the methods in this package the file specification for file names used as input to the methods. Supported operating system file specifications are as follows:

 MacOS
 MSWin32
 os2
 VMS
 epoc

The variable $^O contains the file specification for the current operating system.

drivers method

  @drivers = Test::TestUtil->drivers($base_file, @dirs)

Placing driver objects in their own private directory provides a method to add new drivers without changing the parent object. The parent object finds all the available drivers by listing the files in the driver directory using the drivers method.

The driver method takes as its input a $base_file, usually the parent object, and a list of subdirectories, @base, relative to the $base. It returns the a list, @drivers, of *.pm file names stripped of the extension .pm in the identified directory.

For example, if the subdirectory Drivers to the file __FILE__ contains the files Driver.pm Generate.pm IO.pm, then

 ==> join ',', sort Test::TestUtil->drivers( __FILE__, 'Drivers' );

 'Driver, Generate, IO'

fin fout method

  $data = Test::TestUtil->fin( $file_name )
  $success = Test::TestUtil->fout($file_name, $data, \%options)

Different operating systems have different new line sequences. Microsoft uses \015\012 for text file, \012 for binary files, Macs \015 and Unix 012. Perl adapts to the operating system and uses \n as a logical new line. The \015 is the ASCII Carraige Return (CR) character and the \012 is the ASCII Line Feed character.

The fin method will translate any CR LF combination into the logical Perl \n character. Normally fout will use the Perl \n character. In other words fout uses the CR LF combination appropriate of the operating system and file type. However supplying the option {binary = 1}> directs fout to use binary mode and output the CR LF raw without any translation.

By using the fin and fout methods, text files may be freely exchanged between operating systems without any other processing. For example,

 ==> my $text = "=head1 Title Page\n\nSoftware Version Description\n\nfor\n\n";
 ==> Test::TestUtil->fout( 'test.pm', $text, {binary => 1} );
 ==> Test::TestUtil->fin( 'test.pm' );

 =head1 Title Page\n\nSoftware Version Description\n\nfor\n\n

 ==> my $text = "=head1 Title Page\r\n\r\nSoftware Version Description\r\n\r\nfor\r\n\r\n";
 ==> Test::TestUtil->fout( 'test.pm', $text, {binary => 1} );
 ==> Test::TestUtil->fin( 'test.pm' );

find_in_path method

 ($file_absolute, $path) = Test::TestUtil->find_in_path($fspec, $file_relative, [\@path])

The find_in_path method looks for the $file_relative in one of the directories in the @INC path or else the @path in the order listed. The file $file_relative may include relative directories. When find_in_path finds the file, it returns the abolute file $file_absolute and the directory $path where it found $file_relative. The input variable $fspec is the file specification for $file_relative.

For example, running on Microsoft windows with C:\Perl\Site\t in the @INC path, and the file Test\TestUtil\TestUtil.t present

 ==> Test::TestUtil->find_in_path('Unix', 'Test/TestUtil/TestUtil.t')

 C:\Perl\Site\t\Test\TestUtil\TestUtil.t
 C:\Perl\Site\t

find_t_paths method

This method operates on the assumption that the test files are a subtree to a directory named t and the t directories are on the same level as the last directory of each directory tree specified in @INC. If this assumption is not true, this method most likely will not behave very well.

The find_t_paths method returns the directory trees in @INC with the last directory changed to t.

For example,

 ==> @INC

 myperl/lib
 perl/site/lib
 perl/lib 

 => Test::TestUtil->find_t_paths()

 myperl/t
 perl/site/t
 perl/t 

format_array_table method

 $formated_table = Test::TestUtil->format_array_table(\@array, \@width, \@header)

The format_array_table method provides a formatted table suitable for inclusion in a POD. The \@array variable references an array of array references. Each array reference in the top array is for a row array that contains the items in column order for the row. The \@width variable references the width of each column in column order while the \@header references the table column names in column order.

For example,

 ==> @array_table 

 ([qw(module.pm 0.01 2003/5/6 new)],
 [qw(bin/script.pl 1.04 2003/5/5 generated)],
 [qw(bin/script.pod 3.01 2003/6/8), 'revised 2.03'])

 Test::TestUtil->format_array_table(\@array_table, [15,7,10,15], [qw(file version date comment)])

 file            version date       comment
 --------------- ------- ---------- ---------------
 module.pm       0.01    2003/5/6   new
 bin/script.pl   1.04    2003/5/5   generated
 bin/script.pod  3.01    2003/6/8   revised 2.03

format_hash_table method

 $table = Test::TestUtil->format_hash_table(\%hash, \@width, \@header)

The format_hash_table method provides a formatted table suitable for inclusion in a POD. The \%array variable references a hash of references to either arrays or hashes. Each key is the first column of a row. An array referenced by the hash value contains the items in column order for the rest of the row. The keys of a hash referenced by the hash value is the items for the next column in the row. Any other hash value signals the end of the row. The format_hash_table method always sort hash keys.

The \@width variable references the width of each column in column order while the \@header references the table column names in column order.

For example,

 => %hash_array_table

 ('module.pm' => [qw(0.01 2003/5/6 new)],
 'bin/script.pl' => [qw(1.04 2003/5/5 generated)],
 'bin/script.pod' => [qw(3.01 2003/6/8), 'revised 2.03'])

 ==> Test::TestUtil->format_hash_table(\%hash_array_table, [15,7,10,15],[qw(file version date comment)])

 file            version date       comment
 --------------- ------- ---------- ---------------
 bin/script.pl   1.04    2003/5/5   generated
 bin/script.pod  3.01    2003/6/8   revised 2.03
 module.pm       0.01    2003/5/6   new

 ==> %hash_hash_table

 ('L<test1>' => {'L<requirement4>' => undef, 'L<requirement1>' => undef },
   'L<test2>' => {'L<requirement3>' => undef },
   'L<test3>' => {'L<requirement2>' => undef, 'L<requirement1>' => undef },)

 ==> Test::TestUtil->format_hash_table(\%hash_hash_table, [20,20],[qw(test requirement)])

 test                 requirement
 -------------------- --------------------
 L<test1>             L<requirement1>
 L<test1>             L<requirement4>
 L<test2>             L<requirement3>
 L<test3>             L<requirement1>
 L<test3>             L<requirement2>

fspec_glob method

  @globed_files = Test::TestUtil->fspec_glob($fspec, @files)

The fspec_glob method BSD globs each of the files in @files where the file specification for each of the files is $fspec.

For example, running under the Microsoft operating system, that contains a directory Drivers with file Generators.pm Driver.pm IO.pm under the current directory

 => Test::TestUtil->fspec_glob('Unix','Drivers/G*.pm')

 Drivers\Generate.pm

 => Test::TestUtil->fspec_glob('MSWin32','Drivers\\I*.pm') 

 Drivers\IO.pm

fspec2fspec method

 $to_file = Test::TestUtil->fspec2fspec($from_fspec, $to_fspec $from_file, $nofile)

THe fspec2fspec method translate the file specification for $from_file from the $from_fspec to the $to_fpsce. Supplying anything for $nofile, tells the fspec2fspec method that $from_file is a directory tree; otherwise, it is a file.

For example,

 => Test::TestUtil->fspec2fspec( 'Unix', 'MSWin32', 'Test/TestUtil.pm') 

 Test\\TestUtil.pm

fspec2os method

  $os_file = Test::TestUtil->fspec2os($fspec, $file, $no_file)

The fspec2os method translates a file specification, $file, from the current operating system file specification to the $fspec file specification. Supplying anything for $nofile, tells the fspec2fspec method that $from_file is a directory tree; otherwise, it is a file.

For example, running under the Microsoft operating system:

 ==> Test::TestUtil->fspec2os( 'Unix', 'Test/TestUtil.pm')
 
 Test\\TestUtil.pm

fspec2pm method

 $pm_file = Test::TestUtil->fspec2pm( $fspec, $file )

The fspec2pm method translates a filespecification $file in the $fspce format to the Perl module formate.

For example,

 ==> Test::TestUtil->fspec2pm('Unix', 'Test/TestUtil.pm')

 Test::TestUtil

get_date method

 $date = Test::TestUtil->get_date( )

The get_date method returns the data in yyyy/mm/dd format. This is the preferred US Department of Defense (DOD) format because the dates sort naturally in ascending order.

For example,

 => Test::TestUtil->get_date( )
 1969/02/06

is_driver method

 $driver = Test::TestUtil->is_driver($driver, @drivers)

The is_driver method determines if $driver is present in @drivers. The detemination is case insensitive and only the leading characters are needed.

For example,

 ==> @drivers

 (Driver
 Generate
 IO)

 ==> Test::TestUtil->is_driver('dri', @drivers )

 Driver

is_package_loaded method

 $package = Test::TestUtil->is_package_loaded($package)

The is_package_loaded method determines if a package vocabulary is present.

For example, if File::Basename is not loaded

 ==> Test::TestUtil->is_package_loaded('File::Basename')

 ''

load_package method

 $error = Test::TestUtil->load_package($package)

The load_package method loads attempts to load a package. The return is any $error that occurred during the load attempt. The load_package will check that the package vocabulary is present. Altough it is a Perl convention, the package name(s) in a package file do not have to be the same as the package file name. For these few cases, this method will load the packages in the file, but fail the package vocabulary test.

For example,

 ==> Test::TestUtil->load_package( 'File::Basename' )
 ''

os2fspec method

 $file = Test::TestUtil->os2fspec($fspec, $os_file, $no_file)

The fspec2os method translates a file specification, $file, from the current operating system file specification to the $fspec file specification. Supplying anything for $nofile, tells the fspec2fspec method that $from_file is a directory tree; otherwise, it is a file.

For example, running under the Microsoft operating system:

 ==> Test::TestUtil->os2fspec( 'Unix', 'Test\\TestUtil.pm')

 Test/TestUtil.pm

pm2datah method

 $fh = Test::TestUtil->pm2datah($pm_file)

The pm2datah method will open the $pm_file and return a handle positioned at the first /[\012\015]__DATA__/ token occuring in the file. This function is very similar to the DATA file handle that Perl creates when loading a module file with the /[\012\015]__DATA__/ token. The differences is that pm2datah works whether or not the file module is loaded. The method does not close the file handle. Unlike the DATA file handle, which cannot be reused after the module data is read the first time, the pm2datah will always return an opened file handle, the first time, the second time, any time.

CAUTION:

If the /[\012\015]__DATA__/ token appears in the code section, say in a comment, or as a value assigned to a variable, the pm2datah method will misbehave.

For example,

 ==> my $fh = Test::TestUtil->pm2datah('Test::TestUtil::Drivers::Driver')
 ==> join '',<$fh>;

 \=head1 Title Page

  Software Version Description

  for

  ${TITLE}

  Revision: ${REVISION}

  Version: ${VERSION}

  Date: ${DATE}

  Prepared for: ${END_USER} 

  Prepared by:  ${AUTHOR}

  Copyright: ${COPYRIGHT}

  Classification: ${CLASSIFICATION}

 \=cut

EOF

pm2data method

 $data = Test::TestUtil->pm2data($pm_file)

The pm2data uses the pm2datah to return all the data in a $pm_file form the __DATA__ token to the end of the file.

For example,

 ==> my $fh = Test::TestUtil->pm2data('Test::TestUtil::Drivers::Driver')

 \=head1 Title Page

  Software Version Description

  for

  ${TITLE}

  Revision: ${REVISION}

  Version: ${VERSION}

  Date: ${DATE}

  Prepared for: ${END_USER} 

  Prepared by:  ${AUTHOR}

  Copyright: ${COPYRIGHT}

  Classification: ${CLASSIFICATION}

 \=cut

EOF

pm2file method

  ($file, $path) = Test::TestUtil->pm2file($pm_file)

The pm2file method returns the absolute file and the directory in @INC for a the program module $pm_file.

For example, running on a Microsoft operating system, if Test::TestUtil is in the C:\myperl\t directory, and C:\myperl\t is in the @INC path,

 ==> Test::TestUtil->pm2file( 'Test::TestUtil');

 (C:\myperl\t\Test\TestUtil.pm
 C:\myperl\t)

pod_errors method

 $errors = Test::TestUtil->pod_errors($package)

The pod_errors uses Pod::Checker to analyze a package and returns the number of $errors

For example,

 ==> Test::TestUtil->pod_errors( 'File::Basename')

 0

pm2require

 $file = Test::TestUtil->pm2require($pm_file)

The pm2require method returns the file suitable for use in a Perl require given the $pm_file file.

For example, running under Microsoft Windows

 ==> Test::TestUtil->pm2require( 'Test::TestUtil')

 Test\TestUtil.pm

replace_variables

 $success = Test::TestUtil->replace_variables( \$template, \%variable_hash, \@variable)

For example

 ==> $template
 =head1 Title Page

  Software Version Description

  for

  ${TITLE}

  Revision: ${REVISION}

  Version: ${VERSION}

  Date: ${DATE}

  Prepared for: ${END_USER} 

  Prepared by:  ${AUTHOR}

  Copyright: ${COPYRIGHT}

  Classification: ${CLASSIFICATION}

 =cut

 ==> %variables
 (TITLE => 'SVDmaker',
 REVISION => '-',
 VERSION => '0.01',
 DATE => '2003/6/10',
 END_USER => 'General Public',
 AUTHOR => 'Software Diamonds',
 COPYRIGHT => 'none',
 CLASSIFICATION => 'none')

 ==> $Test::TestUtil->replace_variables(\$template, \%variables);

 =head1 Title Page

  Software Version Description

  for

  SVDmaker

  Revision: -

  Version: 0.01

  Date: 2003/6/10

  Prepared for: General Public 

  Prepared by:  Software Diamonds

  Copyright: none

  Classification: none

 =cut

scrub_date_ticket

 $scrubbed_text = Test::TestUtil->scrub_date_ticket($script_text)

When comparing the contents of email messages, the date and email ticket should not be used in the comparision. The scrub_date_ticket method will replace the date and email ticket with a generic value. Applying the scrub_date_ticket to the contents of both files before the comparision will eliminate the data and ticket as factors in the comparision.

For example,

 ==> $text

 Date: Feb 6 00 00 00 1969 +0000
 Subject: 20030506, This Week in Health
 X-SDticket: 20030205
 X-eudora-date: Feb 6 2000 00 00 2003 +0000
 X-SDmailit: dead Feb 5 2000 00 00 2003
 Sent email 20030205 to support.softwarediamonds.com
 
 ==> Test::TestUtil->scrub_date_ticket($text)

 Date: Apr 12 00 00 00 2003 +0000
 Subject: XXXXXXXXX-X,  This Week in Health'
 X-SDticket: XXXXXXXXX-X
 X-eudora-date: Apr 12 00 00 00 2003 +0000
 X-SDmailit: dead Sat Apr 12 00 00 00 2003 +0000
 Sent email XXXXXXXXX-X to support.softwarediamonds.com

scrub_date_version

 $scrubbed_text = Test::TestUtil->scrub_date_version($script_text)

When comparing the contents of two Perl program modules, the date and version should not be used in the comparision. The scrub_date_ticket method will replace the date and version with a generic value. Applying the scrub_date_ticket to the contents of both files before the comparision will eliminate the date and version as factors in the comparision.

For example,

 ==> $text

 $VERSION = \'0.01\';
 $DATE = \'2003/06/07\';

 ==> Test::TestUtil->scrub_date_version($text)

 $VERSION = '0.00;
 $DATE = 'Jan 1, 2000';

scrub_file_line

 $scrubbed_text = Test::TestUtil->scrub_file_line($script_text)

When comparing the ouput of Test module the file and line number should not be used in the comparision. The scrub_file_line method will replace the file and line with a generic value. Applying the scrub_file_line to the contents of both files before the comparision will eliminate the file and line as factors in the comparision.

For example,

 ==> $text 

 ok 2 # (E:/User/SoftwareDiamonds/installation/t/Test/STDmaker/tgA1.t at line 123 TODO?!)';

 ==> Test::TestUtil->scrub_file_line($text)

 ok 2 # (xxxx.t at line 000 TODO?!)

scrub_test_file

 $scrubbed_text = Test::TestUtil->scrub_test_file($script_text)

When comparing the ouput of Test:Harness module the test file should not be used in the comparision. The scrub_test_file method will replace the test file with a generic value. Applying the scrub_test_file to the contents of both files before the comparision will eliminate the test file as a factor in the comparision.

For example,

 ==>$text

 Running Tests\n\nE:/User/SoftwareDiamonds/installation/t/Test/STDmaker/tgA1.1..16 todo 2 5;

 ==> Test::TestUtil->scrub_test_file($text)

 Running Tests xxx.t 1..16 todo 2 5;

test_lib2inc method

 @INC = Test::TestUtil->test_lib2inc()

When building a distribution, the test scripts should test the distribution modules. The test_lib2inc method assumbe that the current directory is in the t subtree and that there is a lib subtree at the same level with the Unit Under Test (UUT). If these assumptions are not meet, the test_lib2inc method probably will not behave properly.

In order to find the proper UUT, the test_lib2inc method will walk up the tree specifcation until it finds a t directory and put the t subtree on a lib subtree at the same level on the @INC array. The test_lib2inc will return the @INC array value before the <t> and <lib> subtrees on @INC. Use this value to restore @INC after using the test_lib2inc method. Another way to restore @INC is to shift two items from the top of @INC

For example,

 ==> @INC
  
 (myperl/lib
 perl/site/lib
 perl/lib)
  
 ==> cwd()

 myperl/packages/Test-TestUtil-0.01/t/Test/TestUtil

 ==> my @restore_inc = $T->test_lib2inc( );

 ==> @INC

 (myperl/packages/Test-TestUtil-0.01/lib
 myperl/packages/Test-TestUtil-0.01/t
 myperl/lib
 perl/site/lib
 perl/lib)

NOTES

AUTHOR

The holder of the copyright and maintainer is

<support@SoftwareDiamonds.com>

Copyrighted (c) 2002 Software Diamonds

All Rights Reserved

BINDING REQUIREMENTS NOTICE

Binding requirements are indexed with the pharse 'shall[dd]' where dd is an unique number for each header section. This conforms to standard federal government practices, 490A ("3.2.3.6" in STD490A). In accordance with the License, Software Diamonds is not liable for any requirement, binding or otherwise.

LICENSE

Software Diamonds permits the redistribution and use in source and binary forms, with or without modification, provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

SOFTWARE DIAMONDS, http::www.softwarediamonds.com, PROVIDES THIS SOFTWARE 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWARE DIAMONDS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING USE OF THIS SOFTWARE, EVEN IF ADVISED OF NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE POSSIBILITY OF SUCH DAMAGE.