GitHub Actions dla automatyzacji testów

Naucz się budować szybkie, niezawodne pipeline'y CI z GitHub Actions. Opanuj składnię workflow, cache'owanie zależności, strategie matrix, zarządzanie sekretami i integrację Playwrighta dla.

Ten post to część 2 serii Jakość w CI/CD. Część 1 omawiała bramki jakości — co musi blokować merge vs. co powinno informować.


Wprowadzenie — workflow to kod

GitHub Actions to natywna platforma CI/CD GitHub. Uruchamia workflow zdefiniowane jako pliki YAML w .github/workflows/ na każdy push, pull request czy zaplanowany trigger.

Zaleta GitHub Actions nad zewnętrznymi serwisami CI:

  • Zintegrowany — natywne UI GitHub, bez autentykacji third-party
  • Szybki — minimalne opóźnienie między pushem kodu a startem pipeline’u
  • Hojny darmowy tier — 2 000 minut/miesiąc dla prywatnych repo, nielimitowane dla publicznych
  • Marketplace — tysiące akcji do wielokrotnego użycia

Ten post omawia podstawowe koncepty budowania pipeline’ów automatyzacji testów z GitHub Actions: składnia workflow, cache’owanie, równoległość, sekrety i integracja Playwrighta.


Anatomia workflow

Workflow to plik YAML, który definiuje:

  • Kiedy się uruchamia (triggery)
  • Gdzie się uruchamia (OS runnera)
  • Co uruchamia (joby i kroki)

Podstawowa struktura workflow

# .github/workflows/ci.yml
name: CI

# Kiedy uruchomić
on:
  pull_request:
  push:
    branches: [main]

# Co uruchomić
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run tests
        run: npm test

Rozbicie:

  • name — nazwa workflow pokazana w UI GitHub
  • on — zdarzenia wyzwalające (pull request, push na main)
  • jobs — niezależne jednostki pracy
  • runs-on — OS runnera (ubuntu-latest, windows-latest, macos-latest)
  • steps — sekwencyjne komendy w ramach joba
  • uses — akcje do wielokrotnego użycia z marketplace
  • run — komendy shellowe

:::tip[Triggery workflow] Użyj pull_request do walidacji przed merge. Użyj push: branches: [main] do checków po merge. Użyj schedule: cron: '0 6 * * *' do codziennych testów smoke przeciwko produkcji. :::


Cache’owanie zależności

Instalowanie zależności przy każdym uruchomieniu jest wolne. npm ci trwa 30–60 sekund. Zrób to 20 razy dziennie, a spalisz 10–20 minut.

GitHub Actions wspiera cache’owanie. Cache’uj katalog node_modules i przywracaj go przy kolejnych uruchomieniach.

Cache’owanie z actions/cache

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'  # Automatycznie cache'uj zależności npm
      
      - run: npm ci
      - run: npm test

Parametr cache: 'npm' w actions/setup-node automatycznie cache’uje ~/.npm na podstawie hasha package-lock.json.

Rezultat: Pierwsze uruchomienie instaluje zależności w 45 sekund. Kolejne uruchomienia przywracają cache w 3 sekundy.

Cache’owanie przeglądarek Playwright

Playwright pobiera binaria przeglądarek przy pierwszej instalacji. To 300+ MB i trwa 20–30 sekund.

jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      
      - run: npm ci
      
      - name: Cache Playwright browsers
        uses: actions/cache@v4
        with:
          path: ~/.cache/ms-playwright
          key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
      
      - run: npx playwright install --with-deps chromium
      - run: npm run test:e2e

Klucz cache bazuje na OS i package-lock.json. Jeśli wersja Playwrighta zmieni się w package.json, cache unieważnia się i przeglądarki pobierają się ponownie.

:::info[Limity cache] Cache GitHub Actions jest limitowany do 10 GB na repozytorium. Stare cache’e są automatycznie usuwane, gdy limit zostanie osiągnięty. Priorytetyzuj cache’owanie zależności nad artefaktami wyjściowymi. :::


Strategie matrix — testowanie na różnych wersjach

Strategie matrix uruchamiają ten sam job wielokrotnie z różnymi konfiguracjami. Testuj na wielu wersjach Node, systemach operacyjnych czy przeglądarkach.

Testowanie na wielu wersjach Node

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      
      - run: npm ci
      - run: npm test

To tworzy trzy równoległe joby: jeden dla Node 18, jeden dla Node 20, jeden dla Node 22.

Testowanie na wielu przeglądarkach

jobs:
  e2e:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        browser: [chromium, firefox, webkit]
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      
      - run: npm ci
      - run: npx playwright install --with-deps ${{ matrix.browser }}
      - run: npm run test:e2e -- --project=${{ matrix.browser }}

To uruchamia testy E2E równolegle na Chromium, Firefox i WebKit.

Koszt: Joby matrix zużywają równoległe minuty runnerów. Darmowy tier zawiera 20 równoległych jobów dla publicznych repo, 5 dla prywatnych.

