Документация Тест-планы в CI/CD

Тест-планы в CI/CD

Эта страница показывает, как встроить тест-планы Mockarty в три наиболее популярные системы непрерывной интеграции: GitHub Actions, GitLab CI и Jenkins. Цель — один шаг CI, который запускает план, отображает прогресс в логе сборки, валит пайплайн на регрессиях и публикует Allure-отчёт как артефакт.

Об URL в примерах: во всех примерах https://mockarty.company.com — это заглушка адреса вашего admin-узла Mockarty. Замените её реальным адресом инстанса. Подробности в Полезных функциях и советах.

Связанные страницы: Тест-планы · Рецепты API тест-планов · Руководство по CLI

Что вы получите

  • Один код выхода — mockarty-cli testplan run --wait возвращает свой код на каждое терминальное состояние.
  • Пять форматов отчёта — mockarty-cli testplan report <runID> --plan <plan> --format <fmt> отдаёт Allure JSON, Allure ZIP, JUnit XML, Markdown или Unified JSON одного и того же прогона. Выберите формат, который уже понимает ваш CI; перезапуск не нужен.
  • Одна команда для мульти-протокольной проверки — functional, fuzz, chaos, load и contract в одном наборе.

Что нужно заранее

  1. Работающий admin-узел Mockarty, доступный CI-раннерам.
  2. API-токен с правами минимум Developer в нужном namespace. Создайте его в Settings → API Tokens или через POST /api/v1/auth/tokens.
  3. Бинарь mockarty-cli, доступный на раннере (из пакета ОС, Docker-образа или со страницы релизов). В примерах используется Linux x86-64; подставьте URL под свою ОС/архитектуру.
  4. Заранее созданный план в нужном namespace. Если ваш пайплайн собирает план динамически — используйте endpoint ad-hoc (см. Разовые master-прогоны).

Контракт кодов выхода

mockarty-cli testplan run --wait --timeout <d> блокируется до терминального состояния прогона и возвращает:

Код Значение
0 Прогон успешно завершён (все элементы passed или skipped).
1 Прогон упал (хотя бы один элемент failed).
2 Прогон отменён (из UI, другим вызовом CLI или через cancel-endpoint).
3 --wait вышел по таймауту до терминального состояния. Сам прогон продолжает идти на сервере.

Считайте любой ненулевой код причиной упасть пайплайну. Коды 2 и 3, как правило, стоит эскалировать дежурному (они означают человеческое вмешательство или нагрузку на инфраструктуру), а не просто ронять тест.

Аутентификация

Все вызовы CLI аутентифицируются через переменную окружения MOCKARTY_API_TOKEN. Храните её как зашифрованный секрет в CI — никогда не коммитьте токены в репозиторий.

export MOCKARTY_URL=https://mockarty.company.com
export MOCKARTY_API_TOKEN=mk_7_...
export MOCKARTY_NAMESPACE=default

MOCKARTY_NAMESPACE задаёт namespace по умолчанию, чтобы не передавать --namespace в каждую подкоманду.

GitHub Actions

Минимальный workflow

name: mockarty-regression

on:
  push:
    branches: [main]
  pull_request:

jobs:
  regression:
    runs-on: ubuntu-latest
    env:
      MOCKARTY_URL: https://mockarty.company.com
      MOCKARTY_API_TOKEN: ${{ secrets.MOCKARTY_API_TOKEN }}
      MOCKARTY_NAMESPACE: default
    steps:
      - name: Install mockarty-cli
        run: |
          curl -sSL -o /tmp/cli.tar.gz https://mockarty.company.com/downloads/mockarty-cli_linux_amd64.tar.gz
          tar -xzf /tmp/cli.tar.gz -C /usr/local/bin mockarty-cli
          mockarty-cli version

      - name: Trigger plan and wait
        id: run
        run: |
          RUN_ID=$(mockarty-cli testplan run '#42' \
              --wait --timeout 15m \
              --output json | jq -r .run_id)
          echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT"

      - name: Download Allure archive
        if: always() && steps.run.outputs.run_id != ''
        run: |
          mockarty-cli testplan report "${{ steps.run.outputs.run_id }}" \
              --plan '#42' --zip ./allure.zip

      - name: Publish Allure artefact
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: allure-report
          path: allure.zip
          retention-days: 30

