If you are here just to know how to run AET, simply skip to TL;DR.

AET is a quality monitoring system that detects regression on websites (comparing visual and source changes in time and monitoring basic page health checks). Our company open-sourced AET in 2016. Currently, the system is used in most of our projects.

Sample screenshot comparison in AET report

However, AET history starts in 2011. The idea for the tool came with a commercial requirement and solved a real-world problem. One of our customers wanted to migrate their website from one platform to another in a short period of time. That wouldn’t be tricky if not for the fact that production contained over 100 000 pages. The requirement was that pages in the new platform are (pixel-perfect!) identical to the current ones. We needed an automated process for comparing a huge amount of pages. And this is how the very first version of AET was created. If you are interested in the AET project make sure to visit its GitHub repository: https://github.com/wttech/aet/.

That’s enough history, let's now move on to the tutorial. Following this guide, we will set up a local AET instance, run a simple test, and generate a report.

AET instance setup

Before you start, make sure you have the following prerequisites installed on your computer:

  1. Docker Desktop with Kubernetes enabled (I was running this tutorial on version 3.5.1).

    • If you are a macOS user (or run Docker on Windows without WSL2), make sure you have updated resources settings to at least 2 CPUs and 8 GB of memory (however, for a smoother experience, I’d suggest 4 CPUs and 10 GB of memory).
  2. Helm CLI installed (I was running this tutorial on version 3.6).

    • E.g. with brew install helm on macOS or sudo apt-get install helm on Windows WSL2 Ubuntu.
  3. Terminal (e.g. iTerm2 for macOS or Ubuntu console in WSL2 for Windows users).

To run AET we will use Helm. In short words, Helm is a package manager for Kubernetes (you may think of it as yarn for Kubernetes). Helm packaging format is called “charts”. A single chart can deploy any simple (e.g. static website) as well as complex (e.g. web application with databases, caches etc.) application.

Now, to install AET, run these two commands:

helm repo add aet-chart https://malaskowski.github.io/aet-helm (1)
helm install my-aet aet-chart/aet -n local --set ingress.enabled=true --create-namespace (2)
  1. The first line adds a new Helm chart repository named aet-chart to your local list of repositories. This repository is hosted on the GitHub Pages of my repository: https://github.com/malaskowski/aet-helm (which is open-source).
  2. The second line runs the install command that utilises the aet chart from the aet-chart repository. Additionally, we name our instance my-aet and use the local namespace (namespaces in Kubernetes are virtual clusters that share resources like CPU, but separate applications running on the same Kubernetes instance). Finally, we set the ingress.enabled flag to true, which in the AET chart turns on ingress (a layer responsible for incoming traffic) for the application. The whole command is followed by the --create-namespace flag, which creates the namespace (local) if one does not exist yet.

That’s it! Your local AET server should be running within 2-3 minutes. Let’s check AET instance readiness. In a separate console window run the following command:

watch -n 1 kubectl get pods,statefulsets --namespace local

It should display a table similar to the one below:

NAME                                        READY   STATUS    RESTARTS   AGE
pod/my-aet-activemq-64d465ff85-s5fhq     1/1     Running   2          6m41s
pod/my-aet-aet-mongodb-0                 1/1     Running   0          6m41s
pod/my-aet-browsermob-766cfc8778-9259b   1/1     Running   0          6m40s
pod/my-aet-chrome-6447cfd756-275jf       1/1     Running   0          6m41s
pod/my-aet-chrome-6447cfd756-7gw2z       1/1     Running   0          6m41s
pod/my-aet-chrome-6447cfd756-jbsvj       1/1     Running   0          6m41s
pod/my-aet-chrome-6447cfd756-vvnbk       1/1     Running   0          6m41s
pod/my-aet-hub-78d8995bc9-rsfgs          1/1     Running   0          6m41s
pod/my-aet-karaf-7c498bccf8-vvdqk        1/1     Running   0          6m41s
pod/my-aet-report-b4549975-wrpt5         1/1     Running   0          6m41s

NAME                                  READY   AGE
statefulset.apps/my-aet-aet-mongodb   1/1     6m41s

When all pods are in "Running" state, it's time to start using our brand new AET instance. Your AET address is http://aet- (we use nip.io to get a nice alias with no need to edit /etc/hosts on your machine).

Running AET tests

To run AET tests you need a test suite, which is an XML file that follows a very simple AET DSL.

Let’s create one. Save the following snippet in the my-suite.xml file:

<?xml version="1.0" encoding="UTF-8" ?>
<suite name="demo" company="wttech" project="blog">
    <test name="first-test" useProxy="rest">
            <resolution width="1200" />
            <sleep duration="1500"/>
            <screen comparator="layout" fuzz="80"/>
            <source comparator="w3c-html5"/>
            <status-codes filterRange="400,600"/>
            <url href="https://wttech.blog"/>

The above definition contains a suite (named “demo”) with a single test (named “first-test”). AET suites may consist of as many tests as you wish. In the test you can see the “collect” definition, which says what data AET should collect and “compare” that says how to check or compare data collected in the previous (“collect”) step. The last section - “urls” - is a simple list of URLs to be tested by AET within the current test - in our case, a single URL of this blog home page.

If you are curious about the details of other elements, feel free to explore the Features section of AET’s Wiki.

When suite definition is ready, the next thing is to call AET API to execute it. You may use cURL to do that, but the most convenient way is to use the AET client script. Download the aet.sh and place it next to the suite XML file. Make sure to give it proper execution rights, check if you have installed all the prerequisites (curl, jq, xmllint) and run the command:

./aet.sh http://aet- my-suite.xml

You should start seeing progress messages soon. When the suite execution finishes, you will get the URL to the report. Open it in your favourite browser.

That’s all!


During this article, we deployed AET instance within a single helm install command:

helm repo add aet-chart https://malaskowski.github.io/aet-helm
helm install my-aet aet-chart/aet -n local --set ingress.enabled=true --create-namespace

on the local Kubernetes cluster. Next, we configured a simple suite of AET tests, executed it and enjoyed the website quality report.

If you have any suggestions or questions, feel free to reach out on my social media or raise an issue in the AET Helm chart repository: https://github.com/malaskowski/aet-helm.

Happy Helming!