Integrating BrowserStack into your WordPress Azure Devops Pipeline
In a previous post, I described how to to integrate deployments to WPEngine via your CI/CD pipeline on Azure Devops. In this article, I’ll do a deep dive into how to add automated browser testing via BrowserStack into your pipeline.
Table of Contents
- Requirements
- Setup BrowserStack in your Codebase
- Setup PHPUnit Tests
- Setup Global Variables
- Setup Parallel Configuration
- Add BrowserStack to Azure Devops
- Add Necessary Components to Devops Pipeline YAML
Requirements
- A BrowserStack Automate account
- A PHP application (for my use case, this was integrating unit tests into WordPress)
- Azure Devops
Setup BrowserStack in your Codebase
BrowserStack has already written up very good instructions on how to integrate the unit tests into your codebase. There is also a repo with the necessary files. Finally, there are instructions on how to integrate BrowserStack into Azure Devops, but this tutorial fills in the gaps that I had along the way. Here is a short run through of steps needed:
- Require browserstack/browserstack-local, hpunit/phpunit-selenium, and php-webdriver/webdriver in your composer file.
- Create a config folder and drop in local.conf.json, parallel.conf.json, single.conf.json
- Create a lib folder and drop in global.php and parallel.php
- Create a tests folder and drop in local_test.php and single_test.php
For my use case, I was only planning on running a parallel test, but inside of a parallel test, it calls the single test code multiple times for each test to run, so make sure you don’t remove those from your code base. If you aren’t planning on running local tests, you can remove those files.
Setup PHPUnit Tests
I started with tests/single_test.php and created a simple script that will open up the search bar, type in a term to search for, and validate the page title returns is the correct page I’m looking for.
<?php
require 'vendor/autoload.php';
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
class SingleTest extends BrowserStackTest {
public function testSite() {
self::$driver->get($GLOBALS['TEST_URL']);
self::$driver->manage()->timeouts()->implicitlyWait = 10;
$searchbox = self::$driver->findElement(WebDriverBy::id("search-form-2"));
$searchbox->click();
$searchbox->sendKeys("Hello");
$searchform = self::$driver->findElement(WebDriverBy::cssSelector('.widget-content .search-submit'));
$searchform->click();
sleep(10);
$this->assertEquals('Search Results for “Hello” – My WordPress Site', self::$driver->getTitle());
self::$driver->quit();
}
}
?>
Setup Global Variables
In my case, I wanted to pipe in my url into the above script via an environment variable, so that depending on my branch, I could test the prod, staging, or development site. I added this to my lib/globals.php
$GLOBALS['TEST_URL'] = getenv("TEST_URL");
You’ll see farther down how I’m piping that url in via Azure Devops. I plan on having my BrowserStack username and password as environment variables inside of Azure Devops, so there’s no need to add those here.
Setup Parallel Configuration
In config/parallel.conf.json, you’ll set up your configuration for which browsers and devices you want to test. In my case, I wanted to test across all 4 major browsers, and iOS and Android for mobile. Here is my config:
{
"server": "hub-cloud.browserstack.com",
"capabilities": {
"build": "phpunit-browserstack",
"name": "parallel_test",
"browserstack.debug": true
},
"environments": [{
"browser": "chrome",
"browser_version": "latest-1",
"os": "Windows",
"os_version": "10",
"browserstack.selenium_version": "3.141.59"
},{
"browser": "firefox",
"browser_version": "latest-1",
"os": "Windows",
"os_version": "10",
"browserstack.selenium_version": "3.141.59"
},{
"browser": "Safari",
"os": "OS X",
"os_version": "Mojave",
"browser_version": "latest",
"browserstack.selenium_version": "3.141.59"
},{
"browser": "IE",
"browser_version": "latest",
"os": "Windows",
"os_version": "10",
"browserstack.selenium_version": "3.141.59",
"browserstack.sendKeys" : "true"
},{
"os_version": "7.0",
"device": "Samsung Galaxy S8",
"real_mobile": "true"
},{
"device": "iPhone 8 Plus",
"os_version": "11",
"real_mobile": "true"
}]
}
If you would like to run your tests now without running through your pipeline, you can run those via command line like this:
TEST_URL="http://mysite.com" BROWSERSTACK_USERNAME="xxxxxx" BROWSERSTACK_ACCESS_KEY= "xxxxxxx" CONFIG_FILE=config/parallel.conf.json php lib/parallel.php
This passes in your URL you want to test, your username and pass, tells the tests to use the parallel configuration and then calls lib/parallel.php. If you’ll take a look at that file, this script only grabs your parallel configuration and loops through each config to run against (IE, Chrome, etc) and calls your single_test.php against it.
Add BrowserStack to Azure Devops
- Install the extension here for Azure Devops.
- Open Azure Devops and go to your Project Settings.
- Under Pipelines, click Service Connection.
- Click New Service Connection.
- Select BrowserStack
- Input your Username and AccessKey (found on your Dashboard of https://automate.browserstack.com)
- Input a Service Connection Name (you’ll need this in the next step, referenced as “BrowserStack Endpoint”).
- Verify and Save.
Add Necessary Components to Devops Pipeline YAML
The desired workflow for my site was to deploy to WPEngine, and then run my BrowsersSack tests so that I could see if my deployment was successful. I added the following code to the end of my wpengine-pipeline.template.yaml
- script: |
sudo update-alternatives --set php /usr/bin/php$(phpVersion)
sudo update-alternatives --set phar /usr/bin/phar$(phpVersion)
sudo update-alternatives --set phpdbg /usr/bin/phpdbg$(phpVersion)
sudo update-alternatives --set php-cgi /usr/bin/php-cgi$(phpVersion)
sudo update-alternatives --set phar.phar /usr/bin/phar.phar$(phpVersion)
php -version
displayName: 'Use PHP version $(phpVersion)'
- script: composer install --no-interaction --prefer-dist
displayName: 'composer install'
- task: BrowserStackConfig@0
inputs:
BrowserStackServiceEndPoint: 'BrowserStack Endpoint'
- script: |
TEST_URL="${{ parameters.productionUrl }}" CONFIG_FILE=config/parallel.conf.json php lib/parallel.php
displayName: 'Run PHP Tests'
Depending on where we put this code, we can run this as part of a pipeline of certain branches in order to run against different environments, or we can run with each branch and hard code the environment.
A few notes on the previous code:
- The first step sets up php in a necessary fashion to be able to run composer.
- The second step runs composer so the necessary files are installed to be able to run your tests. Remember not to commit anything in the vendor directory to your repo.
- ${{ parameters.productionUrl }} is a parameter that I’ve set up so that I can differentiate my URLs to the corresponding branches. You can read more about how to split up those parameters here.
- The last step inputs this URL parameter, and runs our parallel script. Here is a sample output of how this runs:
You can see how it’s running the parallel script, and running each invidivual test and showing the success of the tests that were ran “OK (1 test, 1 assertion).”