Защиты if: always() гарантируют, что Allure-архив будет сохранён даже при упавшем прогоне, и разработчики смогут разобрать упавшие элементы. Output steps.run.outputs.run_id доживает до следующего шага, потому что записывается до пропагации ненулевого кода.

Параллельный запуск нескольких планов

Для моно-репозитория с несколькими планами запустите их матрицей:

strategy:
  fail-fast: false
  matrix:
    plan: ['#42', '#43', '#44']
steps:
  - name: Trigger
    run: mockarty-cli testplan run "${{ matrix.plan }}" --wait --timeout 10m

fail-fast: false даёт каждому плану досчитаться, чтобы увидеть все регрессии в одном ревью PR.

GitLab CI

stages:
  - test

mockarty:
  stage: test
  image: curlimages/curl:8.6.0
  variables:
    MOCKARTY_URL: "https://mockarty.company.com"
    MOCKARTY_NAMESPACE: "default"
  before_script:
    - curl -sSL -o /tmp/cli.tar.gz "$MOCKARTY_URL/downloads/mockarty-cli_linux_amd64.tar.gz"
    - tar -xzf /tmp/cli.tar.gz -C /usr/local/bin mockarty-cli
  script:
    - RUN_JSON=$(mockarty-cli testplan run '#42' --wait --timeout 15m --output json)
    - echo "$RUN_JSON" | tee run.json
    - RUN_ID=$(echo "$RUN_JSON" | sed -n 's/.*"run_id":"\([^"]*\).*/\1/p')
    - mockarty-cli testplan report "$RUN_ID" --plan '#42' --zip allure.zip
    - mockarty-cli testplan report "$RUN_ID" --plan '#42' --format junit -o report.junit.xml
  artifacts:
    when: always
    paths:
      - allure.zip
      - run.json
      - report.junit.xml
    expire_in: 30 days
    reports:
      # GitLab нативно подхватит этот файл в виджете merge-request-а.
      junit: report.junit.xml
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == "main"

Сохраните MOCKARTY_API_TOKEN как masked/protected переменную в Settings → CI/CD → Variables.

Мульти-проектные пайплайны

Если план проверяет upstream-сервис, триггерьте Mockarty из downstream-стейджа с needs: и фиксируйте MOCKARTY_URL под окружение:

mockarty:staging:
  extends: .mockarty-template
  variables:
    MOCKARTY_URL: "https://mockarty-staging.company.com"
  environment: staging

Jenkins (declarative pipeline)

pipeline {
    agent any
    environment {
        MOCKARTY_URL       = 'https://mockarty.company.com'
        MOCKARTY_NAMESPACE = 'default'
    }
    stages {
        stage('Install CLI') {
            steps {
                sh '''
                    curl -sSL -o /tmp/cli.tar.gz "$MOCKARTY_URL/downloads/mockarty-cli_linux_amd64.tar.gz"
                    tar -xzf /tmp/cli.tar.gz -C /usr/local/bin mockarty-cli
                '''
            }
        }
        stage('Run plan') {
            steps {
                withCredentials([string(credentialsId: 'MOCKARTY_API_TOKEN',
                                        variable: 'MOCKARTY_API_TOKEN')]) {
                    script {
                        env.RUN_ID = sh(returnStdout: true, script: '''
                            mockarty-cli testplan run '#42' \
                                --wait --timeout 15m \
                                --output json | jq -r .run_id
                        ''').trim()
                    }
                }
            }
        }
    }
    post {
        always {
            withCredentials([string(credentialsId: 'MOCKARTY_API_TOKEN',
                                    variable: 'MOCKARTY_API_TOKEN')]) {
                sh '''
                    if [ -n "$RUN_ID" ]; then
                      mockarty-cli testplan report "$RUN_ID" --plan '#42' --zip allure.zip
                    fi
                '''
            }
            archiveArtifacts artifacts: 'allure.zip', allowEmptyArchive: true, fingerprint: true
            // С Allure Jenkins-плагином:
            // allure includeProperties: false, jdk: '', results: [[path: 'allure']]
        }
    }
}

