in reply to Re: Testing image output
in thread Testing image output

Thanks hippo

I've used md5_hex from Digest::MD5 and checked it is installed as I've required Perl 5.010

Could I please have some feedback on this test file as testing is not my strongest skill...

#!perl use 5.010; use strict; use warnings; use Test::More; eval "use Digest::MD5 qw(md5_hex)"; plan skip_all => "Skipping tests: Digest::MD5 qw(md5) not available!" +if $@; plan tests => 11; use Image::Square; # Hashes of visually tested images my %hash = ( 'hor_square' => '370f26d5fbc52ae93b1bd0928e38cd24', 'hor_left' => '807f6263746b7646f172b7b0928d9195', 'hor_right' => '65672407acff93b188d24bc9b0003bd7', 'ver_square' => 'c9958ec55ef446c41fdecb71b2c69d09', 'ver_top' => '024a3f36e32f1ad193e761b315e7be4c', 'ver_bottom' => 'aea5e4120e8459b226ea003a0d57a2b4', ); # Test horizontal iamge my $image = Image::Square->new('t/CoventryCathedral.jpg'); ok ($image, 'Instantiation'); diag('Testing horizontal image'); my $square1 = $image->square(); my $square2 = $image->square(100); my $square3 = $image->square(150, 0); my $square4 = $image->square(150, 1); ok ($square1->width == $square1->height, 'Image is square from horizon +tal'); ok ( 100 == $square2->width && 100 == $square2->height, 'Correct resiz +e from horizontal'); ok ( md5_hex($square2->jpeg(50)) eq $hash{'hor_square'}, 'Correct cent +re image from horizontal'); ok ( md5_hex($square3->jpeg(50)) eq $hash{'hor_left'}, 'Correct left i +mage from horizontal'); ok ( md5_hex($square4->jpeg(50)) eq $hash{'hor_right'}, 'Correct right + image from horizontal'); # Test vertical iamge $image = Image::Square->new('t/decoration.jpg'); diag('Testing vertical image'); my $square5 = $image->square(); my $square6 = $image->square(100); my $square7 = $image->square(150, 0); my $square8 = $image->square(150, 1); ok ($square5->width == $square5->height, 'Image is square from vertica +l'); ok ($square6->width == 100 && $square6->height == 100, 'Correct resize + from vertical'); ok ( md5_hex($square6->jpeg(50)) eq $hash{'ver_square'}, 'Correct cent +re image from vertical'); ok ( md5_hex($square7->jpeg(50)) eq $hash{'ver_top'}, 'Correct top ima +ge from vertical'); ok ( md5_hex($square8->jpeg(50)) eq $hash{'ver_bottom'}, 'Correct bott +om image from vertical'); done_testing;

Replies are listed 'Best First'.
Re^3: Testing image output
by eyepopslikeamosquito (Archbishop) on Sep 08, 2023 at 14:37 UTC

    Could I please have some feedback on this test file as testing is not my strongest skill

    I pulled a face the instant I saw all those ok functions! From Basic Testing Tutorial by hippo:

    While the ok function is useful, the output is a simple pass/fail - it doesn't say how it failed ... Let's use Test::More and its handy cmp_ok function

    To convince yourself this is a worthwhile change, try running some failing test cases with your original ok and compare with cmp_ok.

      Thanks for the bedtime reading...that might improve my abilities with Test::More 👍

      To convince yourself this is a worthwhile change, try running some failing test cases with your original ok and compare with cmp_ok.

      I would take up your suggestion eyepopslikeamosquito but the tests don't fail for me...I would need to upload another dev release to CPAN and wait for some CPAN Testers to generate some results for me. There seem to be precious few testers these days as tests are getting longer and longer before they arrive. I don't want to unnecessarily burden those that are doing this sterling work!

      To convince yourself this is a worthwhile change, try running some failing test cases with your original ok and compare with cmp_ok

      I took this advice...
      As expected, I get a more verbose output.

      But, I don't see how it is any more helpful:

      # Testing horizontal image # Failed test 'Correct centre image from horizontal' # at t/02-image.t line 41. # got: '33220702a62b38deb37ef0ce0b4a1a22' # expected: 'c97e63fc792ef75b5ff49c078046321e' # Failed test 'Correct left image from horizontal' # at t/02-image.t line 43. # got: '4a0e69414c9603b0437d22841ef0d300' # expected: '20a5c6517316ebef4c255c12f991dbc7'

        It is (arguably) more helpful because you now have this extra information:

        1. The computed string (the "got") actually looks like a digest of the right length and the right alphabet. This tells you that the code producing that string is performing the right action, just on the wrong source data. Before, the string could have been "" or "aaaaa" or "I can haz cheeseburger" for all you knew.
        2. The computed and expected strings are entirely different, not just say one character out so you have not introduced a typo in the expected string.

        You now have more confidence that the underlying problem is indeed that the source data for the digest is not what it should be, rather than some issue elsewhere in your code or your test script.


        🦛

