How do you know a change hasn't broken your website?
Your website gets a steady stream of changes: security updates, module updates, new features and fixes. Any of them can affect a part of the site nobody meant to touch. Most teams check by hand, with someone clicking through the important pages and trying the forms. That works while the site is small and the person checking knows it well, but the list grows with the site.
It starts to matter at particular moments. A Drupal upgrade is due and nobody can say what it will touch. Updates are queuing up because each release needs a day of manual checking. A bug you fixed last year has come back. Or your organisation is moving to automated deployments and wants a safety check before anything goes live.
Automated tests do that checking for you on every change, so problems show up before they reach your visitors, and updates can go out as soon as they're ready.
How we test your website
Whether we're building your site or adding tests to one you already have, the work follows the same 5 steps.
1. We agree what to test first
We start with the parts of your website your organisation relies on most, such as the forms that bring in enquiries and the tasks your editors do every day. If your site already has tests, we look at what they cover and whether they still run. Then we write the scenarios down in plain English, so your team can check the list before we write the tests.
2. We set up the tools
We use 2 kinds of test, and each catches a different kind of problem.
PHPUnit(Opens in a new tab/window) is the standard testing framework for PHP, the language Drupal is written in. A PHPUnit test calls a piece of your custom code directly and checks the result, such as the rule that decides who can edit a page or the calculation behind a fee. These tests run in seconds, and when one fails, it points to the exact function that broke.
Behat(Opens in a new tab/window) tests the site the way people use it. It visits pages, follows links and fills in forms, then checks what happened, running in a real browser when a page needs JavaScript. Each Behat test is a scenario written in Gherkin, a plain-English format where Given sets the scene, When is the action and Then is the result you expect.
On websites built on Vortex(Opens in a new tab/window), our open-source Drupal project template, both come ready to run. For an existing codebase, we add the same setup.
3. We write the tests
Behat tests live in feature files, 1 for each part of the site. Here's a feature file that checks news articles: visitors see published news and miss drafts, and an editor can publish a new article.
Feature: News articles
As a site editor
I want to publish news articles
So that visitors can read the latest news
Background:
Given the following article content exists:
| title | status |
| [TEST] Opening hours | 1 |
| [TEST] Draft newsletter | 0 |
Scenario: Visitors see published news
Given I am an anonymous user
When I visit "/news"
Then the response status code should be 200
And I should see "[TEST] Opening hours"
And I should not see "[TEST] Draft newsletter"
Scenario: An editor publishes an article
Given I am logged in as a user with the role "editor"
When I visit "/node/add/article"
And I fill in "Title" with "[TEST] New exhibition"
And I check "Published"
And I press "Save"
Then I should see "[TEST] New exhibition"
The Background creates the test content before each scenario, and every line after it is a step the test carries out. Behind each step is code that drives the site. Most of it comes from Behat Steps(Opens in a new tab/window), our open-source library of ready-made steps for Drupal, and we write custom steps for anything unique to your site. PHPUnit tests sit alongside the feature files and cover the logic in your custom code.
4. We run them on every change
The tests run automatically in your CI pipeline, the automated process that builds and checks every proposed change before it's merged or deployed. If a test fails, the build fails with it, and Behat Screenshot(Opens in a new tab/window) saves the page as it looked at that moment, so the developer can see what went wrong.
Vortex also measures how much of your custom code the tests exercise and reports it on each proposed change. By default, the build fails if that falls below 90%, and you can set your own threshold.
5. We keep the suite quick and hand it over
We fix any test that fails at random, because your team needs to trust a failure when it sees one. Tests that run in a real browser take the longest, so we keep them to the journeys that need JavaScript and run the suite in parallel once it grows. Then we walk your developers and testers through it, and they can add tests of their own from there.
What you get
Everything we write lives in your code repository, beside the code it checks, and it's yours to keep.
Your test suite
Behat scenarios for the journeys that matter most to you, and PHPUnit tests for the logic in your custom code. Your developers can run them on their own machines, and your pipeline runs them on every change, with screenshots of anything that fails and, on Vortex, a coverage report.
A plain-English record of how your site should behave
The Behat scenarios double as documentation. Anyone on your team, from a content lead to a new developer, can read them to see what the site is meant to do and check it matches what they expect. When a requirement changes, the scenario changes with it.
A handover your team can build on
Documentation and worked examples for running the tests and writing new ones, and a walkthrough with your developers and testers. If your site already had tests, you also get our review of them, with a note on which to keep and which to fix.
Where we've done this
Automated tests and continuous integration are part of every website we build, from day one. Some examples:
- We created Behat Steps and Behat Screenshot, and we maintain both as open source. Both ship with Vortex, and developers outside DrevOps contribute to them. A state government's whole-of-government content platform used both across its repositories.
- We're building new Drupal 11 websites for 2 Melbourne community radio stations, with a digital agency partner. Both run Behat tests in parallel on every build, alongside PHPUnit tests for their custom code. The first draws its test steps from Behat Steps, and the second checks accessibility automatically on every build.
- For a NSW government regulator's 2 public websites, delivered with a digital agency partner, we built most of both sites and their content migration. Alongside the Behat and PHPUnit tests, a validation script compared the migrated content with its source.
What it costs
When we build or upgrade your website, the tests are part of the work and part of the quote.
To add tests to a site you already have, get in touch and we'll talk through which journeys matter most. Before any work starts, we send you an estimate, or a fixed-price quote for a defined scope, such as setting up the tools and covering an agreed list of journeys. A fixed-price quote is the price, and nothing starts until you've approved the scope and cost. If you have a support plan with us, test work can come out of your prepaid hours.
AI-assisted delivery speeds up the writing of automated tests. If you choose it, the tests meet the same standard and go through the same review, for up to 30% less on suitable work.
Where testing leads
Tests matter most when a change reaches across the whole site, as a Drupal upgrade or a migration does, because they show the site still does what it did before. They run inside a CI/CD pipeline, which carries each change from a developer's machine to your live site. On a support plan, the updates we make go through the same tests before they go live.
FAQs
Do automated tests replace manual testing?
Not completely. Automated tests take over the checks that repeat with every release. A person still needs to look at what's new, such as a fresh design or a connection to another organisation's system, and we include manual testing where a project needs it.
Why Behat instead of Cypress or Playwright?
Behat works with Drupal directly. A test can set up the users and content it needs through Drupal itself before it starts, and tests that don't need JavaScript run without a browser, which keeps them quick. Its scenarios are written in plain English, so people outside the development team can read them. We use Cypress and Playwright too, where a project suits them.
Do you write custom Behat steps?
Yes, for whatever is unique to your site. The common steps come from Behat Steps, so the custom code stays small. Our post on supercharging your Drupal testing with Behat Steps shows how it fits together.
Can you integrate testing into our existing deployment process?
Yes. The tests become a step in the pipeline you already use, so each change is checked before it's deployed. We've worked with GitHub Actions, CircleCI and GitLab CI.
What if we don't have a CI pipeline? Where would we run these tests?
We set one up with Vortex as part of the work. It comes with PHPUnit, Behat and screenshot capture already wired into GitHub Actions or CircleCI. Our CI/CD pipelines page covers the rest.
Can you add tests to a website you didn't build?
Yes, usually when we take on its upgrades or support. We start with the journeys that matter most and add tests from there. If the site has no test setup yet, we add one first, usually with Vortex.
Can you tell us how good our current tests are?
Yes. An analysis of your automated test coverage is part of our in-depth site audit, which costs $4,450 + GST. If you'd like us to look at your tests on their own, we'll scope and quote that separately.
Do you use AI to write tests?
If you choose AI-assisted delivery, yes, and test writing is among the work it speeds up. We still review every test, and the suite has to pass in CI before anything is merged. Our responsible AI policy explains how we handle your code.