Visual Regression Testing for Drupal
Drupal sites change in more ways than most. Core gets minor and security releases, contributed modules update through Composer, the theme is usually custom, and every deployment imports configuration that can move blocks, change a view or switch a display mode. Most of those changes are fine. Now and then one breaks a page, and it’s usually something you can see but nothing reports: a menu that wraps at tablet width, a view that lost its grid, a paragraph type whose styling disappeared on one content type. There’s no error in the log, and an editor or a visitor finds it a week later.
Diffy is a visual regression testing tool that catches those changes first. It screenshots your pages on two environments (staging and production, a pull request preview and production, or before and after an update), compares them at every breakpoint and highlights exactly what moved. You don’t install a module or write test code. You give Diffy URLs and it does the rest.
Start testing for free: 500 screenshots a month, no credit card.
What breaks on Drupal sites
Visual regressions on Drupal sites tend to come from the same few places:
- Contributed module updates. A module ships new CSS or JavaScript in a library attached to every page, changes the markup it renders or renames a class your theme targets.
- Core updates. Minor releases change core templates, base theme CSS and front-end libraries. Core also removes things over time: the Classy and Stable base themes left core in Drupal 10 and moved to contrib, so themes built on them need attention during an upgrade.
- Twig template overrides. When a module or core changes a template that your theme overrides, your copy keeps the old markup, or stops matching the new variables.
- Configuration imports.
drush config:importon deploy can change block placement, view displays, image styles and form or view modes, so the site looks different even when no code touched the theme. - Layout Builder, Paragraphs and other page-building modules. Updates change the wrapper markup around every section or component, and spacing or column widths shift across every page built with them.
- Asset aggregation and performance settings. Turning CSS/JS aggregation on, or a change to how a module declares its libraries, can change the order styles load in.
- Hosting changes. A PHP version upgrade, a new CDN rule or a change in caching can change what renders, even when nobody touched Drupal.
- Major upgrades and migrations. Moving from Drupal 7 (end of life since January 2025) to Drupal 10 or 11, or from 10 to 11, touches nearly every template on the site at once.
The hard part is that these problems only show up on some pages. The header is fine everywhere except on landing pages built with Layout Builder, or the card grid only breaks at 768px. Clicking through a handful of pages after a deploy won’t catch that. Comparing every page at every breakpoint will. In our study of 100 visual bugs that reached production, the largest group, 35 of the 100, was layout shifts and misalignment.
Where Diffy fits in a Drupal workflow
1. On every pull request
Most Drupal hosts can build a preview environment for each branch. Diffy waits for it, compares it with production (or whichever environment you choose as the baseline) and reports the result on the pull request, so visual changes are reviewed before merge, along with the code. Ready-made workflows exist for:
- Pantheon. A GitHub Actions workflow creates a Multidev for the pull request, runs
drush cranddrush config:import, runs the comparison and posts the result as a GitHub check. See deploying to Pantheon from GitHub with visual tests and the setup docs. - Upsun (formerly Platform.sh). Diffy waits for Upsun’s pull request environment and compares it with production. See the Upsun guide.
- Tugboat. The comparison runs as the last build step, once the preview is ready. See the Tugboat docs.
- Any other host or CI. GitHub Actions, GitLab CI, CircleCI, Bitbucket Pipelines and Jenkins can all call the Diffy CLI once the environment is up. GitLab gets merge request comments and a commit status. See GitHub Actions and GitLab CI.
These workflows use the API, which comes with every paid plan.
2. Monthly module and security updates
For maintenance work, run the updates on staging, then compare staging with production before deploying. If you host on Pantheon, the open-source pantheon-autoupdates script automates the whole loop: it checks for updates, applies them on a separate Multidev and, when there were updates, starts a Diffy comparison against Live.
3. Before you push, from your local site
Teams that develop locally can screenshot their local site with the DDEV add-on, the Lando integration or Docksal, and compare the result with production before opening a pull request.
4. Scheduled monitoring
Not every change comes from a deploy. Editors change blocks and menus, a third-party script changes overnight, and a cache rebuild can expose a problem that was already there. Set a schedule in the project and Diffy screenshots production on the days and at the time you choose. It compares each run with the previous one or with a fixed baseline, and notifies you by email, Slack or webhook when something changes.
5. Upgrades and migrations
For a Drupal 7 migration or a major version upgrade, add the old site and the new build as two environments of one project and compare them page by page. Our website migration testing checklist covers what to check beyond the visuals.
Getting your pages into Diffy
You don’t need to type URLs one by one. When you create a project, Diffy can collect the page list from:
- Your XML sitemap, such as the one generated by the Simple XML Sitemap or XML sitemap modules. Sitemap index files work too.
- Internal links on a page you point it at.
- A text file with one URL per line.
For large sites you don’t need every node. Pick one or two examples of each content type, view and landing page template, plus the pages that use your most complex components, and you’ll cover most of what an update can break for a fraction of the screenshots. Another option is to build a single style guide page that renders every component and test that page: our post on hiding Drupal test pages by IP address shows how to keep it away from visitors, and if you use Pattern Lab or Storybook, see visual testing of Pattern Lab and Drupal and Drupal design systems.
Making Drupal screenshots stable
Screenshots only help if they don’t flag changes that aren’t real. Diffy has a setting for each of the usual sources of noise:
- Pages behind a login. Choose the Drupal preset under Authenticate and Diffy logs in through
/userbefore taking screenshots. Use a dedicated account whose role doesn’t have the “Use the toolbar” or “Use contextual links” permissions, so the admin toolbar and the edit pencils don’t appear in the screenshots. - Staging behind HTTP basic auth. Add the username and password to the environment in the project settings.
- Cookie consent banners. Set the consent cookie in the project so the banner never appears, or hide it with a CSS override.
- Content that loads late. Lazy-loaded images, views loaded over AJAX and other content that arrives after the page loads can be caught with a screenshot delay and scrolling, both in the project’s advanced settings.
- Sliders, carousels and animations. Freeze them with a JavaScript snippet that runs before the screenshot.
- Views that list the latest content. Replace changing text with placeholder text using mock content, so a newly published article doesn’t show up as a change on every page.
- Embedded videos and maps. Mask them so a different video frame doesn’t show up as a difference.

