Upgrade to Pro — share decks privately, control downloads, hide ads and more …

3._Stashevskiy.pdf

 3._Stashevskiy.pdf

Я занимаюсь не только тестированием, но и разработкой и поддержкой автотестов для наших PHP-сервисов.

В своем докладе хочу рассказать, какие тесты мы пишем, и зачем нам нужны flow-тесты, почему выбрали Codeception и зачем пишем свои модули для него. Расскажу, как мокаем внешние зависимости и как запускаем тесты с точки зрения инфраструктуры.

Badoo Tech

March 16, 2019
Tweet

More Decks by Badoo Tech

Other Decks in Programming

Transcript

  1. Тесты на Codeception для PHP-бэкендов Сташевский Павел QA engineer, Lamoda

  2. None
  3. Зачем нам нужны авто-тесты?

  4. Зачем нам нужны авто-тесты? 1. Не тестировать регресс руками

  5. Зачем нам нужны авто-тесты? 1. Не тестировать регресс руками 2.

    Быстро релизить
  6. Зачем нам нужны авто-тесты? 1. Не тестировать регресс руками 2.

    Быстро релизить 3. Использовать в качестве документации
  7. Зачем нам нужны авто-тесты? 1. Не тестировать регресс руками 2.

    Быстро релизить 3. Использовать в качестве документации 4. Ускорить onboarding новых сотрудников
  8. Какие нам нужны авто-тесты? Unit tests Integration tests System tests

    E2E tests
  9. Какие нам нужны авто-тесты? Unit tests Integration tests System tests

    E2E tests API: REST, SOAP. Тесты на взаимодействия с другими системами, внутреннюю логику.
  10. Какие нам нужны авто-тесты? Unit tests Integration tests System tests

    E2E tests API: REST, SOAP. Тесты на взаимодействия с другими системами, внутреннюю логику. Flow-тесты - тесты на бизнес-флоу для объектов системы (например, заказа). UI-backend тесты.
  11. Какие нам нужны авто-тесты? Unit tests Integration tests System tests

    E2E tests API: REST, SOAP. Тесты на взаимодействия с другими системами, внутреннюю логику. Flow-тесты - тесты на бизнес-флоу для объектов системы (например, заказа). UI-backend тесты. 1) Не важна кроссбраузерность для UI 2) Flow-тесты иногда работают как документация
  12. Почему Codeception? ¯\_(ツ)_/¯

  13. Почему Codeception? 1. Можно писать и запускать одинаково тесты любых

    видов (unit, functional, acceptance)
  14. Почему Codeception? 1. Можно писать и запускать одинаково тесты любых

    видов (unit, functional, acceptance) 2. Многие грабли уже решены, много модулей уже написано
  15. Почему Codeception? 1. Можно писать и запускать одинаково тесты любых

    видов (unit, functional, acceptance) 2. Многие грабли уже решены, много модулей уже написано 3. Во всех проектах, несмотря на немного разные потребности, тесты будут выглядеть одинаково
  16. Codeception. Основы

  17. Стандартные модули 1. PhpBrowser

  18. Стандартные модули 1. PhpBrowser 2. REST

  19. Стандартные модули 1. PhpBrowser 2. REST 3. Db

  20. Стандартные модули 1. PhpBrowser 2. REST 3. Db 4. Cli

  21. Стандартные модули 1. PhpBrowser 2. REST 3. Db 4. Cli

    5. AMQP
  22. Над чем пришлось поработать

  23. 1. Работа с SOAP SOAP - модуль для тестирования SOAP

    WSDL сервисов. SOAP: depends: PhpBrowser endpoint: http://serviceapp/api/v1/ $I->sendSoapRequest('UpdateUser', '<user><id>1</id><name>notdavert</name></user>'); $I->seeSoapResponseContainsXPath('//root/user[@id=1]');
  24. А если несколько endpoint-ов для SOAP?

  25. А если несколько endpoint-ов для SOAP? class SoapWrapper extends \Codeception\Module

    { public function configure( string $endpoint, string $schema ): void { $this->getModule('SOAP')-> _reconfigure( [ 'endpoint' => $endpoint, 'schema' => $schema, ] ); } }
  26. А если несколько endpoint-ов для SOAP? class SoapWrapper extends \Codeception\Module

    { public function configure( string $endpoint, string $schema $I->getModule('Helper\SoapWrapper') ->configure('endpoint2', 'schema2');
  27. 2. Что делать с Kafka?

  28. 2. Что делать с Kafka? Модуля для Kafka нет. Нужно

    написать свой. - Tests\Support\Module\KafkaModule: config: metadata.broker.list: '%REFUNDS__KAFKA_BROKER_LIST%' group.id: '%REFUNDS__KAFKA_CONSUMER_GROUP_ID%' topic_config: offset.store.sync.interval.ms: '0' auto.commit.interval.ms: '500' auto.offset.reset: 'smallest' Переменные окружения
  29. Инициализируем модуль из yml-конфига public function _initialize() { parent::_initialize(); $this->conf

    = new Conf(); foreach ($this->config['config'] as $key => $value) { $this->conf->set($key, $value); } ... $this->consumer = new Consumer($this->conf); ... }
  30. Инициализируем модуль из yml-конфига public function _initialize() { parent::_initialize(); $this->conf

    = new Conf(); foreach ($this->config['config'] as $key => $value) { $this->conf->set($key, $value); } ... $this->consumer = new Consumer($this->conf); ... }
  31. 3. Работа с shell Cli - обертка для shell-команд и

    их output-a. $I->runShellCommand('phpunit'); Но иногда shell-команду нужно запустить не в тестах, а в приложении.
  32. Зачем запускать shell в приложении?

  33. Как запустить shell в приложении? 1) запускать тесты в контейнере,

    где находится приложение 2) запускать тесты в отдельном контейнере, но сделать его таким же как приложение
  34. 4. Работа с файловыми системами

  35. С чем нужно работать • Webdav • FTP/SFTP • AWS

    S3 • Local • и др (Azure, Dropbox, google drive)
  36. Что можно использовать • Webdav - ? • FTP/SFTP -

    модуль FTP • AWS S3 - addon https://github.com/polevaultweb/s3-filesystem • Local - модуль FileSystem • и др (Azure, Dropbox, google drive)
  37. Что можно использовать • Webdav - ? • FTP/SFTP -

    модуль FTP • AWS S3 - addon https://github.com/polevaultweb/s3-filesystem • Local - модуль FileSystem • и др (Azure, Dropbox, google drive) Очень хочется работать со всеми файловыми системами одинаково!
  38. Codeception flysystem https://github.com/lamoda/codeception-flysystem Сейчас поддерживаются sftp и webdav. $fileSystem =

    $I->getFileSystem('sftp'); $fileSystem->clearDir('/path/to/dir'); $fileSystem->writeFile('test.txt', 'Hello world!'); $fileSystem->copyFile('test.txt', 'test_copy.txt'); $fileSystem->deleteFile('test.txt'); $files = $fileSystem->grabFileList('/path/to/dir');
  39. 5. Базы данных в тестах

  40. Основные задачи 1. Как раскатать БД нужной структуры 2. Как

    заполнить БД тестовыми данными 3. Как делать выборки и проверки
  41. Основные задачи 1. Как раскатать БД нужной структуры - Db

    2. Как заполнить БД тестовыми данными - Db, Fixtures 3. Как делать выборки и проверки - DB
  42. Основные задачи 1. Как раскатать БД нужной структуры - Db

    2. Как заполнить БД тестовыми данными - Db, Fixtures 3. Как делать выборки и проверки - DB
  43. Разворачивание БД 1. Поднимаем контейнер с PostgreSQL или MySQL. 2.

    Накатываем все миграции с помощью doctrine migrations.
  44. Разворачивание БД 1. Поднимаем контейнер с PostgreSQL или MySQL. 2.

    Накатываем все миграции с помощью doctrine migrations. Плюсы: 1. Не нужно поддерживать дамп базы для тестов
  45. Создание тестовых данных Используем DoctrineFixturesBundle https://github.com/doctrine/DoctrineFixturesBundle $refund = new Refund();

    $refund->setRefundMethod('cash'); $refund->setSeller(1); $refund->setCountry('RU');
  46. Почему DoctrineFixturesBundle? 1. Проще создавать цепочки связанных объектов 2. Меньше

    дупликации данных, если фикстуры для разных тестов похожи 3. Меньше правок при изменении структуры БД 4. Фикстуры-классы гораздо нагляднее чем массивы
  47. 6. Моки для внешних систем

  48. Правила для моков 1. Мокаем все внешние http-взаимодействия сервиса 2.

    Проверяем не только позитивные, но и негативные сценарии
  49. Wiremock https://github.com/mcustiel/codeception-wiremock-extension 1. Моки поднимаются в отдельном контейнере https://hub.docker.com/r/rodolpheche/wiremock/ 2.

    Мок можно создать статически до тестов 3. Мок можно создать динамически в тестах
  50. Как работает Wiremock Docker Docker APP Wiremock Request Mapping Response

    Data { "request": { "method": "POST", "urlPattern": ".*api.*" } { "code": "ok", "error": null }
  51. Как динамически создать мок $I->expectRequestToWireMock( WireMock:: get(WireMock::urlEqualTo('/some/url')) ->willReturn(WireMock::aResponse() ->withHeader('Content-Type', 'text/plain')

    ->withBody('Hello world!')) ); $I->receivedRequestInWireMock( WireMock::getRequestedFor(WireMock::urlEqualTo('/some/url')) );
  52. 6. Как запускаются тесты

  53. Что используется для запуска тестов 1. Docker - все проекты

    в контейнерах 2. Make - для запуска внутренних команд 3. Bamboo - для CI и деплоев
  54. Запуск тестов на CI (bamboo) 1. make build - билдим

    нужную версию приложения 2. make up - поднимаем окружение a. приложение b. kafka, rabbit и прочее (тоже в docker-e) c. база данных d. накатываем миграции 3. make test - запускаем тесты
  55. Запуск тестов на CI (bamboo) 1. make build - билдим

    нужную версию приложения 2. make up - поднимаем окружение a. приложение b. kafka, rabbit и прочее (тоже в docker-e) c. база данных d. накатываем миграции 3. make test - запускаем тесты 5-10 минут 6-30 минут
  56. А как часто надо запускать тесты? Чем чаще - тем

    лучше!
  57. А как часто надо запускать тесты? 1. На каждый чих

    push 2. На перевод задачи в тестирование 3. На релиз Чем чаще - тем лучше!
  58. None
  59. Вопросы Сташевский Павел [email protected] tech.lamoda.ru