Fork me on GitHub

WordPress-kehittäjä, älä missaa ilmaista webinaariamme Xdebugista elokuun 19. päivä!

WordPress-utvecklare, missa inte vår kostnadsfria webbinar om Xdebug den 19. augusti!

WordPress developer, don't miss our free webinar about Xdebug on August 19th!

Deprecated: The legacy Rspec-based test system described on this page has been replaced by our a new testing system based on headless Chrome and Codeception. This page is kept purely for historical reference and will be deleted later in 2019..

For more information see new testing system announcement at

What are integration tests?

Integration tests make sure that certain features of your site work as they should.

For example if we have the following use case:

  1. User visits and sees the login form.
  2. When user fills correct password and username he sees the WordPress dashboard including adminbar.

When the project is functional we will have the feature described above. Integration tests can be used to make sure that the feature works as described in the use case.

Testing with Rspec & Capybara

Our integration tests use a Ruby testing framework called Rspec with the extension Capybara.

We use the headless browser PhantomJS with the Ruby driver Poltergeist.

Using Ruby for testing a PHP application like WordPress may sound overwhelming but in our opinion it’s quite fun and effective. Our latest WordPress baseline template can be found in Github. It can be used as an example for your own unique tests.

Note: These tests are used in your production system as well (if available).

This way we can figure out if the site is still working after updates so that we can alarm you when something breaks and hand the updating process to be manually by the owner.

How to run these tests

You can use this command in Production and Vagrant box:

# Runs all tests in /data/wordpress/tests/rspec/*.rb
$ wp-test-legacy

Example tests

The following test suite consists of two describe blocks.

The first one tests that the front page is loaded correctly and has CSS styles. Then it clicks a link in the front page and expects the following page to contain text Archives.

The second one tests the use case we talked about in the beginning of this page.

# Use preconfigured Poltergeist/PhantomJS rules and load WP class
require_relative 'lib/config.rb'

### Begin tests ###

describe "WordPress: #{} - ", :type => :request, :js => true do

  subject { page }

  describe "frontpage" do

    before do
      visit WP.siteurl('/')

    it "Healthy status code 200" do
      expect(page).to have_status_of [200]

    it "Page includes stylesheets" do
      expect(page).to have_css

    it "After user clicks archive link, User should see archives" do
      click_link('October 2015')
      expect(page).to have_content 'Archives'

  describe "admin-panel" do

    before do
      visit WP.siteurl('/wp-login.php')

    it "There's a login form" do
      expect(page).to have_id "wp-submit"

    # Only try logging in if we could create a test user
    if WP.user?
      it "Logged in to WordPress Dashboard" do
        within("#loginform") do
          fill_in 'log', :with => WP.user.username
          fill_in 'pwd', :with => WP.user.password
        click_button 'wp-submit'
        # Should obtain cookies and be able to visit /wp-admin
        expect(page).to have_id "wpadminbar"


How to extend the tests

All files located in the path tests/rspec/*.rb will be executed. Instead of editing the existing baseline tests, we recommend creating new files for your own tests. Group the tests that test the same features and try to name the files logically to make it easier for your collaborators to debug or extend the tests later.

To try your new test, run it individually with verbose output:

rspec -f d new-test.rb

Rspec also has a profiling option available if you want to measure how long the test takes and potentially detect some execution time anomalies:

rspec -f d -p 10 new-test.rb

List of Helper functions

WP Helper module

These tests use the helper module WP which is included in the project.

# Returns url to your site for the following {path}
# @return string - url to your site

# Returns the hostname/domain which is defined for WordPress
# @return string - hostname of WordPress

# Check if a testuser was created successfully
# @return bool

# Returns the user object
# @return User object

# User has following attributes:
WP.user.username    # Username for the WordPress
WP.user.password    # Password for the WordPress
WP.user.firstname   # Test user firstname - by default: Test
WP.user.lastname    # Test user lastname - by default: Seravo       # Test user email - by default: testbotuser@{your-site}

List of Capybara functions

# Navigating

# Clicking links and buttons
click_link('Link Text')
click('Link Text') # Click either a link or a button
click('Button Value')

# Interacting with forms
fill_in('First Name', :with => 'John')
fill_in('Password', :with => 'Seekrit')
fill_in('Description', :with => 'Really Long Text…')
choose('A Radio Button')
check('A Checkbox')
uncheck('A Checkbox')
attach_file('Image', '/path/to/image.jpg')
select('Option', :from => 'Select Box')

# Scoping
within("//li[@id='employee']") do
  fill_in 'Name', :with => 'Jimmy'
within(:css, "li#employee") do
  fill_in 'Name', :with => 'Jimmy'
within_fieldset('Employee') do
  fill_in 'Name', :with => 'Jimmy'
within_table('Employee') do
  fill_in 'Name', :with => 'Jimmy'

# Querying
page.should have_xpath('//table/tr')
page.should have_css('table')
page.should have_content('foo')
page.should have_no_content('foo')
find_field('First Name').value
all('a').each { |a| a[:href] }

# Scripting
result = page.evaluate_script('4 + 4');

# Asynchronous JavaScript
page.should have_content('baz')
page.should_not have_xpath('//a')
page.should have_no_xpath('//a')

# XPath and CSS
within(:css, 'ul li') { ... }
find(:css, 'ul li').text
locate(:css, 'input#name').value
Capybara.default_selector = :css
within('ul li') { ... }
find('ul li').text

# Source: