Комментарии 54
Мы решили сократить выборку до первых 100 фирм, подходящих под наши условияЗная примерное количество и, предположив, что id — int, можно сделать так:
$id = random_int(1, 150000);
…where id < :id limit 1
Вот насчёт регулярной очистки БД. Приложение с маленьким количеством данных будет вести себя не так, как приложение с большим. По идее нужно отдельное тестирование для проверки как приложение ведёт себя на нормальном объёме данных. Делаете вы такое?
«Почему не поймали описанную проблему выше на этапе нагрузочного тестирования» — спросите Вы. Не поймали мы ее из-за особенностей нагрузочного контура — БД там синкатеся по другому.
Обычно нет в коде условий вроде «если в таблице больше 100500 записей, то вести себя по другому
В коде нет, а в движке БД что-то в этом духе вполне может быть. И то, что нормально работало для небольшого количества данных — при увеличении их количества просто упадёт. Это вроде действительно кейсы для нагрузочного тестирования, но под нагрузкой как правило имеют в виду не большое количество данных, а большое количество запросов.
Строго говоря, это вообще не относится к тестированию приложения
Ну после накопления какого-то количества данных прод начинает падать, а функциональные тесты показывают, что всё норм.
А ее и не нужно тестировать — просто ищешь результаты таких тестов и помнишь про ограничения.
Не совсем понял. Тут же приложение в связке с БД тестируется.
Если написали такой тест связки приложения с БД, в котором база падает, то это баг базы
Падает не база, падает приложение. Падает, например, потому что транзакция вместо трёх секунд отрабатывает за 10 и её прибивает по таймауту.
Ну тут надо писать функциональный, а то и юнит-тест, который проверяет, что приложение и за минуту не упадёт :)
Приложение в таких случаях должно падать, это желаемое поведение. Не целиком, конечно, падать, а только прерывать с ошибкой обработку текущего рест-запроса.
Потом оно, конечно, выводит сообщение юзеру, но вообще транзакции должны отрабатывать за 3 секунды или быстрее. Над этим надо работать. И чем больше данных, тем дольше работают транзакции. Поэтому проверять надо на БД с большим количеством записей.
А так вам классический тест производительности нужен, нагрузочный в широком смысле слова.
А так вам классический тест производительности нужен, нагрузочный в широком смысле слова.
Обычно под нагрузочным тестом имеется в виду тест, который нагружает систему большим количеством запросов в еденицу времени.
А тут достаточно прогнать функциональные тесты, просто на нормальном для системы количестве данных. Это, конечно, можно считать каким-то особенным тестом, но если для создания полноценной нагрузки надо приложить существенные усилия и написать код, то для проверки на большом количестве данных достаточно использовать ту же БД, что на проде, только почистить её от персональной информации пользователей.
Все это прекрасно работает через teamcity, к примеру.
Рандом в тестах почти всегда зло. Хотя бы потому что повторить такой тест невозможно (если у вас нет ключика, который фиксирует состояние… но тогда это другой тест).
Покапитаню: Классы эквивалентности пробовали применять?
Покапитаню2: С выборкой "случайной" фирмы вы тестировали несуществующий кейз. Клиент может запросить "случайную фирму" (а-ля "фирма дня"?) Если нет, то и тесты (массово) такой подход не должны использовать.
Второй вариант получше, все же будет.
На у совсем хороший подход — самим генерить фирму с нужными параметрами, используя классы эквивалентности. Но это может оказаться весьма трудоемко.
Рандом как раз в тестах, просто во входных данных. Получается, что чистая функция "тест" обёрнута в обычную функцию "тест + входные данные" + рандомное время для извлечения тестовых данных.
Конечно, всегда есть некоторая рандомизация (да хотя бы время, в которое скрипт запустили — вдруг фирма уже прекратила существование и уже отправилась в архив), но и от неё надо стараться избавиться.
А создание ненастоящих фирм можно делать отдельным процессом, который будет контролировать наполненность тестовой фермы тестовыми сущностями. Так нагрузка будет не на тесты.
Я не защищаю такой подход, но он вполне может существовать на временной основе, пока не сделают генерилку данных. В нем нет каких-то фундаментально-неверных подходов.
Ещё один недостаток: ошибка может быть в генерации тестовых данных.
Я не защищаю такой подход, но он вполне может существовать на временной основе, пока не сделают генерилку данных. В нем нет каких-то фундаментально-неверных подходов.
Я согласен с вами, что такой подход рабочий. Но нет ничего более постоянного, чем что-то временное :)
Некоторая ошибочность подхода (не фатальная) в том, что вы тестируете гораздо больше, чем вам надо. Просто "а почему бы и нет?" Раз вас пока это устраивает — исползуйте на здоровье :)
Зачем играть в рулетку с рандомом на настоящей базе, когда требования к данным для теста (граничные случаи) известны? Какое-то усложнение во всём: медленнее; нет гарантии, что тест проходит со смыслом (попали в требуемые по форме данные); не повторить разработчику для отладки, если будет нужно.
https://www.phparch.com/magazine/2018-2/april/
PHPUnit Worst Practices — моя статья (наглая реклама, да!). Очень знакомо выглядит то, что вы описываете, несмотря на то, что моя статья больше о качестве тестового кода, чем о производительности тестов.
И отдельно насчет рандома. Рандом в тестах — зло. Тест должен быть предсказуемым, а когда используется рандом — вы рискуете получить рандомные же фэйлы. Покрывайте edge cases, а случайные данные оставьте для fuzzing tests.
Рандом в тестах — зло.
И генерация рандомных идентификаторов тоже?
Если используете один и тот же seed или можете восстановить цепочку, то не зло.
Ну вот есть у нас БД, в ней колонка со строкой, которая естественный ключ. Какими нехорошими последствиями может обернуться рандомная генерация этих ключей? При условии, что каждый запуск ключ будет новый.
Ну например, генератор использует 100 возможных символов для этой строки, а в валидатор зашито только 99. Один из Х тестов падает, повторный запуск — скорее всего проходит.
Ваш случай граничный. Сложно придумать контраргумент. Возможно, даже и не нужно, ведь есть "допустимое зло" :)
Из тех условий, что вы приводите, рандомная генерация ключей единственное что не позволит воспроизвести какую-нибудь ошибку в БД или хранимых процедурах в БД.
Но это уже домыслы.
Очень сложно выглядит. Я не вижу, какими преимуществами оправдывается это возрастание сложности.
Зачем какие-то идентификаторы генерить, когда можно сделать для теста необходимую фикстуру.
Очень сложно выглядит.
Передача сгенерированного значения, вместо передачи подготовленного значения что-то усложняет?
Зачем какие-то идентификаторы генерить, когда можно сделать для теста необходимую фикстуру.
Если что-то подготавливать, то после теста надо будет почистить всё, что попало в БД. Это увеличивает время прогона тестов, плюс добавляет сложности в виде чистилки, которую написать сложнее, чем сделать генератор случайных id.
Нсли чистить не в рамках теста, а в рамках другой задачи (да хоть бы и автоматическим заданием в планировщике очередей), то скорость прохождения тестов не вырастет.
Чистилка не особо нужна, если каждый раз использовать эталонную базу (восстанавливать из докера / хранить слепок / всё что угодно).
Понятное дело, что вы сейчас говорите о каком-то реальном проекте, где это ну оооочень сложно реализовать уже. А вам тут о каком-то академическом примере талдычут. Ну так вот придёте как-нибудь на новый проект, где ещё код весь костылями не оброс и успеете туда прикрутить "чуть лучший" подход к тестированию.
В целом это общее правило для любых тестов. Влияние тестов друг на друга должно быть стремиться к нулю. Если куча всего пишется в базу во время тестов и это не чистится, то о независимости прогонов друг от друга сложно говорить.
Ограничения, которые нужно нарушать или как мы ускорили функциональные тесты в три раза