Google Lighthouse Logo

Automatisiertes Testing mit Google Lighthouse: Testsuite


Weiter gehts! Nach dem Einstieg in das Testen mit Lighthouse schauen wir uns diesmal Techniken und Ideen an, mit denen die Performance-Tests in die eigene Infrastruktur integriert werden können.

Im vorangegangenen Artikel habe ich darauf verwiesen, dass die Page Experience Signals [1] ab Mai 2021 wichtiger Bestandteil des Rankingsystems von Google werden. In einem der letzten Updates auf dem Google Blog [2] wurde nun verkündet, dass sich das komplette Rollout noch bis August erstrecken wird, um Seitenbetreibern mehr Zeit zu geben, etwaige Anpassungen durchzuführen und selbst die Auswirkungen der Änderungen messen zu können. Zunächst werden die drei Metriken Largest Contentful Paint (LCP), First Input Delay (FID) und Cumulative Layout Shift (CLS) in die Seitenbewertung einfließen. Hier eine kurze Übersicht zu diesen Metriken:

  • LCP [Largest Contentful Paint]
    Hier wird die Ladezeit für das größte Element im Viewport gemessen. Das sind typischerweise Bilder, Videos oder Textblöcke.

  • FID [First Input Delay]
    Dieser Wert gibt an, wie lange es dauert, bis ein Nutzer mit der Seite interagieren kann, beispielsweise Links oder Buttons anklicken oder in einem Dropdown eine Option auswählen.

  • CLS [Cumulative Layout Shift]
    Dabei geht es um visuelle Stabilität. Je weniger Elemente sich während des Ladens der Seite bewegen oder ihre Größe ändern, desto besser ist dieser Wert.

Wenn Sie Nutzer der Google Search Console sind, können Sie die Auswertung Ihrer Seite auch dort finden. Diese basieren auf dem Chrome UX Report (CrUX), das heißt die Daten stammen von Chrome-Nutzern. Wenn Sie eine neue Seite oder Webanwendung haben, kann es einige Zeit dauern, bis genügend Nutzerdaten gesammelt worden sind, um Ihnen dort einen Bericht zu geben. In Zukunft werden sicherlich weitere Metriken aus den Web Vitals in das Ranking einfließen. Da zunächst aber die drei genannten entscheidend sein werden, schauen wir uns diese hier genauer an. In diesem Artikel finden Sie Ansätze, wie Sie diese Metriken in automatisierten Tests nutzen. Werfen wir noch einmal einen Blick auf die hier relevanten Teile des Outputs von Lighthouse:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  "categories": {
    "performance": {
      "title": "Performance",
      "auditRefs": [
        ...
      ],
      "id": "performance",
      "score": 0.69
    }
  },
  "audits": {
    "largest-contentful-paint": {
      "id": "largest-contentful-paint",
      "title": "Largest Contentful Paint",
      "description": "Largest Contentful Paint marks the time at which the largest text or image is painted. [Learn More](https://web.dev/lighthouse-largest-contentful-paint/)",
      "score": 0,
      "scoreDisplayMode": "numeric",
      "numericValue": 12970.919000000002,
      "numericUnit": "millisecond",
      "displayValue": "13.0 s"
    },
    "cumulative-layout-shift": {
      "id": "cumulative-layout-shift",
      "title": "Cumulative Layout Shift",
      "description": "Cumulative Layout Shift measures the movement of visible elements within the viewport. [Learn more](https://web.dev/cls/).",
      "score": 1,
      "scoreDisplayMode": "numeric",
      "numericValue": 0.00909832000732422,
      "numericUnit": "unitless",
      "displayValue": "0.009",
      "details": {
        "type": "debugdata",
        "items": [
          {
            "finalLayoutShiftTraceEventFound": true
          }
        ]
      }
    },
  }

Wir sehen hier nochmal einen Ausschnitt aus der Struktur des JSON-Objektes, das von Lighthouse zurückgegeben wird. Die Metrik FID wird hier nicht betrachtet, da diese nur mit realen Nutzerdaten aus CrUX erhoben wird, nicht mit den Tools, die wie hier unter Laborbedingungen laufen. In den einzelnen Audits findet man sowohl den errechneten Score als auch die Rohdaten. Mit beiden können wir in der eigenen Testsuite arbeiten. Die Scores aus den Kategorien können wir nutzen, um die Gesamtperformance der Seite zu überwachen. Mit den weiteren Rohdaten aus den Metriken lassen sich dann feinere Tests schreiben, mit denen gezielt Schwachstellen identifiziert werden können. Die folgenden Beispiele bauen auf denen im o.g. Einstiegsartikel Artikel auf.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  const lighthouse = require('lighthouse')
  const chromeLauncher = require('chrome-launcher');
  let runLighthouseOnUrl = url => {
    return chromeLauncher
      .launch({chromeflags: ['--headless']})
      .then(chrome => {
          const options = {
            port: chrome.port,
            output: 'json',
            loglevel: 'info',
          };
          return lighthouse(url, options).then(
            results => {
              return chrome.kill().then(() => {
                return {
                  'js': results.lhr,
                  'json': results.report
                }
              })
            }
          )
      })
  }

Setup zur Nutzung von Lighthouse im Skript.

