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

Hi Monks ! I am on a learning curve with Perl. I am trying to compare Screenshot between two different browsers for a same image ,in some Test. All is ok. I'am using Selenium::Screenshot and Test::Class modules. But when i would like to compare my screenshots outside of a loop, i have some issues. Here code i did:
sub Login_test : Tests { my $self = shift; foreach my $browser (@{$self->{browsers}}) { diag ("#browser $browser"); my $driver = Test::Selenium::Remote::Driver->new( browser_name => +$browser); $driver->get_ok("$url","Get url ok"); $driver->pause(2000); $driver->set_window_size(600, 600); $driver->pause(2000); my $white = Selenium::Screenshot->new( png => $driver->screenshot, exclude => [{ size => { width => 100, height => 100 }, # s +ize => $elem->get_size, location => { x => 5, y => 5 }, #location => $el +em->get_element_location, }] ); $driver->find_element('login','id')->send_keys("ok"); $driver->find_element('password','id')->send_keys("okok"); $elem = $driver->find_element('login','id'); $driver->mouse_move_to_location(element => $elem); $driver->click_ok('Click on Button submit ok'); $driver->pause(5000); $white->save( file => "snapScreenshot-$browser" ); #$driver->execute_script('document.getElementsByTagName("body")[0] +.style.backgroundColor = "red"'); my $blue = Selenium::Screenshot->new(png => $driver->screenshot); $blue->save( file => "snapScreenshot1-$browser" ); $elem = $driver->find_element('//a[@href="/logout"]'); $driver->mouse_move_to_location(element => $elem); $driver->click_ok('Logout ok'); $driver->pause(3000); $driver->quit(); } unless ($white{browser_name => $browser[0]}->compare($blue{browser_n +ame => $browser[1]})) { $diff_file = $white->difference($blue); print '#The images differ; see ' . $diff_file . ' for details'. "\ +n"; my $open_cmd; if ($^O eq 'darwin') { $open_cmd = 'open' } elsif ($^O eq 'MSWin32') { $open_cmd = ''; } else { $open_cmd = 'display'; } `$open_cmd $diff_file`; } }
And here my output in Shell :
Global symbol "%white" requires explicit package name at MyTest.pm lin +e 33. Global symbol "@browser" requires explicit package name at MyTest.pm l +ine 33. Global symbol "%blue" requires explicit package name at MyTest.pm line + 33. Global symbol "@browser" requires explicit package name at MyTest.pm l +ine 33. Global symbol "$diff_file" requires explicit package name at MyTest.pm + line 34. Global symbol "$blue" requires explicit package name at MyTest.pm line + 34. Global symbol "$diff_file" requires explicit package name at MyTest.pm + line 35. Global symbol "$diff_file" requires explicit package name at MyTest.pm + line 38.
What can i do ? Thanks !!
Lost in translation

Replies are listed 'Best First'.
Re: Recover a variable from a loop
by hippo (Archbishop) on May 26, 2016 at 08:31 UTC

    Declare them. If you don't know what the implications are of an error message you can always use diagnostics:

    $ perl -Mstrict -Mdiagnostics -e '$x=1;' Global symbol "$x" requires explicit package name at -e line 1. Execution of -e aborted due to compilation errors (#1) (F) You've said "use strict" or "use strict vars", which indicates + that all variables must either be lexically scoped (using "my" or +"state"), declared beforehand using "our", or explicitly qualified to say which package the global variable is in (using "::"). Uncaught exception from user code: Global symbol "$x" requires explicit package name at -e line 1 +. Execution of -e aborted due to compilation errors.
      Thanks for the tool. I thought about that but i already declare my variable in my loop. I just want to recover them in this code part
      unless ($white{browser_name => $browser[0]}->compare($blue{browser_na +me => $browser[1]})) { $diff_file = $white->difference($blue); print '#The images differ; see ' . $diff_file . ' for details'. "\ +n"; my $open_cmd; if ($^O eq 'darwin') { $open_cmd = 'open' } elsif ($^O eq 'MSWin32') { $open_cmd = ''; } else { $open_cmd = 'display'; } `$open_cmd $diff_file`; }
      Lost in translation
        but i already declare my variable in my loop

        No, you don't. You have not declared $diff_file in any part of the code which you have shown.

        unless ($white{browser_name => $browser[0]}->compare($blue{browser_name => $browser[1]})) {
           $diff_file = $white->difference($blue);
           print '#The images differ; see ' . $diff_file . ' for details'. "\n";
           ...
           }

        I don't understand what you're trying to do with an expression like $white{browser_name => $browser[0]}, but I doubt it's the right way to go.

        You're trying to use the old fashioned (pre-Perl 5) multidimensional array hack | emulation on the hash  %white which you have never declared. (Update: You're not accessing the  $white object reference.)

        c:\@Work\Perl\monks>perl -wMstrict -le "use Data::Dump qw(dd); ;; my %white; ;; my @bar = qw(bozzle); ;; $white{ foo => $bar[0] } = 'wibble'; dd \%white; " { "foo\34bozzle" => "wibble" }
        The  "foo\34bozzle" key in the dd dump is part of this old hack. See  $; in perlvar for some info on this. I'd like to give you a more complete reference, but I can't seem to find one ATM. (Anyone...?) (Update: Ok, there's this brief discussion on-line in perldata: Multi-dimensional array emulation.)


        Give a man a fish:  <%-{-{-{-<

Re: Recover a variable from a loop
by GrandFather (Saint) on May 26, 2016 at 08:36 UTC

    You use both $white-> and $white{...} (similarly for most of the other errors). The $white-> variant is using white as a scalar and the $white{...} variant is using white as a hash. You have either missed declaring the hash or, more likely, the second variant should be $white->{...}.

    Because you haven't given enough context it is impossible for us to tell which way around the code should be.

    The $diff_file error is fixed by prefixing the statement where it is assigned a value with my.

    Premature optimization is the root of all job security
      Oh ! It could be that, yes. I gave you all my sub . What does it miss for you ?
      Lost in translation
Re: Recover a variable from a loop
by Laurent_R (Canon) on May 26, 2016 at 08:40 UTC
    The errors you are getting are within the foreach loop, so they don't appear to have something to do with the loop itself or with scoping issues related to the loop.

    I do not know Selenium, but my best guess is that the Selenium::Screenshot->new constructor invocation did not return a defined object. Check whether $white is defined right after that constructor invocation. It seems likely you might have a problem there.

      Hello Laurent ! Concerning my constructor , it seems to work. When iam doing comparison within my loop , all is ok. Why i want to do comparison outside? Because i have to get all my browser' screenshots to be able to compare them. And my foreach return for each browser its screenshots. And if i want to compare 2 screenshots for 2 different browser, i think i have to do comparison outside loop.
      Lost in translation
        Then I have probably misunderstood your problem.

        But you report this error:

        Global symbol "%white" requires explicit package name at MyTest.pm lin +e 33.
        And, in the code that you have shown, line 33 is within the loop.

        If the code you show is not exactly the same as the one you run, it is difficult for us to figure out where exactly the error is occurring.

        Looking at it again, the error seems to be in:

        unless ($white{browser_name => $browser[0]} ...
        in which you use 'white' as a hash %white, not a scalar $white. Besides, $white has fallen out of scope anyway, so you would not be to access $white either, unless you had declared it before the start of the loop.
Re: Recover a variable from a loop
by Chaoui05 (Scribe) on May 26, 2016 at 09:39 UTC
    I add this part of code. Hope it will help
    use parent 'Test::Class'; use Test::Selenium::Remote::Driver; use Selenium::Screenshot; my $url ="http://localhost; sub start : Test( start => no_plan ) { my $self = shift; $self->{browsers} = [('firefox', 'internet explorer', 'chrome', 'ope +ra')]; }
    Lost in translation