Re^3: Testing image output
by Anonymous Monk on Sep 08, 2023 at 10:48 UTC

    It won't work as written. Neither coders nor decoders are stable.

    Does your module (can't find it on CPAN) inherit from GD (judging by width/height/jpeg methods)? It doesn't matter in the end, I only hope you force it to treat jpegs as truecolor on open, because it doesn't despite whatever its doco says. If GD converts jpeg to palette, it will be even more mess to add to description below -- looks like GD tunes this algo (true to palette quantization) more frequently, then no need to go as far back as 5.010 to demonstrate.

    Frog is frog

    use strict; use warnings; use feature 'say'; use GD; use Digest::MD5 'md5_hex'; say $^V; say $GD::VERSION; my $f = 'frog.jpg'; GD::Image-> trueColor( 1 ); my $i = GD::Image-> new( $f ); say "Image is ", ( $i-> isTrueColor ? '' : 'not ' ), 'truecolor'; printf "RGB triplet for 0,0 pixel is: %3\$d, %2\$d, %1\$d\n", unpack 'C3', pack 'L', $i-> getPixel( 0, 0 ); __END__ v5.32.1 2.76 Image is truecolor RGB triplet for 0,0 pixel is: 0, 248, 231 v5.10.1 2.44 Image is truecolor RGB triplet for 0,0 pixel is: 0, 247, 231

    Blame ancient GD version? But

    >convert frog.jpg -format "%[pixel:u.p{0,0}]\n" info: srgb(0,247,231)

    I'd say lossy codecs are murky waters and avoid them in tests:

    >convert frog.jpg frog.png

    use strict; use warnings; use feature 'say'; use GD; use Digest::MD5 'md5_hex'; say $^V; say $GD::VERSION; my $f = 'frog.png'; GD::Image-> trueColor( 1 ); my $i = GD::Image-> new( $f ); say "Image is ", ( $i-> isTrueColor ? '' : 'not ' ), 'truecolor'; say md5_hex( $i-> png() ); __END__ v5.32.1 2.76 Image is truecolor 1b6edecaa6d0b67f7bf960113f2136c7 v5.16.3 2.49 Image is truecolor 9edf3f9e11991f2dcfd77a7e1ffbafe8

    Eh? What's the matter now? My first thought was zlib tunes its compression algo (despite same "level" 0..10), but it's not the reason for difference above -- though I strongly suspect it can influence the result for some input other than puny frog. But, above, it's just pHYs chunk that libpng decides to include from some version on.

    Then, what it all amounts to -- try stable (read: "obsolete") lossless coder with uncompressed output (GD can't dump raw pixels, unfortunately), short of enumerating pixels one by one and adding RGB to string. Hopefully it's OK now:

    use strict; use warnings; use feature 'say'; use GD; use Digest::MD5 'md5_hex'; say $^V; say $GD::VERSION; my $f = 'frog.png'; GD::Image-> trueColor( 1 ); my $i = GD::Image-> new( $f ); say "Image is ", ( $i-> isTrueColor ? '' : 'not ' ), 'truecolor'; say md5_hex( $i-> gd() ); __END__ v5.32.1 2.76 Image is truecolor e60c6afd7eefe80050d6af4488457281 v5.16.3 2.49 Image is truecolor e60c6afd7eefe80050d6af4488457281 v5.10.1 2.44 Image is truecolor e60c6afd7eefe80050d6af4488457281
      Neither coders nor decoders are stable

      Do you mean the hashing coder/decoder or the image format?

      Does your module (can't find it on CPAN) inherit from GD (judging by width/height/jpeg methods)?

      Yes, it does use GD. It doesn't inherit from it.

      You can't find it on CPAN because it is still in development release. Although the module works under all visual testing, I wanted to get it working with a complete test suite before releasing it publicly.

      Yes, the module does use GD::Image-> trueColor( 1 ); and the tests specify $new->jpeg(50) rather than leaving GD to choose the best compression (whatever that means) as the docs say it does. I stayed away from PNG as I know that the exact behaviour of that depends on how GD was built, something that will vary on target machines.

      I hadn't thought of using a GD object to perform the comparison...obvious really...thanks...

        GD image file format[1] is not an "object", just dumb data stored externally, same as PNG, JPG, TIF, etc. I now see the module on CPAN. Not sure if it's worth re-iterating, what I suggested was no JPGs in t folder, because same image file can't be expected to decode to same data. Neither $new->jpeg(50) is reliable:

        v5.32.1 2.76 d0116830c00ed65dbebfd53afec1dcd0 v5.16.3 2.49 a26bc180a0f0067e00788dee47975324

        for CoventryCathedral.jpg source, because (1) comment segments are

        CREATOR: gd-jpeg v1.0 (using IJG JPEG v90), quality = 50 CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), quality = 50

        respectively, and (2) APP0 segment stores aspect ratio for the former, vs. dots-per-inch resolution for the latter, for no obvious reason. +Of course I meant image coders/decoders.

        1: https://libgd.github.io/manuals/2.3.3/files/gd_gd-c.html