Beefy Boxes and Bandwidth Generously Provided by pair Networks Cowboy Neal with Hat
Perl: the Markov chain saw
 
PerlMonks  

Test::More not working with Perl local special variables

by Doozer (Beadle)
on Apr 22, 2013 at 18:18 UTC ( #1029948=perlquestion: print w/ replies, xml ) Need Help??
Doozer has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I am using Test::More along with WWW::Selenium to automate some router GUI browsing. One thing I am trying to do is use Test::More's "like" function to check that certain contents on the web page match a regular expression.

For example I want run the contents of a web element where the router's wireless SSID is shown against a regex and then print the match so the code would look something like:

like($sel->get_value("name=wlSsid_wl0v0"), qr/\S{1,}/, "1000.0362 SSID was displayed on the wireless settings page \($&\)");

I would like to be able to use the various local special variables in perl such as $& and $1,$2 etc so that I can print what the script finds against the regex pattern match, but they dont seem to work. I'm guessing this a localisation issue? Any help would be much appreciated and I can provide more info if needed.

Comment on Test::More not working with Perl local special variables
Download Code
Re: Test::More not working with Perl local special variables
by space_monk (Chaplain) on Apr 22, 2013 at 19:13 UTC

    The $& in the string (last parameter) is evaluated at the time of the call to like, whereas the regex comparison is performed within the method, so using the local variables in the way you have described is doomed to failure.

    Looking at the code, the name parameter is passed through a couple of methods to Test::Builder::_regex_ok, so I don't think you can escape the string up a few levels either.

    If any of my proposed solutions have minor errors, it's because I don't waste my genius on trivial matters. :-P
Re: Test::More not working with Perl local special variables
by tobyink (Abbot) on Apr 22, 2013 at 19:13 UTC

    This is a timing thing. Your double-quoted string "1000.0362 SSID was displayed on the wireless settings page \($&\)" is interpolated before like is called; then the regexp match happens inside the like call.

    So when the interpolation happens, $& is still undefined.

    The following might work:

    like($sel->get_value("name=wlSsid_wl0v0"), qr/\S{1,}/, "1000.0362 SSID + was displayed on the wireless settings page") and diag("got: $&");
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
      Thank you for the responses on this. I had a bad feeling I wasn't going to be able to use them in this way. I tried tobyink's suggestion but it still doesn't work. I think I can work around it but it turns 1 line of code in to about 6. Thanks again :)
Re: Test::More not working with Perl local special variables
by AnomalousMonk (Monsignor) on Apr 22, 2013 at 19:26 UTC

    It's a dynamic scoping issue:

    >perl -wMstrict -le "my $s = 'foobar'; printf qq{\$& in sub: '%s' \n}, S($s); print qq{\$& post sub: '$&'}; print '$& undefined' unless defined $&; ;; sub S { $_[0] =~ m{ oob }xms; return $&; } " $& in sub: 'oob' Use of uninitialized value $& in concatenation (.) or string at ... $& post sub: '' $& undefined

    See the section Variables related to regular expressions in perlvar: "These variables are read-only and dynamically-scoped, unless we note otherwise."

Re: Test::More not working with Perl local special variables
by Doozer (Beadle) on Apr 23, 2013 at 07:55 UTC
    Just thought I would follow this up with my alternative solution to this (for anyone who is curious or has a similar issue).

    After reading more on Test::More I decided to use the pass and fail functions instead. This means I can do a normal if statement with the regex pattern matching and pass $1 or $& into them instead. For example:

    if ($sel->get_value("name=wlSsid_wl0v0") =~ /(\S{1,})/) { pass("1000.0362 SSID - $1 - was displayed on the wireless settings pag +e"); } else { fail("1000.0362 SSID - $1 - was displayed on the wireless settings pag +e"); }

    It's a bit more clunky but does the job nicely.

      What do you expect $1 will contain in the else branch?
      لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        That was a quick copy/paste job and I didn't realize. Obviously $1 will be undefined so the else statement will be adjusted accordingly. I will keep the rest of the statement the same as that will be what helps identify each test.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1029948]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (7)
As of 2014-04-19 08:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (478 votes), past polls