Skip to content

Instantly share code, notes, and snippets.

View tourdedave's full-sized avatar

Dave Piacente tourdedave

  • Applitools
  • Takoma Park, MD
View GitHub Profile
<script src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="/js/waypoints.min.js"></script>
<script>
$(function() {
var promo = $('#promo'),
speed = 500; //speed in ms
$('.promo-hook').waypoint(function(direction){
if (direction === "down") {
promo.slideDown(speed);
@tourdedave
tourdedave / 3.md
Created February 19, 2014 23:09
Chapter 3 Rendered Example

Writing Your First Selenium Test

Fundamentally, Selenium works with two pieces of information -- the element on a page you want to use and what you want to do with it. This one-two punch will be repeated over and over until you achieve the outcome you want in your application -- at which point you will perform an assertion to confirm that the result is what you intended.

Let's take logging in to a website as an example. With Selenium you would:

  1. Visit the main page of a site
  2. Find the login button and click it
  3. Find the login form's username field and input text
  4. Find the login form's password field and input text

How To Reuse Your Test Code

One of the biggest challenges with Selenium tests is that they can be brittle and challenging to maintain over time. This is largely due to the fact that things in the app you're testing change, breaking your tests.

But the reality of a software project is that change is a constant. So we need to account for this reality somehow in our test code in order to be successful.

Enter Page Objects.

Rather than write your test code directly against your app, you can model the behavior of your application into simple objects -- and write your tests against them instead. That way when your app changes and your tests break, you only have to update your test code in one place to fix it.

Writing Resilient Test Code

Ideally, you should be able to write your tests once and run them across all supported browsers. While this is a rosy proposition, there is some work to make this a reliable success. And sometimes there may be a hack or two involved. But the lengths you must go really depends on the browsers you care about and the functionality you're dealing with.

By using high quality locators you will be well ahead of the pack, but there are still some persnickity issues to deal with. Most notably -- timing. This is especially true when working with dynamic, JavaScript heavy pages (which is more the rule than the exception in a majority of applications you'll deal with).

But there is a simple approach that makes up the bedrock of reliable and resilient Selenium tests -- and that's how you wait and interact with elements. The best way to accomplish this is through the use of explicit waits.

An Example

module Handler
extend self
attr_accessor :message
def speak
puts message
end
end
@tourdedave
tourdedave / 6.md
Last active August 29, 2015 13:57

Packaging For Use

In order to get the most out of our tests and page objects, we'll need to package them into a more useful structure.

Let's do that using the examples from the previous write-ups.

Global Setup And Teardown

First we'll need to pull the test setup and teardown actions out of our tests and into a central place. In RSpec this is straight-forward through the use of a 'spec_helper' file.

ENV['SAUCE_USERNAME'] = ''
ENV['SAUCE_API_KEY'] = ''
require 'selenium-webdriver'
describe 'Page Title' do
before(:each) do
browser_name = 'firefox'
browser_version = '27'
caps = Selenium::WebDriver::Remote::Capabilities.send(browser_name.to_sym)
@tourdedave
tourdedave / 7.md
Last active August 29, 2015 13:57

How To Scale Your Tests

If you've ever needed to test features in an older browser like Internet Explorer 8 then odds are you ran a virtual machine (VM) on your computer with a "legit" version of Windows XP.

Handy, but what happens when you need to check things on multiple versions of IE? Now you're looking at multiple VMs. And what about when you need to scale and cover other browser and Operating System (OS) combinations? Now you're looking at provisioning, running, and maintaining your own farm of machines and standing up something like Selenium Grid to coordinate tests across them.

And all you wanted to do was run your tests on the browsers you cared about...

Rather than take on the overhead of a test infrastructure you can easily outsource things to a third-party cloud provider -- like Sauce Labs

@tourdedave
tourdedave / 8.md
Last active August 29, 2015 13:57

Finding Information On Your Own

There is information all around us when it comes to Selenium. But it it can be challenging to sift through it, or know where to look.

Here is a list breaking down a majority of the Selenium resources available, and what they're useful for.

Documentation & Tips

Tying It All Together

You'll probably get a lot of mileage out of your test suite in its current form if you just run things from your computer, look at the results, and inform people on your team when there are issues. But that only helps you solve part of the problem.

The real goal in all of this is to find issues reliably, quickly, and continuously -- and ideally in sync with the development workflow you are a part of. In order to do that, we want to use a Continuous Integration (CI) server.

A Continuous Integration Primer

Continuous Integration (a.k.a. CI) is the practice of merging code that is actively being worked on into a shared mainline (e.g., trunk or master) as often as possible (e.g., several times a day). This is with the hopes of finding issues early and avoiding merging and integration issues that are not only considered a special kind of hell, but can dramatically slow the time it takes to release software.