Changeset 7279


Ignore:
Timestamp:
04/28/10 07:58:58 (2 years ago)
Author:
MichaelTempest
Message:

Item1326: Ensure that each selenium-based test object (including the first to run) is destroyed after the test has run

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UnitTestContrib/test/unit/FoswikiSeleniumTestCase.pm

    r7246 r7279  
    1515use Error qw( :try ); 
    1616use Encode; 
     17use Scalar::Util qw( weaken ); 
    1718 
    1819my $startWait; 
     
    4142my $browsers; 
    4243my @BrowserFixtureGroups; 
     44my $currentTest; 
    4345 
    4446my $debug = 0; 
    45  
    46 my $instance_count = 0; 
    4747 
    4848sub new { 
     
    5050    my $this  = $class->SUPER::new(@_); 
    5151 
    52     $instance_count++; 
     52    if (defined $currentTest) { 
     53        $this->assert(0, 
     54            "There may only be one FoswikiSeleniumTestCase-based test\n" 
     55            . "running in each test process.\n" 
     56            . "Cannot run the $class test \n" 
     57            . "because the $currentTest is still running."); 
     58    } 
     59    $currentTest = $this; 
     60    weaken($currentTest); # Ensure the destructor is called at the normal time 
    5361 
    5462    $this->{selenium_timeout} = 30_000; # Same as WWW::Selenium's default value 
     
    6371END { 
    6472    _shutDownSeleniumBrowsers() if $browsers; 
     73} 
     74 
     75sub DESTROY { 
     76    my $this = shift; 
     77    if (not defined($currentTest) or $currentTest != $this) { 
     78        $this->assert(0, 
     79            "Unexpected change of current test:" 
     80          . "Expected $this but found $currentTest"); 
     81    } 
     82    $this->SUPER::DESTROY if $this->can('SUPER::DESTROY'); 
    6583} 
    6684 
     
    130148                $config{browser_url} ||= $Foswiki::cfg{DefaultUrlHost}; 
    131149 
    132                 $config{error_callback} = sub { $this->assert(0, join(' ', @_)); }; 
     150                # The error callback needs a reference to the current test 
     151                # object. There may be several test objects that use the 
     152                # selenium interface, so the error callback cannot be a  
     153                # closure (anonymous sub) that uses $this (because $this 
     154                # in a closure would always refers to the first test 
     155                # to run that is derived from FoswikiSeleniumTestCase). 
     156                # Instead, the error callback uses a static class variable 
     157                # that is set (and weakened) in the constructor. 
     158                $config{error_callback} = \&_errorCallback; 
    133159 
    134160                my $selenium = Test::WWW::Selenium->new( %config ); 
    135161                if ($selenium) { 
    136162                    $browsers->{$browser} = $selenium; 
     163                } 
     164                else { 
     165                    $this->assert(0, "Could not create a Test::WWW::Selenium object for $browser"); 
    137166                } 
    138167            } 
     
    152181 
    153182    return $browsers; 
     183} 
     184 
     185sub _errorCallback { 
     186    if ($currentTest) { 
     187        $currentTest->assert(0, join(' ', @_)); 
     188    } 
     189    else { 
     190        die "A Test::WWW::Selenium class reported an error, " 
     191          . "but the associated test-case object has " 
     192          . "already been destroyed. The error is:\n" 
     193          . join(' ', @_); 
     194    } 
    154195} 
    155196 
Note: See TracChangeset for help on using the changeset viewer.