Selenium
and
Perl

by Eric Johnson (@kablamo)

What is Selenium?

  • A tool for testing your website
  • Written in Java
  • Similar to Test::WWW::Mechanize
  • But tests at the browser level
  • Tests closer to the real user experience
  • Exercises your JavaScript
  • Tests your site in any browser

Selenium IDE

  • Firefox plugin
  • Designer can create tests
  • Records your actions in the browser
  • Replays them

Demo

Problems

  • Unreliable tests
  • It's not Perl
  • Repetition: can't easily use libraries
  • Lack of automation

Unreliable tests

    Problem

    waitForPageToLoad does not handle ajax requests

    Solution

    waitForTextPresent

Problems

  • Unreliable tests
  • It's not Perl
  • Repetition: can't easily use libraries
  • Lack of automation

Test::WWW::Selenium

4 ingredients

  1. Perl test
  2. Selenium server
  3. Web browser
  4. Website
use Test::Most;
use Test::WWW::Selenium;

my $s = Test::WWW::Selenium->new( 
    host           => "localhost",
    port           => 4444,
    browser        => "*firefox",
    browser_url    => "http://localhost:5000",
);

$s->open_ok("/index.tt");
$s->wait_for_page_to_load_ok;
$s->type_ok(searchInput => "cat pictures");
$s->click_ok("searchButton");
$s->wait_for_page_to_load_ok;
$s->is_text_present_ok('2 bajillion results');

done_testing;
use Test::Most;
use Test::WWW::Selenium;

my $s = Test::WWW::Selenium->new( 
    host           => "localhost",
    port           => 4444,
    browser        => "*firefox",
    browser_url    => "http://localhost:5000",
);

$s->open_ok("/index.tt");               sleep 2;
$s->wait_for_page_to_load_ok;           sleep 2;
$s->type_ok(searchInput => "cat pics"); sleep 2;
$s->click_ok("searchButton");           sleep 2;
$s->wait_for_page_to_load_ok;           sleep 2;
$s->is_text_present_ok('2 bajillion results');

done_testing;

Problems

  • Unreliable tests
  • It's not Perl
  • Repetition: can't easily use libraries
  • Designers can't easily write tests
  • Lack of automation
use Test::Most;
use Test::WWW::Selenium;

my $s = Test::WWW::Selenium->new( 
    host           => "localhost",
    port           => 4444,
    browser        => "*firefox",
    browser_url    => "http://localhost:5000",
);

$s->open_ok("/index.tt");
$s->wait_for_page_to_load_ok;
$s->type_ok(searchInput => "cat pictures");
$s->click_ok("searchButton");
$s->wait_for_page_to_load_ok;
$s->is_text_present_ok('2 bajillion results');

done_testing;
use Test::Most;
use MySelenium;

my $s = MySelenium->new;

$s->open_ok("/index.tt");
$s->wait_for_page_to_load_ok;
$s->type_ok(searchInput => "cat pictures");
$s->click_ok("searchButton");
$s->wait_for_page_to_load_ok;
$s->is_text_present_ok('2 bajillion results');

done_testing;
package MySelenium;
use Moose;
extend 'Test::WWW::Selenium'; 

Unfortunately

Moose cannot extend non Moose libraries

Fortunately

MooseX::NonMoose can extend non Moose libraries
package MySelenium;
use Moose;
use MooseX::NonMoose;
extend 'Test::WWW::Selenium'; 

Unfortunately

MooseX::NonMoose does not work on parents that use AUTOLOAD

Problems

  • Unreliable tests
  • It's not Perl
  • Test::WWW::Selenium dislikes Moose
  • Repetition: can't easily use libraries
  • Designers can't easily write tests
  • Lack of automation

Fortunately

Test::WWW::Selenium::More
package MySelenium;
use Moose;
extends 'Test::WWW::Selenium::More';

