Continuous Integration has become synonymous with testing and automation. In order to merge and push code together on a tight iteration, assurances and checkpoints must be built into the system.
But there are other reasons to test. Among them, defining 'done' with a client and translating the definition of done into code so that we can know when a feature is complete. It adds focus to the process, documentation to the project, and regression testing to the project's lifecycle. Making the definition of done executable means you can ask "is it done?" and "has it stayed done?".
Today we are going to set Behat up, add a test, and run that test with an automated CI server with every push to github.
Hang onto your butts, this one is going to be an awesomely wild adventure.
Step One: Install and Configure Behat (the Drupal Extension)
With composer already installed (thanks, Ansible), and a
composer.json already defined in our project root (see here if you skipped No Excuses Part III), we only need to add Behat as a dependency.
composer.json so that it includes:
From inside your running vagrant box (
vagrant up if you shut it down, and
vagrant ssh if you are no longer logged in), run
composer update. The Drupal Behat Extension and its dependencies will be downloaded. We will get to why we added drush in a bit.
Now we need to add a configuration file for Behat. This is what ours will look like:
Add these contents into a file called
behat.yml and save it in your project root.
We just installed the Drupal Extension for Behat. You can and should read more about the extension here. But "I haven't read the docs yet" is an excuse that hasn't held you up before so why start now?
bin/behat --init inside your vagrant box. If successful, you should see:
vagrant@no-excuses:/vagrant$ bin/behat --init
+d features - place your *.feature files here
+d features/bootstrap - place your context classes here
+f features/bootstrap/FeatureContext.php - place your definitions, transformations and hooks here
These are directories and files that Behat has set up for you. Run
bin/behat -dl and you can see all the predefined step definitions that we can use to start writing tests.
Step Two: Write our first test.
Let's write a test then.
features directory that Behat created for you, make a test file called
installation.feature. We are going to add a test that verifies a.) the site is up, and b.) that a user can login.
Put this into your newly created file, add this:
Feature: Installation Verification
As a developer,
I want to know that my project has installed,
So that I can smoke test craychee's work.
Scenario: Verify that the site and its variables are installed. Given I am on homepage Then I should see the text "Welcome to no-excuses"
Scenario: Verify that user 1 can log into the site. Given I am not logged in When I visit "user/login" And I fill in "name" with "admin" And I fill in "pass" with "admin" And I press "Log in" Then I should see the link "Log out" And I should see the link "Add content" ~~~ Note that the text "Welcome to no-excuses" is the text that I am expecting since "no-excuses" is the name of my example project. This text will be different if you have named you project something other than "no-excuses".
Now let's run this locally. From inside your project's root (inside your vagrant box), run
bin/behat and your test suite will run. If your project is built successfully, everything should pass.
This test is a great start because it allows us to verify that our site is built properly and we can log into it as expected. This is especially important if we are testing our build without access to a browser GUI, such as on a CI Server.
Step Three: Run that test on a CI Server
Great. Now we are going to add some files to explain to circleCI how to build our Drupal project in the same way that we are building our Drupal project locally. I go through a bit more explanation about what I am doing in the previous blog post. For now, you are going to need to just trust me. Yikes.
First, navigate to your
cnf directory and create a file called
circle.conf. Add these contents:
While still inside
cnf, create a file called
circle.settings.php. Add these contents:
$databases=array('default' => array(
'default' => array(
'database' => 'circle_test',
'username' => 'ubuntu',
'password' => '',
'driver' => 'mysql',
'host' => '127.0.0.1',
require_once DRUPAL_ROOT . '/sites/default/vendor/autoload.php';
Remember how we set up the build to just copy in the
settings.php into Drupal before running site install because the connection information would be different per environment? (Note that you don't need the
require_once line if you aren't using Composer to manage Drupal.)
Now return to the project root. Create a file called
circle.yml and add these contents:
dependencies: pre: - cp $HOME/$CIRCLE_PROJECT_REPONAME/cnf/circle.conf /etc/apache2/sites-available/default - sudo sed -e "s?%HOME%?$(pwd)?g" --in-place /etc/apache2/sites-available/default - sudo sed -e "s?%PROJECT_DIR%?www?g" --in-place /etc/apache2/sites-available/default - echo "sendmail_path=/bin/true" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - sudo a2enmod rewrite - sudo service apache2 restart - cp cnf/circle.settings.php cnf/settings.php override: - composer install --prefer-dist post: - sudo chown -R $(whoami):www-data www - build/install.sh
These are instructions for circleCI to build our project and, after configuring Apache2, they are identical from our local build: run
composer install and then
build/install.sh to build the project, then run
bin/behat to verify everything is working as expected.
Since circleCI doesn't have Drush installed and our version of Drush, installed with
apt-get, is outdated anyway, we added Drush to the project with composer instead. Now we can tell our build to use that version of Drush instead when building our project.
build/install.sh for editing. Where we are setting the
drush variable (line 6), change it instead to:
drush="$base/bin/drush $drush_flags -y -r $base/www"
Great. Now circleCI will be able to use the same version of Drush that we are.
Now sit back and watch your project build and test itself.
Want to make sure you followed all of my instructions? You can view/fork my no-excuses-example here.
Great ...Now what?
You are going to need to catch yourself up on writing tests for Drupal with Behat. I recommend Jack Franks talk.
When should you write tests? Early and often.