Acceptance Testing - статья от Ian M. Jones

Вы когда-нибудь испытывали радость от проведения приемочного тестирования? Для нашей команды в Delicious Brains тестирование наших релизов в прошлом было одной из самых страшных задач в списке дел. Мы поддерживаем наши плагины высоким стандартом качества, поэтому это необходимо, но ручные тесты утомительны и могли занимать часы дорогостоящего времени .

Недавно мы решили, что настало время исправить это.
Представьте, я + мои начинания автоматизации процесса приемочного тестирования.

Это будет работать? Будут ли они спасать нас от часов рутинных тестов, утомляющих мозг? Мы будем лучше?

Читайте дальше, чтобы узнать больше о том, как формируется автоматизация тестирования наших плагинов перед выпуском - включая то, как мы вручную тестировали в прошлом, и посмотрим на некоторые из автоматизированных приемочных тестов, которые мы уже реализовали.

Будьте осторожны, это не учебник! Приемочное тестирование может быть довольно сложным, поэтому, пока я покажу код, он далек от завершения , чтобы дать вам представление о том, как мы это настраиваем.

Что такое Acceptance Testing?

Так что же из себя представляет Acceptance Testing и почему мы это делаем?

Для Delicious Brains Acceptance Testing - это процесс тестирования финальной сборки предстоящего выпуска плагина, чтобы убедиться, что он готов для наших клиентов. В других (крупных) компаниях, когда «клиент» или их представитель тестируют релиз кандидата и, надеюсь, прогоняет тесты. После их прохождения он выпущен в production.

Acceptance Testing сильно отличаются от модульных тестов тем, что вы тестируете программное обеспечение с точки зрения клиента, проверяя все действия и сценарии, которые клиент должен и не должен выполнять. При тестировании модулей вы тестируете отдельные классы и функции, составляющие API для программного обеспечения. При Acceptance Testing вы нажимаете кнопки, ссылки, ввод текста, подсказки для чтения и обычно взаимодействуете с программным обеспечением в качестве пользователя.
Без Acceptance Testing вы не можете быть уверены, что программное обеспечение будет работать, как ожидается, при использовании конечным пользователем. Это лучший способ убедиться, что у вас есть качественный продукт, подходящий для ваших клиентов.

Ручной метод

За последние 3 года я участвовал во многих выпусках WP Migrate DB Pro и WP Offload S3 . Каждый из них включает мучительный период тестирования. Никто в команде не любит тестировать release, поскольку это очень медленный период , ручной и рутинный , проходящий через постоянно растущую группу тест кейсов, которые подробно описывают каждый шаг тестов.

На приведенном выше снимке экрана показана небольшая часть сценария release тестирования, который мы обычно используем для WP Offload S3. Сценарий имеет 116 мануальних шагов, которые часто требуют дополнительной ручной проверки данных или объектов базы данных на S3. Если тест не прошел, вы помещаете «X» в столбец «Результат», который превращает ячейку в красный цвет или «P», если она проходит, что превращает ячейку в зеленый цвет.
Вы видите эти ячейки «PPP» на скриншоте? Далее по сценарию есть две строки, которые говорят вам вернуться назад и выполнить все эти шаги снова для многоуровневых установок на основе домена и подкаталога! Душераздирающий опыт…

У нас также есть сценарии для наших приложений Amazon Web Services, WP Offload S3 Lite и WP Offload S3, а также Easy Digital Downloads, WooCommerce, Enable Media Replace, Meta Slider, Advanced Custom Forms и WPML-интеграции.
И это только сценарии, связанные с WP Offload S3. WP Migrate DB Pro также имеет набор сценариев для тестирования WP Migrate DB, WP Migrate DB Pro и сред Media Files, CLI и Multisite Tools.
При тестировании релиза 2-3 разработчики привязаны примерно на всю неделю, проверяя все тесты для всех компонентов продукта. Часто мы используем формат «преследования», когда один разработчик начинает тестирование, обычно начиная с версии «Lite». Как только какие-либо проблемы были проверены для плагина Lite, они переходят на версию «Pro» со вторым разработчиком, начиная с тестирования Lite. Если требуется третий разработчик, волонтера ищут в одной из других команд плагина, чтобы кто-то, не знакомый с выпуском функции, не стал терять время и начал тестировать версию Lite после того, как второй разработчик перешел на Pro. Иногда на небольшом выпуске исправления ошибок мы делаем «перекрестный» формат, первый разработчик начнет с одного конца скриптов, а второй начнет с другого конца, перейдя через половину, чтобы сэкономить некоторое время.
Как вы, вероятно, могли догадаться, это не популярная часть цикла выпуска для наших плагинов. Период разработки может затянуться намного дольше, чем он, вероятно, должен. Плюс мы можем потерять на тестировании дорогостоящего времени разработчика, но качество невероятно важно для нас как компании, поэтому требуется этот этап тестирования. В прошлом мы боролись с наймом профессиональных тестировщиков, которые могут обрабатывать наши самые технические продукты.
В прошлом году в нашей компании была презентация в Вене , где была затронута тема тестирования. После этого мы решили автоматизировать приемочное тестирование, чтобы освободить часть времени. Я вызвался начать писать тесты для WP Offload S3!