Multisites and large content sites
Drupal is often used for big estates: one codebase serving dozens of sites, or one site with thousands of nodes. That’s where checking pages by hand stops working.
Chromatic, a Drupal agency, maintains a multisite of more than 20 sites. For every pull request they build a Tugboat preview for each site and have Diffy compare each one with its production site. A typical result is 15 sites with no changes and 5 with something to look at, so the team knows exactly where to go before the code is merged.
At the Urban Institute, which runs several Drupal sites, the team compares staging with production right before each deployment. In the words of Farnoosh Johnson, Associate Director: “Being able to run a set of screenshots from staging and compare them to production right before the deployment has been a huge improvement.”
For agencies with many client sites, projects can be organised with tags and run in bulk, team members are unlimited, and roles let clients see their own results.
Every breakpoint, two browser engines
Drupal themes are full of media queries, so responsive bugs are where changes hurt most. Diffy screenshots each page at as many widths as you set, from 240px to 2000px, in Chrome or WebKit (the engine behind Safari). Our responsive design testing guide explains which widths are worth testing.
Reviewing the results
A comparison of 50 pages at 4 breakpoints is 200 pairs of screenshots, so reviewing them quickly matters.
- An AI summary groups the changes by impact, so you see “the footer changed on all 48 pages” as one item rather than 48.
- You approve changes one at a time, per screenshot, per page or per breakpoint, so expected changes are out of the way and only the real problems are left.
- Shareable links let you send a comparison to a client or developer who doesn’t have a Diffy account.
Frequently asked questions
Do I need to install a Drupal module?
No. Diffy works from URLs. It loads your pages in a real browser the same way a visitor would, so nothing is added to your codebase and it works with any theme, any hosting and any Drupal version, including Drupal 7.
Can Diffy test pages that need a Drupal login?
Yes. Choose Drupal under Authenticate in the project settings and enter a username and password. Diffy logs in through the standard /user form before taking screenshots. If your login form is customised, you can give Diffy your own field selectors instead.
Does it work with Pantheon, Upsun, Acquia and other Drupal hosts?
Diffy needs a URL for each environment, so any host works. Pantheon Multidev, Upsun and Tugboat have ready-made pull request workflows. On other hosts you call the Diffy CLI from your deployment pipeline once the environment is ready.
Can I use Diffy to check a Drupal 7 to Drupal 10 or 11 migration?
Yes. Add the old site and the new site as two environments of the same project and compare them page by page. It works best when the migration keeps your URL paths, which a migration that carries over path aliases does.
How many screenshots does a Drupal site need?
One screenshot is one page at one breakpoint. Comparing 40 pages at 3 breakpoints on staging and production uses 240 screenshots. The free plan includes 500 a month, enough for regular checks on a small site or a trial on a bigger one.
Start with your next deployment
Before your next round of module updates or your next release, add the site to Diffy, compare staging with production and see exactly what changed. It takes a few minutes to set up.
Related: What breaks during WordPress and Drupal updates · Visual regression testing for WordPress · Integrations · Pricing