Modern QA2026Bash-скриптинг для QA
Join

Course19 Linux & Command Line

Foundations · Chapter 19

Bash-скриптинг для QA

Updated Jul 2026

Почему QA-инженеры пишут скрипты

Bash-скрипты автоматизируют повторяющиеся QA-задачи: проверка здоровья окружений, подготовка тестовых данных, запуск дымовых тестов, анализ логов и управление тестовой инфраструктурой. Хорошо написанный скрипт экономит часы ручной работы и снижает вероятность человеческой ошибки.

Основы Bash

Структура скрипта

#!/bin/bash
# Строка shebang (первая строка) указывает системе использовать bash

# Немедленный выход при ошибке команды
set -e

# Считать неустановленные переменные ошибкой
set -u

# Ошибка при сбое в конвейере (не только последней команды)
set -o pipefail

# Здесь идёт логика вашего скрипта
echo "Script started at $(date)"

Сделайте скрипт исполняемым: chmod +x my-script.sh

Запуск скрипта: ./my-script.sh или bash my-script.sh

Переменные

# Присвоение (без пробелов вокруг =)
NAME="QA Engineer"
PORT=3000
BASE_URL="https://staging.example.com"

# Использование переменных
echo "Hello, $NAME"
echo "Server is at ${BASE_URL}:${PORT}"

# Значения по умолчанию (использовать умолчание, если переменная не установлена)
TIMEOUT=${TEST_TIMEOUT:-30000}
BROWSER=${TEST_BROWSER:-chromium}

# Подстановка команды (захват вывода команды в переменную)
CURRENT_DATE=$(date +%Y-%m-%d)
GIT_HASH=$(git rev-parse --short HEAD)

Массивы

# Объявление массива
ENVIRONMENTS=("dev" "staging" "preprod")
BROWSERS=("chromium" "firefox" "webkit")

# Доступ к элементам
echo "${ENVIRONMENTS[0]}"          # Первый элемент: "dev"
echo "${ENVIRONMENTS[@]}"          # Все элементы
echo "${#ENVIRONMENTS[@]}"         # Количество: 3

# Итерация по массиву
for env in "${ENVIRONMENTS[@]}"; do
  echo "Testing $env..."
done

Управление потоком выполнения

Условные конструкции

# If/else
if [ "$STATUS" -eq 200 ]; then
  echo "PASS: Service is healthy"
elif [ "$STATUS" -eq 503 ]; then
  echo "WARNING: Service unavailable"
else
  echo "FAIL: Unexpected status $STATUS"
fi

# Сравнение строк
if [ "$ENVIRONMENT" = "production" ]; then
  echo "Running production smoke tests"
fi

# Проверка файлов
if [ -f "test-config.json" ]; then
  echo "Config file exists"
fi

if [ -d "test-results" ]; then
  echo "Results directory exists"
fi

# Логические операторы
if [ "$STATUS" -eq 200 ] && [ "$RESPONSE_TIME" -lt 5 ]; then
  echo "Fast and healthy"
fi

Часто используемые операторы проверки

Оператор Значение Пример
-eq Равно (числовое) [ "$a" -eq 200 ]
-ne Не равно (числовое) [ "$a" -ne 0 ]
-lt Меньше [ "$a" -lt 100 ]
-gt Больше [ "$a" -gt 0 ]
= Равно (строковое) [ "$a" = "hello" ]
!= Не равно (строковое) [ "$a" != "" ]
-f Файл существует [ -f "config.json" ]
-d Каталог существует [ -d "results/" ]
-z Строка пустая [ -z "$VAR" ]
-n Строка не пустая [ -n "$VAR" ]

Циклы

# Цикл for со списком
for browser in chromium firefox webkit; do
  echo "Running tests in $browser"
  npx playwright test --project="$browser"
done

# Цикл for с диапазоном
for i in $(seq 1 5); do
  echo "Test run $i of 5"
done

# Цикл while
ATTEMPTS=0
MAX_ATTEMPTS=10
while [ "$ATTEMPTS" -lt "$MAX_ATTEMPTS" ]; do
  STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/health")
  if [ "$STATUS" -eq 200 ]; then
    echo "Service is up after $ATTEMPTS attempts"
    break
  fi
  ATTEMPTS=$((ATTEMPTS + 1))
  sleep 5
done

Функции

# Определение функции
check_health() {
  local env=$1
  local url="https://${env}.example.com/health"
  local status
  status=$(curl -s -o /dev/null -w "%{http_code}" --max-time 30 "$url")
  if [ "$status" -eq 200 ]; then
    echo "PASS: $env ($status)"
    return 0
  else
    echo "FAIL: $env ($status)"
    return 1
  fi
}

# Вызов функции
check_health "staging"
check_health "production"

Практический скрипт: дымовое тестирование нескольких окружений

#!/bin/bash
# run-smoke-tests.sh -- Health-check multiple environments
set -euo pipefail