Как мы автоматизируем

Выбор технологии
Мы используем #tools:codeception для проведения наших приемочных тестов. Некоторые из нашей команды уже имели некоторый опыт работы с Codeception, и, откровенно говоря, на самом деле нет других вариантов, если вы хотите написать свои тесты на #PHP, поэтому выбор очевидный, если не единственный.
Самая большая проблема, с которой мы сталкивались в прошлом с Codeception, заключалась в создании серверов Selenium или PhantomJS, необходимых для запуска тестов. Selenium и PhantomJS предоставляют headless веб-браузеры, которые могут управляться через API для подключения к вашему тестовому сайту и отвечать на такие команды, чтобы взаимодействовать со ссылками и кнопками, вводить текст или сообщать содержимое полей или DOM, запускать JavaScript и так далее. Эти серверы могут быть немного сложными для настройки. Они могут также требовать Java или другие зависимости, которые вы не хотите устанавливать, и в идеале должны быть запущены в фоновом режиме.
Еще одна проблема с проведением приемочного тестирования - это обеспечение того, что у вас есть тестовый веб-сайт или два, которые находятся в известном чистом состоянии. .
Чтобы устранить вышеупомянутые потенциальные проблемы, я решил запустить весь тестовый процесс в контейнерах #Docker, чтобы каждый запуск имел согласованную среду, которая может быть автоматически развернута за считанные секунды.

Docker Compose
Чтобы держать вещи относительно гибкими, мы запускаем несколько контейнеров, которые работают в унисон, потому что мы используем компоновку контейнеров.

version: '2'
services:
  #
  # Base services.
  #
  data:
    image: deliciousbrains/data@sha256:6fbc27c3c84c0e4d40b261e2c8246a2065a96916481ab475facfcd6e81548f31
    labels:
      com.deliciousbrains.service: "data"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    command: ["echo", "Data Container"]

  repo:
    image: deliciousbrains/data@sha256:6fbc27c3c84c0e4d40b261e2c8246a2065a96916481ab475facfcd6e81548f31
    labels:
      com.deliciousbrains.service: "repo"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes_from:
      - data
    volumes:
      - ../:/mnt/build
    command: ["echo", "Repo Data Container"]


  #
  # Run acceptance tests (eventually).
  #
  acceptance-tests-base:
    image: deliciousbrains/php-cli@sha256:c2bf45814327891aa8a9a72fb3cd1da9c04dde28f81588a0fccaf570c7a9ca7c
    labels:
      com.deliciousbrains.service: "acceptance-tests-base"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    entrypoint: ["/tmp/run-acceptance-tests.sh"]

  acceptance-tests:
    extends:
      service: acceptance-tests-base
    labels:
      com.deliciousbrains.service: "acceptance-tests"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes_from:
      - repo
    volumes:
      - ./php-cli/run-acceptance-tests.sh:/tmp/run-acceptance-tests.sh
    depends_on:
      - plugin-build
    links:
      - web-server
      - selenium-server-chrome

  acceptance-tests-phantomjs:
    extends:
      service: acceptance-tests-base
    labels:
      com.deliciousbrains.service: "acceptance-tests-phantomjs"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes_from:
      - repo
    volumes:
      - ./php-cli/run-acceptance-tests.sh:/tmp/run-acceptance-tests.sh
    depends_on:
      - plugin-build
    links:
      - web-server
      - phantomjs-server

  acceptance-tests-chrome:
    extends:
      service: acceptance-tests-base
    labels:
      com.deliciousbrains.service: "acceptance-tests-chrome"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes_from:
      - repo
    volumes:
      - ./php-cli/run-acceptance-tests.sh:/tmp/run-acceptance-tests.sh
    depends_on:
      - plugin-build
    links:
      - web-server
      - selenium-server-chrome

  acceptance-tests-firefox:
    extends:
      service: acceptance-tests-base
    labels:
      com.deliciousbrains.service: "acceptance-tests-firefox"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes_from:
      - repo
    volumes:
      - ./php-cli/run-acceptance-tests.sh:/tmp/run-acceptance-tests.sh
    depends_on:
      - plugin-build
    links:
      - web-server
      - selenium-server-firefox

  phantomjs-server:
    image: wernight/phantomjs
    labels:
      com.deliciousbrains.service: "phantomjs-server"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    expose:
      - "8910"
    links:
      - web-server
    command: ["phantomjs", "--webdriver=8910"]

  selenium-server-chrome:
    image: selenium/standalone-chrome
    labels:
      com.deliciousbrains.service: "selenium-server-chrome"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    expose:
      - "4444"
    links:
      - web-server

  selenium-server-firefox:
    image: selenium/standalone-firefox
    labels:
      com.deliciousbrains.service: "selenium-server-firefox"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    expose:
      - "4444"
    links:
      - web-server


  #
  # Plugins Build Setup.
  #
  plugin-build:
    image: deliciousbrains/php-cli@sha256:c2bf45814327891aa8a9a72fb3cd1da9c04dde28f81588a0fccaf570c7a9ca7c
    labels:
      com.deliciousbrains.service: "plugin-build"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes_from:
      - repo
    volumes:
      - ./php-cli/build-plugins.sh:/tmp/build-plugins.sh
    entrypoint: ["/tmp/build-plugins.sh", "-c"]


  #
  # Web Server Setup.
  #
  web-data:
    image: deliciousbrains/data@sha256:6fbc27c3c84c0e4d40b261e2c8246a2065a96916481ab475facfcd6e81548f31
    labels:
      com.deliciousbrains.service: "web-data"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes_from:
      - data
    volumes:
      - ./web-server/html/phpinfo.php:/var/www/html/phpinfo.php
      - ./web-server/html/index.html:/var/www/html/index.html
      - ./web-server/html/db-test.php:/var/www/html/db-test.php
    command: ["echo", "Web Data Container"]

  web-server:
    image: nginx:1.11-alpine
    labels:
      com.deliciousbrains.service: "web-server"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes_from:
      - web-data
    volumes:
      - ./web-server/nginx/server_common.conf:/etc/nginx/server_common.conf
      - ./web-server/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./web-server/nginx/local-wp.conf:/etc/nginx/conf.d/local-wp.conf
      - ./web-server/nginx/remote-wp.conf:/etc/nginx/conf.d/remote-wp.conf
    expose:
      - "80"
