Pull to refresh

Comments 7

Правильно ли я понимаю, что метод assertGiftAddSuccess — обертка через __call над встроенным assertSmth? Если да, то не пробовали ли вы убирать магию и запускать методы напрямую?

Как никак, это же целый performance-hit — magic method + extra function call(s).
Нет, assertGiftAddSuccess — это обычный метод класса теста, который делает серию проверок другими assert-методами. Вот его код:
    private function assertGiftAddSuccess($response, $fail_message)
    {
        $this->assertInternalType('array', $response, "{$fail_message}: an array expected");
        $this->assertArrayHasKey('gift_id', $response, "{$fail_message}: gift id expected!");
    }


У нас есть целая пачка подобных asssertSomething, которые мы используем для упрощения самих тестовых методов.

Magic method здесь — это вызов серверной команды ($ClientGiftSender->ServerGetUser), который собирает из аргументов запрос, отправляет его серверу и разбирает полученный ответ. Тут «магию» мы убирать не пробовали, но думаю, что теряем на ней мы сравнительно немного — ведь в тесте мы работаем с реальной базой и реальными сервисами.
Честно говоря не очень понял о чем именно статья.

«Смоук-тесты» для апи должны быть, даже если компания не занимается разработкой клиентов для своего апи.
Кроме того, есть существующие инструменты для автоматизации и конфигурации таких тестов (напр. Cucumber), зачем писать свои велосипеды?

Существующие средства (конкретно Cucumber) используют QA-инженеры, занимающиеся тестированием самих приложений. Тесты, про которые я рассказал, пишут сами разработчики. Нам удобно писать такие тесты на php, т.к. мы получаем за счет этого несколько плюсов:


  • использование уже имеющихся в коде констант (в приведённом коде есть несколько примеров). Благодаря этому мы можем использовать в тесте семантические значения и нам не нужно делать какой-то маппинг;
  • использование привычного разработчикам инструмента — работать с phpunit умеют чуть ли не все разработчики. За счёт этого снижается порог входа для нового человека;
  • ускорение прогона тестов: при использовании phpunit и локальной площадки разработчика тесты работают в рамках одного процесса без http-запросов. Это важно, ведь таких тестов очень много и они не очень быстрые.
Спасибо за ответ. Я тоже работаю в компании, которая занимается разработкой апи и клиентов для него, было бы интересно поделиться опытом, если вы не против.

Например, мы пишем спеки для апи, которые лежат в одном репозитории с основным кодом (в стиле «BDD»)
Код выглядит примерно так:
(мы пишем не на ПХП, а на ноде)
describe('User', () => {

    let user

    // создаем нового пользователя перед всеми тестами
    before(() => user = helper.createUser({ balance: 1000, channel: 'Android' }))

    // удаляем пользователя после тестов
    after(() => helper.removeUser(user))
   
    // тестируем покупку двух конфет
    it('buys two candies', done => {

        config.enableCandies = true // задаем необходимые настройки для апи
        
        // то что мы отправим нашему апи
        let payload = {
            type: 'buy-candy',
            amount: 2
        }

        api().post('/api/v1/buy') // POST запрос на URL покупки
            .set('authtoken', user.getToken()) // задаем заголовки авторизации
            .send(payload) // отправляем запрос
            .end((err, res) => {

                // проверяем что вернулся статус 200
                expect( res.status ).to.be( 200 )
            
                // проверяем что у пользователя теперь есть 2 конфеты
                expect( user.getCandies() ).to.be( 2 )
            
                done()
            })
    })
})


Можете пожалуйста объяснить в чем заключается отличие вашего подхода?
Вроде так же задаются необходимые настройки для сервера и проверяется что запрос отработал правильно.
Но ничего не отправляется по сети и отсутствуют недостатки, описанные в вашей статье.

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

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

И если не трудно, можете пожалуйста в двух словах описать как это автоматизируется?

PS
getLoginedConnection()
getLoggedInConnection :)

В принципе это похоже на то, что делаем мы. Разница только в том, что создание пользователя в начале теста и удаление в конце мы делаем неявно — оно происходит "само" и по мере необходимости. У нас есть пул тестовых пользователей, каждый из которых может быть взят любым тестом. За счет этого:


  • нам не нужно тратить время на создание пользователя и его чистку в момент прогона тестов => тесты работают быстрее
  • мы экономим место на дисках: законодательства некоторых стран требуют хранить данные даже удаленных пользователей, поэтому штатно удаление пользователя не означает DELETE записей о нём из базы. У нас несколько тысяч тестов и мы часто их запускаем, поэтому база бы очень быстро росла (особенно это критично на площадках разработчиков, которые используют общие базы)

После использования пользователя тестом его нужно будет очистить. Это произойдет не сразу, а через какое-то время, когда станет понятно, что "чистых" пользователей осталось мало.


Еще одно отличие, которое я заметил — вы работаете с локальным объектом (например в вызове user.getCandies()). Мы так не делаем потому, что это не даёт возможность запускать тесты на удалённых площадках.


Периодически у нас возникает проблема, что тест проходит на площадке разработчика, изменения мержатся в ветку билда, выкладываются на стейджинг (на котором используются боевые базы данных и сервисы) и там тест начинает падать, хотя на девел окружении проходит. В такой ситуации разработчик может сделать checkout ветки билда на своей площадке (в девел окружении) и запускать свой тест в стейджинг окружении (через отправку серверных команд поверх http). При этом можно менять сам тест, добавлять какие-то дебаги, дополнительные вызовы QaApi, которые покажут, что происходит на сервере.


P.S. Не совсем понял: вы говорите, что у вас по сети ничего не отправляется, но это выглядит как отправка http-запроса


        api().post('/api/v1/buy') // POST запрос на URL покупки
            .set('authtoken', user.getToken()) // задаем заголовки авторизации
            .send(payload) // отправляем запрос
Это Node.js там можно проворачивать такие трюки.
Sign up to leave a comment.