ENVIRONMENTS=("dev" "staging" "preprod")
FAIL_COUNT=0
RESULTS=()

check_health() {
    local env=$1
    local url="https://${env}.example.com/health"
    local status
    local time

    status=$(curl -s -o /dev/null -w "%{http_code}" --max-time 30 "$url" 2>/dev/null || echo "000")
    time=$(curl -s -o /dev/null -w "%{time_total}" --max-time 30 "$url" 2>/dev/null || echo "0")

    if [ "$status" -eq 200 ]; then
        RESULTS+=("PASS: $env (HTTP $status, ${time}s)")
        return 0
    else
        RESULTS+=("FAIL: $env (HTTP $status, ${time}s)")
        return 1
    fi
}

echo "=== Environment Health Check ==="
echo "Date: $(date)"
echo "================================"

for env in "${ENVIRONMENTS[@]}"; do
    check_health "$env" || FAIL_COUNT=$((FAIL_COUNT + 1))
done

echo ""
for result in "${RESULTS[@]}"; do
    echo "  $result"
done

echo ""
echo "Results: $((${#ENVIRONMENTS[@]} - FAIL_COUNT))/${#ENVIRONMENTS[@]} passed"

if [ "$FAIL_COUNT" -gt 0 ]; then
    echo "STATUS: SOME ENVIRONMENTS DOWN"
    exit 1
else
    echo "STATUS: ALL ENVIRONMENTS HEALTHY"
    exit 0
fi

Практический скрипт: ожидание готовности сервиса

#!/bin/bash
# wait-for-service.sh -- Wait until a service is ready before running tests
set -euo pipefail

URL="${1:?Usage: $0 <url> [timeout_seconds]}"
TIMEOUT="${2:-120}"
INTERVAL=5
ELAPSED=0

echo "Waiting for $URL to be ready (timeout: ${TIMEOUT}s)..."

while [ "$ELAPSED" -lt "$TIMEOUT" ]; do
    STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$URL" 2>/dev/null || echo "000")

    if [ "$STATUS" -eq 200 ]; then
        echo "Service is ready (HTTP $STATUS) after ${ELAPSED}s"
        exit 0
    fi

    echo "  Not ready (HTTP $STATUS), retrying in ${INTERVAL}s... (${ELAPSED}/${TIMEOUT}s)"
    sleep "$INTERVAL"
    ELAPSED=$((ELAPSED + INTERVAL))
done

echo "ERROR: Service not ready after ${TIMEOUT}s"
exit 1

Использование: ./wait-for-service.sh https://staging.example.com/health 180

Практический скрипт: очистка тестовых данных

#!/bin/bash
# cleanup-test-data.sh -- Remove test data older than N days
set -euo pipefail

DAYS="${1:-7}"
DIRS=("test-results" "screenshots" "videos" "traces" "coverage")

echo "Cleaning up test artifacts older than $DAYS days..."

for dir in "${DIRS[@]}"; do
    if [ -d "$dir" ]; then
        COUNT=$(find "$dir" -type f -mtime +"$DAYS" | wc -l)
        if [ "$COUNT" -gt 0 ]; then
            echo "  Removing $COUNT files from $dir/"
            find "$dir" -type f -mtime +"$DAYS" -delete
        else
            echo "  $dir/ -- nothing to clean"
        fi
    fi
done

echo "Cleanup complete"

Обработка ошибок в скриптах

# Перехват ошибок и очистка
cleanup() {
    echo "Cleaning up..."
    docker compose down -v 2>/dev/null || true
    rm -f /tmp/test-data-*.json
}

# Вызвать cleanup при выходе (успех или ошибка)
trap cleanup EXIT

# Вызвать cleanup при определённых сигналах
trap cleanup SIGINT SIGTERM

Лучшие практики скриптинга

Практика Зачем
Используйте set -euo pipefail Ловить ошибки рано, а не продолжать молча
Используйте local в функциях Предотвращать утечку переменных между функциями
Оборачивайте все переменные в кавычки Предотвращать разбиение слов: "$VAR", а не $VAR
Используйте shellcheck Инструмент статического анализа для обнаружения типичных ошибок bash
Добавляйте сообщения об использовании echo "Usage: $0 <url> [timeout]"
Используйте осмысленные коды возврата 0 = успех, 1 = ошибка, 2 = ошибка использования
Комментируйте неочевидную логику Будущий вы будет благодарен настоящему вам

Практическое упражнение

  1. Напишите скрипт дымового тестирования, который проверяет 3 URL и выводит результаты пройдено/не пройдено
  2. Напишите скрипт ожидания готовности сервиса и используйте его перед запуском тестового набора
  3. Напишите скрипт очистки, удаляющий артефакты тестов старше 7 дней
  4. Установите shellcheck и проверьте им ваши скрипты. Исправьте все предупреждения.
  5. Добавьте обработку ошибок (trap) в один из ваших скриптов
  6. Напишите скрипт, который принимает имя окружения как аргумент и запускает соответствующий набор тестов