#    ports:
#      - "80:80"
    links:
      - php-server
    networks:
      default:
        aliases:
          - local-wp
          - remote-wp
          - local-ms
          - remote-ms

  php-server:
    image: deliciousbrains/php-server@sha256:cedfed62c55a4650e1400fe6f2f708b1835629064ebda342daf7580334e1e332
    labels:
      com.deliciousbrains.service: "php-server"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes_from:
      - web-data
    expose:
      - "9000"
    links:
      - db-server

  db-data:
    image: alpine:3.4
    labels:
      com.deliciousbrains.service: "db-data"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes:
      - /var/lib/mysql
    command: ["echo", "DB Data Container"]

  db-server:
    image: mariadb:10.1
    labels:
      com.deliciousbrains.service: "db-server"
      com.deliciousbrains.project: "${COMPOSE_PROJECT_NAME}"
    volumes_from:
      - db-data
    environment:
      MYSQL_ROOT_PASSWORD: wp

В приведенном выше представлении содержится текущий файл docker-compose.yml для приемочного тестирования WP Offload S3. Я не собираюсь вдаваться в подробности здесь, но, как вы видите, есть комбинация контейнеров данных, которые обеспечивают согласованные точки монтирования для другого веб-сервера, сервера базы данных, серверов Selenium / PhantomJS, служб тестового запуска и создания плагинов. Некоторые службы зависят от других, чтобы функционировать, например, служба acceptance-tests по умолчанию, которая запускает тесты Codeception, тестирует ссылки поскольку она не может ничего сделать, если они не работают.

Выше вы можете увидеть структуру папки докеров в репозитории WP Offload S3. У нас есть пользовательские Docker image, которые мы создаем для связанных с data , php-cli и php-server которые необходимы для удовлетворения требований для запуска WordPress или Codeception или для создания наших плагинов.
Итак, в качестве небольшого бонуса я создал примера docker/build-plugins.sh который строит наши плагины через контейнер, то есть разработчику даже не нужно устанавливать такие вещи, как #grunt , #yarn или #compass на своей машине. Это заставляет нас запускать приемочные тесты на выделенном сервере сборки, или, может быть, через Travis CI, как мы делаем наши модульные тесты.
В папке run-tests.sh есть еще несколько удобных сценариев, но самым важным скриптом является run-tests.sh .

#!/usr/bin/env bash

