SkillAgentSearch skills...

2fingers

simple PHP framework for REST API black-box functional testing

Install / Use

/learn @2gis/2fingers
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

2fingers

Кратко о сути

2fingers - это простой PHP-фреймворк для написания параметризованных функциональных тестов для вашего JSON-based REST API.

Инструмент позволяет тестировать API методом полноценного чёрного ящика и заточен под использование реальных случайных данных из тестовой БД.

Для запуска тестов используется PHPUnit, для выполнения запросов - HTTP-клиент Guzzle, для управления зависимостями - composer.

Рекомендуется к использованию под ОС семейства Linux.

Обратите внимание, в репозитории лишь базовые классы и примеры, фреймворк нужно адаптировать под архитектуру вашего API и структуру БД!

По любым вопросам касательно 2fingers пишите на leaxfm@gmail.com или p.asanov@flamp.ru.

Деплоймент и запуск

Требуемые компоненты

  • для запуска 2fingers требуются установленные пакеты php5-cli (версия PHP не ниже 5.4), php5-pgsql, php5-curl.
  • требуются установленные composer и phpunit

Установка composer и phpunit

  • скачиваем файл .phar с оф. сайта
  • переносим фарку в папку с другими исполняемыми файлами: sudo mv phpunit.phar /usr/local/bin/phpunit
  • заходим в /usr/local/bin и превращаем файл в исполняемый: sudo chmod u+x phpunit
  • теперь можно из любой папки писать phpunit <something>
  • аналогично для composer

Копируем проект из репозитория

git clone git@github.com:2gis/2fingers.git

Подтягиваем необходимые зависимости

composer install

Создание конфига

Переименовываем шаблон конфига server.php.dist в server.php, затем прописываем в получившийся конфиг хост и базу данных.

cd config/
cp server.php.dist server.php
vim server.php

Запуск тестов

Тесты на API лежат в папке tests. Запускаем их с помощью phpunit.

phpunit tests/

Внутри тесты удобно разбивать по директориям в соответствии, например, с разделами документации (Auth, Users и т.д.). Соответственно, можно запускать тесты из конкретного раздела:

phpunit tests/Users/

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

phpunit tests/AddSomethingTest.php

При запуске можно консольными параметрами указать хост, БД и параметр verbose, если не хочется менять их значения в конфиге server:

phpunit tests/AddSomethingTest.php --host=test.test --dbhost=test.test --dbname=test
phpunit tests/AddSomethingTest.php --verbose=false

Параметр verbose показывает, нужно ли отображать развёрнутую отладочную информацию (параметры запроса, JSON-ответ) для упавших тестов в консоль. По умолчанию он всегда true.

Также есть возможность запускать наборы тестов (test suites):

phpunit --testsuite regression

Формировать такие наборы можно в конфиге phpunit.xml.

###Примеры запуска

Так выглядит успешно прошедшая сборка:

p.asanov@uk-rnd-266:~/2fingers$ phpunit tests/2.0/Comments/
 
( ͡° ͜ʖ ͡°) starting 2fingers...
 
PHPUnit 4.3.5 by Sebastian Bergmann.
 
Configuration read from /home/p.asanov/2fingers/phpunit.xml
...............................................................  63 / 146 ( 43%)
............................................................... 126 / 146 ( 86%)
....................
 
Time: 43.17 seconds, Memory: 16.50Mb
 
OK (146 tests, 1135 assertions)

Каждая точка - это успешно прошедший тест-кейс. Всего в папке Comments 12 классов с тестами, их запуск даёт нам суммарно 146 тест-кейсов, которые суммарно дают нам 1135 проверок атрибутов в JSON. Если тест упал, вместо точки будет красная буква F (проверка не прошла) или E ( в тесте произошла ошибка). Кроме того, в консоль по умолчанию выводится отладочная информация:

....................F...
 
Time: 6.48 seconds, Memory: 8.00Mb
 
There was 1 failure:
1) AddReviewTest::testAddReview with data set #20 ('141265770608749', 'rDlJ4zSUks', 5, true, NULL, 0, 403)
===============================================================
POST https://jazz.precise.flamp.test/api/2.0/reviews
 
filial_id = 141265770608749
text = rDlJ4zSUks
rating = 5
is_recommended = true
photos = 
 
HEADERS:
Accept: application/json;q=1;depth=1;scopes={"review":{}}
Authorization: Bearer 271b3df12efbbace6ff88ea98f964aa52da32a4
---------------------------------------------------------------
{
    "code": 401,
    "status": "error",
    "error_code": 0,
    "message": "У вас нет прав доступа для выполнения запроса"
}
---------------------------------------------------------------
 
Failed asserting that 401 matches expected 403.
 
/home/p.asanov/2fingers/tests/2.0/BaseFlampApiTest.php:79
/home/p.asanov/2fingers/tests/BaseTest.php:62
/home/p.asanov/2fingers/tests/2.0/Reviews/AddReviewTest.php:89
                                         
FAILURES!                              
Tests: 24, Assertions: 122, Failures: 1.

Настройки для PHPStorm