Храните API-токен в Jenkins Credentials (ID MOCKARTY_API_TOKEN, тип “Secret text”), чтобы он маскировался в логе сборки.

Динамические ad-hoc прогоны

Если содержимое плана зависит от того, что изменил PR — соберите элементы на лету и дёрните endpoint ad-hoc вместо предрегистрации плана. В ответе уже есть run_id; опрашивайте его до завершения через testplan run-status (или SDK WaitForRun):

RUN_ID=$(curl -s -X POST \
    "$MOCKARTY_URL/api/v1/namespaces/$MOCKARTY_NAMESPACE/test-runs/ad-hoc" \
    -H "X-API-Key: $MOCKARTY_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d @adhoc.json | jq -r .run_id)

# опрашиваем run id до терминального статуса:
until mockarty-cli testplan run-status "$RUN_ID" | grep -qiE 'completed|failed|cancelled'; do sleep 5; done

adhoc.json — файл, который CI-скрипт собирает из диффа: каждый изменённый компонент маппится в один элемент (functional, contract, fuzz, …) со ссылкой на UUID ресурса. Полный payload — в Рецептах API.

Публикация в Allure TestOps

ZIP, который возвращает Mockarty, — это Allure-архив результатов (result-*.json + вложения). Подавайте его в любой Allure-инструмент:

# Локальный HTML-отчёт
allure generate allure.zip -o allure-html --clean

# Allure TestOps CLI
allurectl upload allure.zip \
    --project-id $ALLURE_PROJECT_ID \
    --launch-name "mockarty #42"

allurectl — референсный клиент от команды Allure; такая же схема работает для Report Portal, XRay и любого другого инструмента, потребляющего Allure-results.

Как выбрать формат отчёта

Любой прогон Mockarty экспортируется в шесть форматов без повторного запуска плана. Берите тот, который ваш пайплайн уже умеет читать:

Формат Когда брать Пример
zip Allure TestOps, Allure Report HTML, Report Portal. mockarty-cli testplan report $RUN_ID --plan '#42' --zip allure.zip
allure / json Программный разбор (дашборды, свои скрипты). mockarty-cli testplan report $RUN_ID --plan '#42' --format json -o run.json
junit Нативный test-widget GitLab, GitHub Actions test summary, Jenkins JUnit Publisher. mockarty-cli testplan report $RUN_ID --plan '#42' --format junit -o report.junit.xml
markdown Комментарии к PR, Slack-уведомления, email-дайджесты. mockarty-cli testplan report $RUN_ID --plan '#42' --format markdown -o report.md
html Самодостаточный документ для архива, печати в PDF, представления регулятору. mockarty-cli testplan report $RUN_ID --plan '#42' --format html -o report.html
unified Стабильная Mockarty-схема JSON для долгоживущей автоматизации. mockarty-cli testplan report $RUN_ID --plan '#42' --format unified -o report.unified.json

Можно также тянуть сырые байты прямо из REST-endpoint-ов — см. Рецепты API.

Частые ошибки

  • Маленький таймаут — флейковая внешняя зависимость может увести p95 за 10 минут. Задавайте --timeout минимум 1.5x от исторического p95; на load/fuzz-элементы — с запасом.
  • Скачивание CLI на каждой сборке — кэшируйте /usr/local/bin/mockarty-cli между запусками или запекайте в базовый CI-образ.
  • Эфемерный раннер теряет артефакт — всегда публикуйте Allure после триггера и до очистки задачи. Используйте if: always() (GitHub) / when: always (GitLab) / post { always {...} } (Jenkins).
  • Утечка токена — ротируйте MOCKARTY_API_TOKEN по расписанию и ограничивайте его узким namespace и минимальной ролью, при которой ещё возможен testplan run.
  • Неверный namespace — MOCKARTY_NAMESPACE решает, где искать план; расхождение выльется в 404 на триггере.
  • Отменённые прогоны (код 2) — кто-то нажал Cancel в UI или другой CI-job стучится в тот же план. Заведите отдельный план под каждое окружение или сериализуйте стадию мьютексом.

Куда дальше