cd `dirname $0`

source ./.env

while getopts "u:p:h:d:ct:z:s:vkge:" ARG
do
	case ${ARG} in
	    e)  TEST_ENV=$OPTARG;;
	esac
done

TEST_ENV=${TEST_ENV-""}
RUN_WITH=""

RUN_CHROME=`echo "${TEST_ENV}" | sed 's/chrome//'`
if [ "${TEST_ENV}" != "${RUN_CHROME}" ]
then
    RUN_WITH="${RUN_WITH}-chrome "
fi

RUN_FIREFOX=`echo "${TEST_ENV}" | sed 's/firefox//'`
if [ "${TEST_ENV}" != "${RUN_FIREFOX}" ]
then
    RUN_WITH="${RUN_WITH}-firefox "
fi

RUN_PHANTOMJS=`echo "${TEST_ENV}" | sed 's/phantomjs//'`
if [ "${TEST_ENV}" != "${RUN_PHANTOMJS}" ]
then
    RUN_WITH="${RUN_WITH}-phantomjs "
fi

for BROWSER in "${RUN_WITH}"
do
    docker-compose run --rm acceptance-tests${BROWSER} $@
done

Запуск docker/run-tests.sh в командной строке - все, что требуется для запуска всего набора приемочных тестов. Однако вы можете дать ему аргументы, чтобы переключиться с Selenium / Chrome по умолчанию на что-то вроде Selenium / Firefox или PhantomJS. Например, чтобы запустить тесты с Firefox, мы будем использовать :

docker/run-tests.sh -e firefox

В следующем разделе вы узнаете о наиболее важном аргументе, который мы часто используем при выполнении приемочных тестов, -t .

Codeception

При использовании Codeception для запуска ваших приемочных тестов вы можете структурировать свои сценарии в красивую иерархию папок, и они будут проходить их в алфавитном порядке, найдя что-либо, заканчивающееся на «-Cept.php».

Мы разделили наши приемочные тесты на отдельные папки с плагинами, префиксные папки с 2-значным номером. Он похож внутри папок: каждый тест имеет 3-значный префикс, чтобы гарантировать, что они выполняются в том порядке, в котором мы хотим. 3-значные префиксы свободно группируют тестовые сценарии в предметные области, такие как установка / настройка, настройки, загрузка медиафайлов, редактируемые носители и т. Д.
Мы можем запускать все тесты плагина самостоятельно:

docker/run-tests.sh -t 01-amazon-s3-and-cloudfront

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

docker/run-tests.sh -t 01-amazon-s3-and-cloudfront/01-002-DeactivateParent-Cept

Большинство сценариев зависят от других сценариев для основных предварительных условий установки. Например, сценарий acceptance/01-amazon-s3-and-cloudfront/01-002-DeactivateParent-Cept.php выглядит следующим образом:

<?php include '01-001-ActivatePlugin-Cept.php'; include COMMON_TESTS_DIR . 'DeactivateParentStd.php';

01-001-ActivatePlugin-Cept.php сценарий 01-001-ActivatePlugin-Cept.php также очень прост:

<?php include '_bootstrap.php'; include COMMON_TESTS_DIR . 'ActivatePlugin.php';

Codeception любит, чтобы его имена функций читались как действия, которые вы принимаете. Таким образом, в приведенном выше коде вы можете видеть такие вещи, как «I log in as admin», «I am on Plugins page» или «I see plugin activated».

Вот как выглядят запуск тестов:

Помогает ли это?

О да, автоматизация приемочных тестов наиболее определенно помогает уменьшить боль при тестировании сборки.
В настоящий момент 75% тестов, которые мы запускали вручную для Amazon Web Services и WP Offload S3 Lite, покрываются автоматическими приемочными тестами . :tada:
Это огромная победа для нас. Устранение необходимости вручную выполнять все эти тесты не только экономит время при тестировании WP Offload S3 Lite, но так как большинство тестов необходимо повторно запускать для WP Offload S3 и WP Offload S3 Assets, мы экономит время в разы.
Мы сохраняем как минимум пару дней на тестирование для каждого разработчика (хотя, вероятно, больше). Это от четырех до шести дней тестов до онемения мозга, сохраненных при каждом выпуске!
Автоматизированные приемочные тесты также более тщательны, чем ручные тесты, которые у нас были. Наши приемочные тесты поймали большое количество существующих ошибок.
Обе наши команды WP Offload S3 и WP Migrate DB Pro намного счастливее, зная, что самые утомительные тесты теперь обрабатываются автоматическими тестами.

  • Прохожу Acceptance тесты
  • Зачем, это трата времени

0 участников

3 лайка