Jak se zbavit nestabilních end-to-end testů jednou provždy?

Martin Topolánek
27/5/2024
Série 30 testů bez náhodného pádu

Určitě jste se setkali s testy, které běžně projdou, ale občas selžou z neznámého důvodu. Spustíte si tedy ten samý scénář a proběhne bez chyby. V tomto článku vám prozradím, jak s těmito problematickými testy zatočit pomocí správně nastaveného prostředí. Navážeme tak na 5 tipů z minulého článku, které se zaměřovaly na prevenci nestabilních testů. Nyní se podíváme na to, jak je efektivně odhalovat a zbavit se jich jednou provždy.

My k nastavení prostředí využijeme emulace. Emulace je možná pomocí devtools-protocol. Tento protokol je vyvíjen speciálně pro prohlížeče, které používají Blink renderovací jádro. Jinými slovy — v prohlížeči Firefox toto fungovat nebude.

V tomto článku budeme pracovat s knihovnou Playwright, který komunikuje s Devtools protokolem skrz třídu CDPSession (Chrome Devtools Protocol Session).

Spuštění testů v různých prostředích

Pomocí rozhraní CDPSession můžete provádět jakoukoliv akci, kterou lze provést v DevTools. Můžete si tak nastavit emulaci tiskových stránek, emulaci rozostřeného vidění, aj. Úplnou dokumentaci naleznete na stránkách devtools-protocol.

Prostředí s pomalým internetovým připojením

Testovací scénáře často píšete v optimálním prostředí. Při běžném manuálním testování vaše webová aplikace dostává většinou odezvu z backendu okamžitě. Proto vás při psaní scénářů mnohdy nenapadnou různé skalní případy, ve kterých se aplikace může ocitnout.

Tyto scénáře spadnou jen výjimečně a důvod na první pohled není zřejmý. Příčinu objevíte nejspíš až při detálním zkoumání trace souboru. Abyste se těmto spadnutým testům vyhli, máte možnost spustit si scénář s pomalejším síťovým připojením. Při manuálním testováním byste toho docílili přes DevTools. V záložce Network byste změnili hodnotu z No throttling na hodnotu například Slow 3G.

Nyní si ukážeme, jak toho stejného, lze docílit v chrome instanci, kterou spouští Playwright:

import { chromium } from '@playwright/test'

const NETWORK_CONDITIONS = {
  'Slow 3G': {
    downloadThroughput: ((500 * 1000) / 8) * 0.8,
    uploadThroughput: ((500 * 1000) / 8) * 0.8,
    latency: 400 * 5,
    offline: false,
  },
  'Fast 3G': {
    downloadThroughput: ((1.6 * 1000 * 1000) / 8) * 0.9,
    uploadThroughput: ((750 * 1000) / 8) * 0.9,
    latency: 150 * 3.75,
    offline: false,
  },
}

const browser = await chromium.launch()
const context = await browser.newContext({
  viewport: { width: 1600, height: 800 },
  baseURL: 'https://google.com/',
})
const page = context.newPage()
const cdpSession = context.newCDPSession(page)

if (process.env.NETWORK_CONDITION) {
  await cdpSession.send(
    'Network.emulateNetworkConditions',
    NETWORK_CONDITIONS[process.env.NETWORK_CONDITION],
  )
}

await page.goto('/');

Síťové zpomalení pak můžete ovládat pomocí nastavených env.

Prostředí se sníženým CPU výkonem

Webové aplikace se často chovají jinak v závislosti na rychlosti CPU vašeho počítače. Odezvy z aplikace jsou většinou pomalejší. Pokud však odladíte scénáře pro toto pomalejší prostředí, můžete zvážit i větší pararelizaci vašich testů. Platí, že čím víc pararelně spuštěných testů, tím je větší zátěž na CPU a taky větší spotřeba RAM.

Toho lze opět při manuálním testování docílit přes emulaci v DevTools. CPU můžete totiž ovlivnit v záložce Performance a u CPU byste změnili hodnotu z No throttling na hodnotu například 6x slowdown. Nicméně je důležité mít na paměti, že zpomalení CPU je relativní vůči vašemu procesoru.

Relativní zpomalení vašeho CPU můžete docílit i v Playwright testech:

import { chromium } from '@playwright/test'

const browser = await chromium.launch()
const context = await browser.newContext({
  viewport: { width: 1600, height: 800 },
  baseURL: 'https://google.com/',
})
const page = await context.newPage()
const cdpSession = context.newCDPSession(page)

if (process.env.THROTTLING_RATE) {
  await cdpSession.send(
    'Emulation.setCPUThrottlingRate', {
      rate: parseInt(process.env.THROTTLING_RATE),
  })
}

await page.goto('/');

Zpomalení CPU pak můžete ovládat pomocí nastavených env.

Tip na závěr

Navrhuji spustit si vaši sadu testovacích scénářů proti těmto pomalejším prostředím. Při opravování testů se držte 5 tipů, které jsem zmiňoval v předchozím článku.

Abyste předešli dalším nespolehlivým scénářům, doporučuji každý nový testovací scénář spouštět v těchto pomalejších prostředích. Můžete si napsat pomocný skript pro tento případ:

const execSync = require('child_process').exescSync

const arg = process.argv[2] || ''

execSync('cross-env THROTTLING_RATE=10 yarn test ' + arg, { stdio: [0, 1, 2] })
execSync('cross-env NETWORK_CONDITION="Fast 3G" yarn test ' + arg, {
  stdio: [0, 1, 2],
})

Skript pak budete spouštět pomocí tohoto příkazu:

node script.js <cesta-k-souboru>