Если вы собираетесь разрабытавать тесты на 2fingers, настройте PHPStorm, чтобы дебаг и запуск тестов работали корректно из самой IDE:

  • Настройки - PHP: убедитесь, что в графах PHP Language Level и Interpretator указана корректная версия PHP, а в настройках интепретатора указан корректный путь до PHP (напр. /usr/bin)
  • Настройки - PHPUnit: убедитесь, что выбран пункт Use custom autoloader и указан корректный путь к PHPUnit (напр. /usr/local/bin/phpunit), в качестве Default configuration runner указан 2fingers/phpunit.xml, а в качестве Default bootstrap file - 2fingers/bootstrap.php.

Как писать тесты в 2fingers

Структура теста

Создаём файл вида AddSomethingTest.php, содержащий в себе PHP-класс AddSomethingTest. Названия файла и класса должны совпадать и оканчиваться на Test.

Кроме этого, класс должен обязательно расширять базовый класс BaseTest:

class AddSomethingTest extends BaseTest
{
}
<p align="center"> <img src="https://hsto.org/files/8ac/516/8e9/8ac5168e93354774b488f348f506d489.png" alt=""> </p>

Параметризованный тест- это тест-шаблон, который принимает на вход N наборов данных, а на выходе выдает N реальных тестов.

Поэтому внутри класса AddSomethingTest должны быть 2 обязательных метода:

  • дата провайдер, т.е. источник данных (тест-кейсов, тестовых наборов) для параметризованного теста - providerAddSomething
  • метод, представляющий себой непосредственно исполняемый параметризованный тест - testAddSomething

Имя теста должен обязательно начинаться со слова test, имя дата провайдера - со слова provider. В остальном желательно, чтобы названия соответствовали имени класса, для понятности.

Чтобы testAddSomething знал, откуда брать тестовые наборы, нужно указать для него дата провайдер с помощью аннотации @dataProvider:

class AddSomethingTest extends BaseTest
{
    public function providerAddSomething() {}
 
    /**
     * @dataProvider providerAddSomething
     */
    public function testAddSomething() {}
}

Пишем метод test

Метод testAddSomething и является, собственно, параметризованым тестом, прогоняемым на нескольких тестовых наборах.

Что же должен делать такой тест? Очевидно - установить параметры запроса к API, выполнить этот запрос и проверить ответ!

Кроме того, т.к. тест параметризованный, на вход он должен принимать из дата провайдера параметры (тестовый набор) в виде списка аргументов.

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

Теперь понятно, как написать метод test:

  • задаем список аргументов для метода, соответствующий тестовому набору
  • задаём HTTP-метод, метод API, параметры запроса (если они есть): просто присваиваем <br>$this->имя_параметра нужное значение.
  • выполняем запрос с помощью метода send(). При этом можно указать роль методом asUser(), либо напрямую аксесс токен методом withAccessToken(). При необходимости можно указать протокол методом overProtocol(). Все эти методы вызываются через $this->, и их можно вызывать цепочно, т.е. друг за другом через стрелочку. Разумется, send() в цепочке всегда должен быть последним.
  • проверяем код ответа с помощью метода waitFor()
public function testAddReview($filial_id, $text, $rating, $is_recommended,
                              $photos, $user_id, $expected_code)
{
    // Задаём http-метод, метод API, параметры запроса и scopes
    $this->http_method = 'POST';
    $this->method = "reviews";
    $this->params = [
        'filial_id' => $filial_id,
        'text' => $text,
        'rating' => $rating,
        'is_recommended' => $is_recommended,
        'photos' => $photos,
    ];
    $this->scopes = 'review';
 
    // Выполняем запрос и проверяем коды ответа
    $this->asUser($user_id)->send();
    $this->waitFor($expected_code);
}

Пишем dataProvider

В методе providerAddSomething формируются тестовые наборы. Чтобы сформировать такой набор, нам в большинстве случаев нужно иметь какой-то исходный объект. Например, это может быть филиал, к которому мы добавляем отзыв. Таким образом, дата провайдер состоит из двух частей:

  • получение данных из подходящего источника для формирования наборов
  • непосредственно формирование списка тестовых наборов. По сути это просто return массива массивов.
public function providerAddReview()
{
    $filial_id = Config()->filials->pac;
    $user_id = Db()->user()->getRandomUser()->id;
 
    return [
        [$filial_id, Generate()->text(150), 5, true, null, $user_id, 201],
    ];
}

Источники данных

  • Конфиг как источник статичных, синтетических данных (фикстуры). В конфиге данные хранятся в виде дерева (массив массивов). Просто указываем через стрелочки путь до нужного узла дерева. Если нужно получить конкретный массив целиком, можно воспользоваться методом asArray().
$user_id = Config()->roles->guest;
  • БД как источник реальных случайных данных. Объекты из БД получаем цепочным запросом в удобном описательном виде. Обычно сначала указываем таблицу/сущность, затем условия выборки и в самом конце дёргаем метод получения.
$entity = Db()-
View on GitHub
GitHub Stars8
CategoryDevelopment
Updated5y ago
Forks0

Languages

PHP

Security Score

55/100

Audited on Aug 21, 2020

No findings