:::warning[Eksplozja matrix] Matrix z 3 OS × 3 wersje Node × 3 przeglądarki = 27 równoległych jobów. Upewnij się, że Twój przypadek użycia uzasadnia koszt. Dla większości projektów testuj na ubuntu-latest z Node 20 i Chromium. Dodaj pokrycie matrix dla bibliotek LTS lub cross-platformowych aplikacji desktopowych. :::


Zarządzanie sekretami

Automatyzacja testów często wymaga credentials: klucze API, URLe baz danych, tokeny autentykacji.

Nigdy nie hardkoduj sekretów w kodzie ani nie commituj ich do Gita.

GitHub dostarcza sekrety repozytorium i sekrety środowiskowe do bezpiecznego przechowywania credentials.

Dodawanie sekretu

  1. Przejdź do Settings → Secrets and variables → Actions
  2. Kliknij New repository secret
  3. Dodaj nazwę (np. STRIPE_TEST_KEY) i wartość
  4. Zapisz

Używanie sekretów w workflow

jobs:
  integration-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      
      - run: npm ci
      
      - name: Run API tests
        env:
          STRIPE_TEST_KEY: ${{ secrets.STRIPE_TEST_KEY }}
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
        run: npm run test:api

Sekrety są wstrzykiwane jako zmienne środowiskowe w runtime. Są zamaskowane w logach — GitHub automatycznie redaguje wartości sekretów z outputu.

:::tip[Sekrety specyficzne dla środowiska] Użyj environments do separacji sekretów staging i production. Zdefiniuj środowiska staging i production w Settings → Environments, potem odwołuj się do nich w workflow z environment: staging. :::


Akcje specyficzne dla Playwright

Playwright dostarcza oficjalną akcję GitHub: microsoft/playwright-github-action.

Używanie oficjalnej akcji Playwright

jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      
      - run: npm ci
      
      - name: Install Playwright browsers
        run: npx playwright install --with-deps
      
      - name: Run Playwright tests
        run: npm run test:e2e
      
      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 7

Uploadowanie raportów HTML i trace’ów

Playwright generuje raporty HTML i pliki trace przy niepowodzeniu testu. Uploaduj je jako artefakty do debugowania.

      - name: Run Playwright tests
        run: npm run test:e2e
      
      - name: Upload Playwright report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report/
      
      - name: Upload traces
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-traces
          path: test-results/
  • if: always() — uploaduj raport nawet jeśli testy failują
  • if: failure() — uploaduj trace’y tylko przy niepowodzeniu (oszczędza storage)

Dostęp do artefaktów: Przejdź do uruchomienia workflow w UI GitHub → sekcja Artifacts → pobierz zip.

:::info[Trace Viewer] Pobierz pliki trace i otwórz je lokalnie z npx playwright show-trace trace.zip. Trace viewer pokazuje pełny timeline, aktywność sieciową, logi konsoli, snapshoty DOM i screenshoty dla każdej akcji. :::


Praktyczny przykład — pełny workflow CI

Oto gotowy do produkcji workflow łączący build, lint, testy jednostkowe, testy smoke E2E i uploady artefaktów.

name: CI

on:
  pull_request:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      
      - run: npm ci
      - run: npm run build
      
      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: build
          path: dist/

  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm run lint

  unit-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm test

  smoke-tests:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      
      - run: npm ci
      
      - name: Download build artifacts
        uses: actions/download-artifact@v4
        with:
          name: build
          path: dist/
      
      - name: Install Playwright
        run: npx playwright install --with-deps chromium
      
      - name: Run smoke tests
        run: npm run test:e2e:smoke
      
      - name: Upload test report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: smoke-test-report
          path: playwright-report/

Kluczowe funkcje:

  • needs: build — testy smoke czekają na zakończenie joba build
  • Artefakty przekazywane między jobami używając upload-artifact i download-artifact
  • Playwright instaluje tylko Chromium dla szybszych testów smoke
  • Raport uploadowany przy sukcesie lub niepowodzeniu (if: always())

Podsumowanie — automatyzacja jako obywatel pierwszej klasy

GitHub Actions czyni automatyzację testów natywną częścią workflow developmentu. Workflow są wersjonowane z Twoim kodem, reviewowane w pull requestach i wykonywane na infrastrukturze GitHub.

Zasady:

  • Cache’uj zależności aby zminimalizować czas instalacji
  • Używaj strategii matrix rozsądnie — testuj to, co ma znaczenie, nie każdą kombinację
  • Przechowuj sekrety bezpiecznie i nigdy ich nie commituj
  • Uploaduj artefakty do debugowania nieudanych uruchomień
  • Integruj Playwrighta z oficjalnymi akcjami i uploadami trace

Dobrze skonfigurowany pipeline GitHub Actions wykonuje się w poniżej 5 minut dla testów smoke, dostarcza natychmiastową informację zwrotną na pull requestach i kosztuje zero dla publicznych repozytoriów.

Zadanie na ten tydzień: Dodaj cache’owanie zależności do swojego workflow CI. Zmierz zaoszczędzony czas przy typowym uruchomieniu pull requesta. Jeśli nie masz jeszcze CI, zacznij od podstawowego przykładu workflow z tego postu i dodaj jedną komendę testową.


Dalej w tej serii: Część 3 — E2E w Dockerze i efemerycznych środowiskach