Wir wollen, dass unsere Testsuite uns warnt, falls unsere Seite die Grenze der Bewertungsstufe “Good” unterschreitet. Wir definieren also den Grenzwert entsprechend. Außerdem setzen wir eine Timinggrenze für bestimmte Audits, die wir genauer betrachten.

1
2
3
  let scoreThreshold = 0.9
  let timingThreshold = 1200
  let layoutShiftThreshold = 0.01

Am Beispiel der oben genannten Metriken gibt es hier nun eine kleine Testsuite. Verwendet wird Javascript/Typescript/WebdriverIO. Zunächst werden die Scores für die großen Kategorien überprüft, anschließend werden nochmal explizit die Werte der besprochenen Metriken angeschaut.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import 'mocha'
import { expect } from 'chai'

describe('performance test suite', function () {
  let websiteUnderTest = 'yourwebsite.com'
  let lighthouseResults
  let lighthouseJson

    before(() => {
        return runLighthouseOnUrl(websiteUnderTest).then(r => {
            lighthouseResults = r.js
        })
    })

    describe('Scores', () => {
        it('accessibility', () => {
            expect(lighthouseResults.categories.accessibility.score).to.be.greaterThan(scoreThreshold)
        })
        it('performance', () => {
            expect(lighthouseResults.categories.performance.score).to.be.greaterThan(scoreThreshold)
        })
        it('seo', () => {
            expect(lighthouseResults.categories.seo.score).to.be.greaterThan(scoreThreshold)
        })
        it('best-practices', () => {
            expect(lighthouseResults.categories['best-practices'].score).to.be.greaterThan(scoreThreshold)
        })

    });

    describe('Timings', () => {
        it('LCP', () => {
            expect(lighthouseResults.audits['largest-contentful-paint'].numericValue).to.be.lessThan(timingThreshold)
        })
        it('CLS', () => {
            expect(lighthouseResults.audits['cumulative-layout-shift'].numericValue).to.be.lessThan(layoutShiftThreshold)
        })
    })
    
    describe('Audits', () => {
        it("All Images have alt values", () => {
            expect(lighthouseResults.audits['image-alt'].score === 1)
        })
    })
})
Testsuite mit Tests für Scores in Kategorien und einzelnen Metriken.

Die Testsuite führt zunächst Lighthouse auf der eingetragenen URL aus und die gesammelten Daten werden in einem JSON-Objekt zusammengefasst. Die einzelnen Tests evaluieren dann die gemessenen Werte und stellen anhand von uns konfigurierter Grenzen fest, ob der Test erfolgreich war oder nicht. Die Metrik “Cumulative Layout Shift” hatte oben einen Wert von unter 0.01, dies ist laut der von uns gesetzten Grenzen ausreichend und so gilt der Test als bestanden. Die Metrik “Largest Contentful Paint” allerdings liegt mit etwa 13 Sekunden weit über der Grenze von 1.5 Sekunden, der Test schlägt demnach fehl. Lighthouse gibt zu Metriken, die nicht dem Idealwert entsprechen, auch immer Vorschläge (Opportunities), wie der Wert verbessert werden könnte. An diesem sehr einfachen Beispiel sieht man leicht, wie man mit den Outputs von Lighthouse ganz nach eigenen Bedürfnissen Tests bauen kann.

Sitemap Test mit lighthouse-batch

Als weiteres interessantes Anwendungsbeispiel soll hier das Testen der gesamten Sitemap durch Lighthouse dienen. Mit lighthouse-batch, einem kleinen extra NPM-Package, können Sie Lighthouse einfach auf eine Liste von URLs anwenden.

1
2
  npm install lighthouse-batch
  npx lighthouse-batch -s https://yoursite.com, https://yoursite.com/content/page1, https://yoursite.com/content/page2, ...

Die URLs können zeilenweise in einer TXT-Datei stehen. Dazu extrahieren wir die URLs aus der Sitemap und führen auf der zusammengestellten Liste lighthouse-batch aus.

1
  npx lighthouse-batch -f urls.txt

Lighthouse-batch legt einen Ordner mit einer Zusammenfassung aller Seiten und den einzelnen Berichten an.

Lighthouse CI

Lighthouse CI [3] ist eine Suite, die das Leistungsmessen mit Lighthouse im Bereich CI möglichst unkompliziert machen soll. Dabei werden Reports erstellt, die miteinander verglichen werden können. So können Verbesserungen, aber auch Regressionen festgestellt werden. Lighthouse CI lässt sich leicht in beispielsweise Github einbinden. Folgendes Bild zeigt, wie sich verschiedene Metriken über Reports hin entwickelt haben. In den entsprechenden Dokumentationen finden Sie Ansätze, wie Sie Lighthouse CI in Ihre Infrastruktur einbinden können.

Vergleich zweier Lighthouse Reports
Lighthouse CI Report: Vergleich zweier Versionen einer Website.

Fazit

Die existierenden Lösungen wie Lighthouse CI bieten eine einfache, konfigurierbare Lösung, mit der Sie Reports von Lighthouse verwalten und analysieren können. Sie können aber auch selbst Lighthouse in Ihre automatisierten Tests integrieren und nach Belieben die generierten Daten verwerten. Eines wird aber deutlich: Diese Metrik wird steigenden Einfluss auf die Sichtbarkeit Ihrer Webauftritte haben. Es lohnt sich also in jedem Fall, das eigene CI/CD-Portfolio hiermit zu ergänzen.

Referenzen