The Test::WWW::Selenium does a good integration of Selenium with Perl testing framework. However by default, tests runs in sequence. One easy solution is to use the Thread::Pool::Simple module to run the test functions in parallel. Short testing showed that this parallel version ran for 19 seconds vs 39 seconds for the serial run.
#!/usr/bin/env perl
use Thread::Pool::Simple;
use Test::More "no_plan";
use Test::WWW::Selenium;
sub test_page() {
my ($url, $input, $button) = @_;
my $sel = Test::WWW::Selenium->new(
host => "localhost",
port => 4444,
browser => "*firefox",
browser_url => $url,
);
$sel->open($url);
$sel->type_ok($input, "Sauce Labs");
$sel->click_ok($button);
$sel->wait_for_page_to_load_ok(5000);
$sel->body_text_like(qr/Selenium/);
$sel->close();
}
sub test_google() {
&test_page("http://google.com", "q", "btnG");
}
sub test_yahoo() {
&test_page("http://yahoo.com", "p", "search-submit");
}
sub test_bing() {
&test_page("http://www.bing.com", "q", "go");
}
sub worker() {
my $func = shift;
# We can't pass CODE items to a pool, so we use eval
eval("&$func();");
}
my @names = (
"test_google",
"test_yahoo",
"test_bing",
);
my $pool = Thread::Pool::Simple->new(
min => 3,
max => 10,
do => [\&worker],
);
foreach $name (@names) {
print "Adding $name\n";
$pool->add($name);
}
$pool->join();
Converting the code to work with Sauce OnDemand is a breeze as well, we will also use the job-name
attribute to assign name for our jobs.
#!/usr/bin/env perl
use Thread::Pool::Simple;
use Test::More "no_plan";
use Test::WWW::Selenium;
# Replace username and access-key with your real
# Sauce OnDemand username and access-key
my $settings = qq(
{
"username" : "YOUR-SAUCE-USER-NAME",
"access-key" : "YOUR-SAUCE-ACCESS-KEY",
"os" : "Linux",
"browser" : "firefox",
"browser-version" : ""
"job-name" : "_JOB_NAME_"
}
);
sub test_page() {
my ($name, $url, $input, $button) = @_;
my $opts = $settings;
$opts =~ s/_JOB_NAME_/$name/; # Add job name
my $sel = Test::WWW::Selenium->new(
host => "ondemand.saucelabs.com",
port => 80,
browser => $opts,
browser_url => $url,
);
$sel->open($url);
$sel->type_ok($input, "Sauce Labs");
$sel->click_ok($button);
$sel->wait_for_page_to_load_ok(5000);
$sel->body_text_like(qr/Selenium/);
$sel->close();
}
sub test_google() {
&test_page("Google", "http://google.com", "q", "btnG");
}
sub test_yahoo() {
&test_page("Yahoo", "http://yahoo.com", "p", "search-submit");
}
sub test_bing() {
&test_page("Bing", "http://www.bing.com", "q", "go");
}
sub worker() {
my $func = shift;
# We can't pass CODE items to a pool, so we use eval
eval("&$func();");
}
my @names = (
"test_google",
"test_yahoo",
"test_bing",
);
my $pool = Thread::Pool::Simple->new(
min => 3,
max => 10,
do => [\&worker],
);
foreach $name (@names) {
print "Adding $name\n";
$pool->add($name);
}
$pool->join();