2026-09-16 | ansible

Your Own Test Automation Environment: Ansible Does the Heavy Lifting

MDN dropped a solid walkthrough on standing up your own Selenium/WebDriver environment. Good for the fundamentals, sure. But here’s the thing — they teach you how to install a testing stack once. They don’t teach you how to rebuild it from scratch when your laptop dies, or how to replicate it across your team’s machines, or how to keep it in lockstep with your CI runners.

That’s where Ansible comes in. If you’re going to run your own automation environment, the automation itself should be automated. Otherwise you’re just trading vendor lock-in for manual drudgery.

What MDN Actually Covers

The article walks through the classic local testing setup. Install a Selenium-compatible driver for your browser, pull in selenium-webdriver for Node, write some basic tests, and run them against a local server. They also touch on integrating that local environment with commercial cloud testing services like Sauce Labs or BrowserStack.

Nothing wrong with any of that. The code examples are clean, the browser driver matrix is well-explained, and the local-vs-cloud tradeoff discussion is honest. For someone who has never touched WebDriver, it’s a perfectly fine starting point.

But the whole thing assumes you’re installing this on one machine, by hand, once. That’s not how real environments work. Not for a small business with a handful of devs, and definitely not for anyone running a home lab that mirrors production.

The Missing Layer: Reproducibility

Here’s the problem MDN doesn’t solve. You install Selenium Manager, you grab the right ChromeDriver, you write your tests. Three months later, your OS updates, Node bumps a major version, and your browser auto-updates past what your driver supports. Everything breaks. You spend an afternoon debugging.

Or worse — your colleague sets up the same environment on their machine, and it works differently. Different browser version. Different driver. Different test results. Now you’re arguing about whether the bug is in the code or the setup.

Ansible fixes that. You write a playbook once, and every machine gets the identical environment. Every time.

Here’s the pattern I use for any test runner, whether it’s Selenium, Playwright, or Cypress:

- name: Ensure test automation environment
  hosts: test_runners
  become: true
  tasks:
    - name: Install Node.js and npm
      apt:
        name: ["nodejs", "npm"]
        state: present

    - name: Install selenium-webdriver globally
      npm:
        name: selenium-webdriver
        global: true
        state: present

    - name: Ensure Chrome is present
      apt:
        name: google-chrome-stable
        state: present

    - name: Pin ChromeDriver to match Chrome version
      get_url:
        url: "https://storage.googleapis.com/chrome-for-testing-public/{{ chrome_version }}/linux64/chromedriver-linux64.zip"
        dest: /tmp/chromedriver.zip

The version pinning is the part most people skip. MDN mentions that Selenium Manager can auto-resolve driver versions, and that’s fine for a quick local setup. But in a shared environment, you want determinism. Pin the Chrome version, pin the driver version, pin the Node version. Your tests should fail because the code is wrong — not because Chrome auto-updated overnight.

Ansible as the Orchestrator

MDN’s article treats the testing environment as a static thing you install. But your test infrastructure is a living system. It needs to scale, it needs to heal, and it needs to stay consistent.

Ansible gives you that orchestration layer. I use it to manage a small fleet of LXC containers in Proxmox that exist solely for running browser tests. Each container gets provisioned from the same playbook, so I know they’re identical.

The playbook does more than install packages. It also:

  • Creates the directory structure for test artifacts
  • Installs the right Node dependencies from a lockfile
  • Copies the test suite itself from a git repo
  • Sets up a systemd timer to run the tests on a schedule

That last bit is worth repeating. A test environment that only runs when you remember to run it is barely better than no test environment at all. Automate the execution, not just the installation.

A Concrete Takeaway for Small Business

I’ve helped a few small shops set this up. They don’t need a grid of browser instances or a dedicated CI server. They need one reliable place where tests run the same way every time, and where a new hire can be productive on day one.

Here’s the playbook structure I’d recommend for that use case:

- hosts: test_runner
  roles:
    - common
    - nodejs
    - chrome
    - selenium
    - test_suite

Each role does one thing. The test_suite role clones the repo, runs npm ci, and sets up a cron job that executes the tests at 2 AM. If a test fails, a small script posts the output to a Slack webhook.

The beauty is that when the environment drifts — and it will — you don’t debug it by hand. You re-run the playbook, and Ansible brings the machine back to the desired state. Idempotency is your friend.

What MDN Gets Right

I don’t want to sound like I’m dumping on the article. It covers the basics well. The explanation of how WebDriver communicates with the browser through a driver binary is clear. The section on choosing between local and cloud testing is honest about costs and tradeoffs.

The local-first approach is also the right philosophy for learning. You should understand what happens under the hood before you hand your tests to a commercial service. MDN’s examples with selenium-webdriver for Node are straightforward and copy-pasteable.

For someone who wants to understand the moving parts, it’s a good read. I’d just argue that the moving parts should be managed by an orchestrator, not by memory and good intentions.

What I Decided to Do

I’m not ripping out my existing setup, but I am tightening it. I pulled the MDN article’s example tests and ran them against a fresh LXC container in my Proxmox cluster. Then I wrote an Ansible playbook that provisions that container from scratch, including the test suite and the cron schedule.

The playbook lives in my git repo alongside the tests. When I update the tests, I tag the repo, and the playbook can deploy that specific tag. Reproducible, versioned, and boring in exactly the way production automation should be.

If you’re running your own test automation environment, stop installing it by hand. Write the playbook, commit it, and let Ansible do what it does best. Your future self — and your teammates — will thank you.

tags: Ansible · ansible automation orchestrator · selenium webdriver · test automation environment · ansible playbook · small business testing
← Back to blog