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

Dear Monks,

I am trying to write my first Perl module (Net::SNTP::Client). I have post several questions over and over trying to get some help from the experts. So unfortunately now I got stack again, with the testing and verification of the module.

So first thing first. The module code if someone want to test it can be found here RFC: Net::SNTP::Client v1.

So as a next step I should explain what I am doing.

I was following the instructions from How to make a CPAN Module Distribution where I completed all steps even the testing part. Now I am trying to verify my module before I uploaded on CPAN and I got stack.

I am trying to install the module manually by applying the following commands:

perl Makefile.PL make make test sudo make install

Everything seems to be fine up to the point of make test. I am getting the following error:

make test PERL_DL_NONLAZY=1 "/usr/bin/perl" "-MExtUtils::Command::MM" "-MTest::H +arness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/l +ib', 'blib/arch')" t/*.t t/Net-SNTP-Client.t .. 1/15 # Failed test 'Module Hash Keys are Identical' # at t/Net-SNTP-Client.t line 94. # Failed test 'Exptected Output From the Module Received' # at t/Net-SNTP-Client.t line 98. # Comparing hash keys of $data # Missing: 'Net-SNTP-Client.t' # Extra: 't/Net-SNTP-Client.t' # Looks like you failed 2 tests of 15. t/Net-SNTP-Client.t .. Dubious, test returned 2 (wstat 512, 0x200) Failed 2/15 subtests Test Summary Report ------------------- t/Net-SNTP-Client.t (Wstat: 512 Tests: 15 Failed: 2) Failed tests: 6-7 Non-zero exit status: 2 Files=1, Tests=15, 1 wallclock secs ( 0.04 usr 0.00 sys + 0.11 cusr + 0.02 csys = 0.17 CPU) Result: FAIL Failed 1/1 test programs. 2/15 subtests failed. make: *** [test_dynamic] Error 2

The strange part is that I am executing the test manually inside the /t directory through the command: perl Net-SNTP-Client.t everything compiles and executes just fine.

Sample of output:

1..15 ok 1 - use Net::SNTP::Client; ok 2 - Module Hash Input Works ok 3 - Hostname Must be Defined ok 4 - Port Has to be Defined and Integer ok 5 - Got Hash Output ok 6 - Module Hash Keys are Identical ok 7 - Exptected Output From the Module Received ok 8 - Faulty Test Extra Key ok 9 - Correct Output Error Extra Hash Key ok 10 - Faulty Test no Hostname ok 11 - Correct Output Error No Hostname ok 12 - Faulty Test Negative Port Number ok 13 - Correct Output Error for Negative Port Number ok 14 - Faulty Test Out of Range Port Number ok 15 - Correct Output Error Out of Range Port Number

So the question is why is it failing, when manually is not? What I am missing?

Bellow is the test cases code in case that someone would like to replicate the error.

# Before 'make install' is performed this script should be runnable wi +th # 'make test'. After 'make install' it should work as 'perl Net-SNTP-C +lient.t' ######################### # change 'tests => 1' to 'tests => last_test_to_print'; use strict; use warnings; use lib '/home/username/Desktop/Net-SNTP-Client-0.01/lib/'; # note her +e use Test::More tests => 15; use Test::Deep; my %hashInputModuleHostnameTest = ( -hostname => undef ); my %hashInputModuleTest = ( -hostname => "0.pool.ntp.org", -port => 123 ); my %hashInputModuleTestExtraKeysInserted = ( -hostname => "0.pool.n +tp.org", -port => 123, -RFC4330 => 1, -clearScreen => 1, -extraKey => "Test" ); my %hashInputModuleTestNoHostName = ( -port => 123, -RFC4330 => 1, -clearScreen => 1 ); my %hashInputModuleTestNegativePortNumber = ( -hostname => "0.pool. +ntp.org", -port => -123, -RFC4330 => 1, -clearScreen => 1 ); my %hashInputModuleTestOutOfRangePortNumber = ( -hostname => "0.poo +l.ntp.org", -port => 65536, -RFC4330 => 1, -clearScreen => 1 ); my %hashInputModuleTestNotCorrectNtpPortNumber = ( -hostname => "0. +pool.ntp.org", -port => 12345, -RFC4330 => 1, -clearScreen => 1 ); my @hashInputModuleTestOriginalKeys = ( "-hostname" , "-port", "-RFC43 +30", "-clearScreen" ); my $hashRefExpected = { 'Net-SNTP-Client.t' => { 'VN' => 4, 'Originate Timestamp' => '00', 'Root Delay' => '0', 'Stratum' => '0', 'Receive Timestamp' => ignore(), 'Transmit Timestamp' => ignore(), 'Reference Timestamp' => '00', 'Precision' => '0', 'LI' => 0, 'Root Dispersion' => '0', 'Poll' => '0', 'Reference Identifier' => '0', 'Mode' => 3 }, 'RFC4330' => { 'Round Trip Delay' => ignore(), 'Clock Offset' => ignore() }, '0.pool.ntp.org' => { 'LI' => ignore(), 'Transmit Timestamp' => ignore(), 'Receive Timestamp' => ignore(), 'Reference Timestamp' => ignore(), 'Precision' => ignore(), 'Root Delay' => ignore(), 'Stratum' => ignore(), 'VN' => 4, 'Originate Timestamp' => ignore(), 'Mode' => 4, 'Poll' => ignore(), 'Reference Identifier' => ignore(), 'Root Dispersion' => ignore() } }; BEGIN { use_ok('Net::SNTP::Client', qw(getSNTPTime) ) }; ok( getSNTPTime( %hashInputModuleTest ), 'Module Hash Input Works' ); ok( !defined( $hashInputModuleHostnameTest{-hostname} ), 'Hostname Mus +t be Defined' ); ok( defined( $hashInputModuleTest{-port} ) && $hashInputModuleTest{-po +rt} =~ /\A (\d+) \z/xms , 'Port Has to be Defined and Integer' ); ok( my ( $error , $hashRefOutput ) = getSNTPTime( %hashInputModuleTest + ), 'Got Hash Output' ); my @expectedHashKeys = ( 'Net-SNTP-Client.t', 'RFC4330', '0.pool.ntp.o +rg' ); my @gotHashRefKeys = keys $hashRefOutput; ok( eq_set(\@gotHashRefKeys, \@expectedHashKeys), 'Module Hash Keys ar +e Identical' ); #is_deeply( [sort @gotHashRefKeys], [sort @expectedHashKeys], 'Module +Hash Keys are Identical' ); cmp_deeply( $hashRefOutput, $hashRefExpected, 'Exptected Output From t +he Module Received' ); ok( my ( $errorForExtraHashKey , $hashRefOutputForExtraHashKey ) = get +SNTPTime( %hashInputModuleTestExtraKeysInserted ), 'Faulty Test Extra + Key' ); ok( $errorForExtraHashKey eq 'Not defined key(s)', 'Correct Output Err +or Extra Hash Key' ); ok( my ( $errorNoHostname , $hashRefOutputNoHostName ) = getSNTPTime( +%hashInputModuleTestNoHostName ), 'Faulty Test no Hostname' ); ok( $errorNoHostname eq 'Not defined Hostname', 'Correct Output Error +No Hostname' ); ok( my ( $errorNegativePortNumber , $hashRefOutputNegativePortNumber ) + = getSNTPTime( %hashInputModuleTestNegativePortNumber ), 'Faulty Tes +t Negative Port Number' ); ok( $errorNegativePortNumber eq 'Not correct port number', 'Correct Ou +tput Error for Negative Port Number' ); ok( my ( $errorOutOfRangePortNumber , $hashRefOutputOutOfRangePortNumb +er ) = getSNTPTime( %hashInputModuleTestOutOfRangePortNumber ), 'Faul +ty Test Out of Range Port Number' ); ok( $errorOutOfRangePortNumber eq 'Not correct port number', 'Correct +Output Error Out of Range Port Number' ); use Data::Dumper; #print Dumper $hashRefOutputNegativePortNumber; #print "Error: " . $errorNegativePortNumber . "\n"; ######################### # Insert your test code below, the Test::More module is use()ed here s +o read # its man page ( perldoc Test::More ) for help writing this test scrip +t.

Although the test cases that are failing are 2 out of 15 I tried to fix them because the error is really simple. I have commended the fix, but still the error is not stopping to appear. Where I am going so wrong?

Thank you in advance for your time and effort to assist me.

Seeking for Perl wisdom...on the process of learning...not there...yet!

Replies are listed 'Best First'.
Re: Failed test of Net::SNTP::Client module
by Corion (Patriarch) on Jul 06, 2015 at 07:05 UTC

    Instead of using ok(), I like to use is() or diag() from Test::More, because they always also output the offending values when a test failure occurs. That helps me to narrow down the causes of test failures.

      Hello Corion,

      Thank you for your time and effort reading and replying to my question. You are absolutely right, I should use is() instead of ok().

      From documentation ( Test::More ):

      So why use these? They produce better diagnostics on failure. ok() cannot know what you are testing for (beyond the name), but is() and isnt() know what the test was and why it failed.

      Thanks for the tip.

      Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: Failed test of Net::SNTP::Client module
by stevieb (Canon) on Jul 05, 2015 at 23:22 UTC

    Test cases should always be run from within the module root directory to simulate exactly how CPAN testers does it (ie, the directory that t/ is in: perl t/Net-SNTP-Client.t), especially when using file names and paths as your test data.

    It looks like your module might be creating the hash key from a relative directory path or script name, so try changing this line:

    'Net-SNTP-Client.t' => {

    to:

    't/Net-SNTP-Client.t' => {

    in the test and see if that fixes it.

    -stevieb

      Hello stevieb,

      This is was my first thought also, to add the t/ indicate the directory. I was not quite sure if this was the correct way of solving the problem or not but it seems it worked fine. The only modification that I had to apply was to put the keys in correct order also. Any way details seems to be working just fine. ;)

      Thank you for your time and effort.

      Seeking for Perl wisdom...on the process of learning...not there...yet!

        Indeed, it was the correct fix. The test itself was faulty in this case. I do see now that you were using the script name as a key in the hash ($0 => {), so from the module's perspective when running the tests within the root dir, it would for certain have the t/ prepended to it.

Re: Failed test of Net::SNTP::Client module
by kcott (Archbishop) on Jul 06, 2015 at 11:02 UTC

    G'day thanos1983,

    "So first thing first. The module code if someone want to test it can be found here RFC: Net::SNTP::Client v1."

    That link has two problems (which you should fix):

    1. It doesn't link to "RFC: Net::SNTP::Client v1" at all. In fact, it links to The Monastery Gates! So, at this point, nobody can see the code, let alone test it (sure, we could spend time searching for it, but we shouldn't have to).
    2. It's an absolute link to 'http://perlmonks.com/?' — anyone following it stands a good chance of being logged out. Don't use absolute links, use relative links. See "All Links Within PerlMonks Should Be Relative" for both the reason why and how to do this.
    "I was following the instructions from How to make a CPAN Module Distribution ..."

    [That's also an absolute link, so please fix it as well.]

    "How to make a CPAN Module Distribution" is thirteen (13) years old: I'm not suggesting there's wrong information there, it's just old information. It shows three methods: h2xs, ExtUtils::ModuleMaker and Module::Starter: you haven't said which one you're using. Take a look at "perlnewmod: Perl modules: preparing a new module for distribution" — this forms part of the core Perl distribution and should be (more) current.

    "I have post several questions over and over ..."

    In one of these (Undefined subroutine &main [SOLVED]), you said you had installed Module::Starter and thought it was causing the errors (described in that thread) but, as it turned out, it had nothing to do with those errors. I recommend you go back to using Module::Starter: it does a lot of the work for you including, via your chosen plugin, creating a distribution bundle suitable for uploading to CPAN.

    I've been using Damian Conway's Module::Starter::PBP plugin for about eight years. I've used it successfully in large commercial contracts and for smaller, personal (hobby) projects. While I'm happy to recommend it, I certainly don't insist you use it: there's other Module::Starter Plugins which you may find preferable.

    "I am trying to install the module manually ..."

    I think you're completely jumping the gun doing this. At its most basic, my typical workflow is:

    1. perl Makefile.PL make make test
    2. Add/Change/Delete module/test code.

      make realclean

      Go to 1.

    That cycle will repeat many, many times before I get to 'make dist' or 'make install'.

    -- Ken

      Hello kcott,

      Thank you for your time and effort reading and replying to all my mistakes. I have updated the links to relative ones, as correctly pointed out to me.

      Thank you for the information links that you provide me with, I founded them really useful.

      One last question though, every time that I am rebuilding/reinstalling my written module should I repeat the Module::Starter process?

      What I mean is, let's assume that I have unistalled my module (Net::STNP::Client) and I want to install it again before I post it on CPAN do I need to repeat the Module::Starter process even though I have done it before?

      Update Ignore this question I figure it out the answer by my self from the document Module::Starter:

      Module::Starter is used to create a skeletal CPAN distribution, including basic builder scripts, tests, documentation, and module code.

      Apologies for the late reply I had to leave for some hours.

      Seeking for Perl wisdom...on the process of learning...not there...yet!