has host        => (...);
has port        => (...);
has browser     => (...);
has browser_url => (
    is      => 'rw', 
    isa     => 'Str',
    default => 'http://localhost:5000'
);

no Moose; 
use Test::Most;
use MySelenium;

my $s = MySelenium->new;

$s->note('Are there enough cat pictures?');
$s->open_ok("/index.tt");
$s->type_ok(searchInput => "cat pictures");
$s->click_ok("searchButton");
$s->wait_for_page_to_load_ok;
$s->is_text_present_ok('2 bajillion results');

done_testing;
use Test::Most;
use MySelenium;

my $s = MySelenium->new;

$s->note('Are there enough cat pictures?');
$s->open_ok("/index.tt");
$s->type_ok(searchInput => "cat pictures");
$s->click_ok("searchButton");
$s->wait_for_page_to_load_ok;
$s->is_text_present_ok('2 bajillion results');

$s->note('Check results as a logged in user');
$s->login_ok('bob'); # not in the Selenium API
$s->is_text_present_ok('2 bajillion results');

done_testing; 
package MySelenium;
use Moose;
extends 'Test::WWW::Selenium::More';

has host        => (...);
has port        => (...);
has browser     => (...);
has browser_url => (is  => 'rw', isa => 'Str', 
      default => 'http://localhost:5000');

sub login_ok {
    my ($self, $username, $password) = @_;
    $self->open_ok('/login.tt');
    $self->type_ok(username => $username);
    $self->type_ok(password => $password);
    $self->click_ok('login');
}

no Moose;
package MySelenium;
use Moose;
extends 'Test::WWW::Selenium::More';
with 'MySelenium::Roles::Authentication';

has host        => (...);
has port        => (...);
has browser     => (...);
has browser_url => (
    is      => 'rw', 
    isa     => 'Str', 
    default => 'http://localhost:5000'
);

no Moose; 
package MySelenium;
use Moose;
extends 'Test::WWW::Selenium::More';
with 'MySelenium::Roles::Authentication';
with 'MySelenium::Roles::Payments';
# etc

has host        => (...);
has port        => (...);
has browser     => (...);
has browser_url => (
    is      => 'rw', 
    isa     => 'Str', 
    default => 'http://localhost:5000'
);

no Moose; 

Problems

  • Unreliable tests
  • It's not Perl
  • Test::WWW::Selenium dislikes Moose
  • Repetition: can't easily use libraries
  • Designers can't easily write tests
  • Lack of automation

Test::WWW::Selenium::More

Method chaining
use Test::Most;
use MySelenium;

MySelenium->new

  ->note('Are there enough cat pictures?')
  ->open_ok("/index.tt")
  ->type_ok(searchInput => "cat pictures")
  ->click_ok("searchButton")
  ->wait_for_page_to_load_ok
  ->is_text_present_ok('2 bajillion results')

  ->note('Check results as a logged in user')
  ->login_ok('bob') # not in the Selenium API
  ->is_text_present_ok('2 bajillion results');

done_testing; 

Problems

  • Unreliable tests
  • It's not Perl
  • Test::WWW::Selenium dislikes Moose
  • Repetition: can't easily use libraries
  • Designers can't easily write tests
  • Lack of automation

Jenkins

  • Written in Java
  • cron with a web interface and features
  • The moose dev team uses it

Problems

  • Unreliable tests
  • It's not Perl
  • Test::WWW::Selenium dislikes Moose
  • Repetition: can't easily use libraries
  • Designers can't easily write tests
  • Lack of automation

THE END

Links

Test::WWW::Selenium::More

http://github.com/kablamo/Test-WWW-Selenium-More

Selenium reference (locators + api)

http://cavaliere.org/sandbox/selenium_api_reference

This talk

http://kablamo.org/selenium-2012-yapceu-slides

Kablamo

http://kablamo.org

Bonus slide

Test your website
on multiple browsers/operating systems
using virtual machines in your browser
for free
https://saucelabs.com