Automated Behavioral Testing on a budget with Pantheon, GitLab CI, and Behat
— with mparker17
Follow along at mparker17.github.io/talk–software-testing-overview
Who am I?
mparker17 on Drupal.org, GitHub, and GitLab
I work for Brady’s Meat & Deli, Digital Echidna
(previously Environment Canada, Versabanq, UWaterloo, PeaceWorks, Myplanet, OpenConcept)
Who am I? (ctd.)
I am an Acquia Certified Drupal Developer
CS degree not completed at UWaterloo
How did this all start?
- Bradys is using Pantheon for our existing D7 site; but we are porting our site to D8
- We needed to install Drupal Commerce
- Drupal Commerce has non-Drupal dependencies, so it needs Composer
- Using Composer on Pantheon breaks automatic updates — and isn’t encouraged
How did this all start? (ctd.)
- Researched other hosting providers (Acquia Cloud, Platform.sh, Omega8.cc, Contegix)
- … for our use case, Pantheon is still cheaper by large margin
- Reading support pages and forums pointed me to
pantheon-systems/example-drops-8-composer
- it didn’t solve the broken automatic updates;
- but it is a recommended way of managing a site with composer dependencies
Concept: artifact repos
By Illustratedjc - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=26761018
Concept: artifact repos (ctd.)
- PHP is an interpreted language: its source code is the program — “traditional” languages are compiled to “artifacts”, which get distributed/run.
- Before D8, Drupal was in its own world: nearly everything in modules or themes
- (sometimes you needed libraries — usually front-end scripts — and PHP libraries were a special case)
- This meant you could use the same Git repo to:
- version control your source code,
- manage the state of your production filesystem.
Concept: artifact repos (ctd.)
- With D8, we made a conscious decision to build on work outside Drupal community:
- this lets us accomplish more than if we did everything ourselves…
- but… we have to deal with Composer (which compiles dependencies);
- and… modern theming practices often involves compiling assets.
- So now web dev has become more like “traditional” development (i.e.: we have to compile before we can run)
Concept: artifact repos (ctd.)
- Git treats artfacts like any other file
- this is great if you’re using Git to manage the state of a filesystem,
- but if you’re doing that, it makes development difficult (lot of noise/churn)
Concept: artifact repos (ctd.)
One possible solution:
- tell your VCS to ignore artifacts,
- do your development as normal
- deploy the repo to production
- compile your dependencies, assets, etc. on production
Concept: artifact repos (ctd.)
This has problems, though…
- reproducability — composer/npm can and will download different versions of packages on different runs
- disaster recovery — what if package server is down? what if you want to spin up a replacement server?
- security — how do you detect unauthorized changes? what if your prod server has limited outbound internet access for security?
- scalability — what if you want to spin up a load-balancer running identical code?
Concept: artifact repos (ctd.)
- A better solution:
- store your code in a “source” repo without compiled dependencies,
- use Continuous Integration (CI) to compile your dependencies, and package that into an “artifact repo”
- deploy your artifact repo
- The artifact repo gives you the reproducability, disaster recovery, security, and scalaiblity you need
- The source repo makes development / code review easier
Set up source repo
pantheon-systems/example-drops-8-composer
is a source repo template
- But it had a lot of stuff in it that I didn’t need (provisioning scripts, CircleCI code, etc.)
- And I wanted to understand it
- So I started by deleting all the stuff I didn’t need
- Got it down to 32 files and 1200 lines of code (excluding
composer.lock
)
Set up automation bot
The automation bot needs to push code to Pantheon…
- Create the bot an email account
- Generate an SSH key pair with
ssh-keygen -f $destination_file
- Don’t forget the
-f $destination_file
!
- Don’t set a password because GitLab CI can’t enter it
- Sign up bot for Pantheon user account; add SSH public key; generate machine token
- Grant the bot access to the site
Setting up GitLab CI variables
The automation bot is going to push from GitLab…
- Base64-encode the SSH private key with
cat $destination_file | base64 -w0
- Add information to the GitLab repo’s Settings -> CI/CD -> Variables…
SSH_PRIVATE_KEY
= the base64-encoded one
TERMINUS_ENV
= dev
(i.e.: the pantheon environment I want to run tests on)
TERMINUS_SITE
= the machine name of the site
TERMINUS_TOKEN
= the machine token
GitLab CI Variable options
When entering variables, you’ll see the following options…
- Type — can be variable or file — examples used vars
- Protected — whether variable is available during feature branch tests — maybe “no” on public sites?
- Masked — whether variable shows up in logs — “no” for keys/tokens
- Scope — lets you make multiple vars with same name, but different values per environment — useful if CI deploys to multiple environments
Behat tests
example-drops-8-composer
looks for tests in tests/behat/features/
For example:
# tests/behat/features/environment_indicator.feature
Feature: Environment indicator
In order to avoid making changes to the wrong environment
As an administrator
I need a way to distinguish which environment I am using
@api
Scenario: Administrator sees links to open this page in other environments
Given I am logged in as a user with the "administrator" role
When I go to "admin/content"
Then I should see "Open in: Dev"
End result
- When I push to a branch, GitLab CI runs in two stages…
- build — compiles artifact repo, pushes with SFTP to Pantheon dev site
- test — spawns two sub-processes that run independently
- test:behat — runs Behat tests on the Pantheon dev site
- test:code_sniff_unit_test — runs
php -l
, phpcs
with Drupal, DrupalPractice lints, phpunit
on custom code
Limitation: no multidev
This setup mangles the dev environment, so only one person can test, and only one change at a time; and you can’t really use the dev environment for anything else
- example-drops-8-composer was designed to be used with Pantheon multidev; but that’s expensive
- this works for our use case though (1 dev, working local environment, hardly use dev, rarely use stage)
Thanks!
Special thanks to Rob and Monica at Brady’s Meat & Deli