Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

Как хранить тестовые данные при тестировании API?

rest
test-data
soap
api
python
json
Теги: #<Tag:0x00007f7b704d7810> #<Tag:0x00007f7b704d76a8> #<Tag:0x00007f7b704d7568> #<Tag:0x00007f7b704d7428> #<Tag:0x00007f7b704d72e8> #<Tag:0x00007f7b704d71a8>

(Quramolt Quramolt) #1

Всем привет! Столкнулся со следующей проблемой - не понимаю, как лучше хранить тестовые данные для последующего тестирования REST \ SOAP

Если представить, что у меня есть поисковая форма со многими полями, значения которых отправляются в JSON через POST-запрос. И таких форм не одна, если не говорить о других сценариях работы.

Я хочу проверять много разных значений полей и валидировать полученные результаты либо на основании сравнения с БД, либо на основании логики, что возвращаются нужные и только нужные значения, если мне известен требуемый результат. То есть также, как и руками, но автоматизированно.

В интернете слабо освещается вопрос хранения json-данных, которые нужно отправлять с запросом. Но там всё ограничивается одним-двумя запросами и одним-двумя параметрами и хранится это всё в конфиге YAML или JSON.

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


(Oleksii Ihnatiuk) #2

Как я понимаю Вам нужно смотреть в сторону параметризации тестов. У TestNG например есть аннотация DataProvider.


(Quramolt Quramolt) #3

Посмотрел в док по ссылке. Вопрос остался. Там в примере два параметра - имя и возраст. Таких легко 100 строк накидать, если нужно.

Мне непонятно, если у меня с формы передается 15 разных параметров, каждый в целях тестирования может принимать 5-15 значений.

Пока что мне приходит в голову только идея для тестирования каждого метода завести отдельную папку resources/{folder} и там накидать n-ое количество JSON-файлов с конкретным набором значений, которые я хочу передавать при тестировании.

Возможно, есть способ получше? Этот просто вообще не гибкий


(vmaximv) #4

(Quramolt Quramolt) #5

Если я правильно понял, идея в том, чтобы отдельно держать шаблон, отдельно варианты заполнения и создавать нужные объекты по шаблону?


(vmaximv) #6

Yeap


(Александр Илюшкин) #7

Делайте фреймворк СРАЗУ на основе ООП и ничего не зашивайте в код. Никакого хардкода в тестах. Только автоматизация. Как хотите, хоть свой код пишите, хоть используйте готовый фреймворк.

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

  1. Пишите четырехфазные тесты: создать, выполнить, проверить, удалить (очистить, закрыть и т.п.)
  2. Генерите все и беспощадно. Генерить json можно с помощью сериализаторов объекта в json. Например преобразовывать dictionary в json. Можете так же рассмотреть вариант шаблонизатора вроде jinja templates.
  3. Ещё раз, никакого плоского кода, используйте ООП. Если ваш объект - это бот в игре, напишите класс бота и класс управляющий ботом. Если это взаимодействие с апи, напишите классы апи запрос, апи ответ, апи клиент, апи компонент, объектную модель апи и т.п. все сущности вашей системы - это сущности вашего тестового фреймворка.

(rpwheeler) #8

Хм. Мне даже как-то странно такое читать. Освещен он нормально: https://en.wikipedia.org/wiki/Document-oriented_database . Постоянно на слуху MongoDB , видел также проект, работавший на Elasticsearch .

Вот туда и копать.


(rpwheeler) #9

… Однако с документ-ориентированной базой возможны проблемы в том плане, что она не очень хорошо совместима с системой контроля версий. Если предполагается работа с версионированием вроде Git (что может быть вполне желательно), вариант разбрасывания документов по разным папкам и чтения из каждой папки пакетов данных для прогона однотипных тестов тоже вполне подойдет.


(rpwheeler) #10

Ужасы какие.

Обозначим мои объекты в данный момент на данном проекте как S, Q, TD, R и С .

У С — простая структура, но их и генерить не надо, руками прописать. Вот объектов Q — до 40 типов, для них надо генерить куски XML. Некоторые типы похожи, но непохожих можно выделить 14 типов. Объекты S — это XML-файлы, содержащие в определенной структуре произвольное количество объектов Q . Объекты TD — тестовые данные, индивидуальные для каждого отдельного типа Q, тоже XML , R — результаты, исходящие ответы системы на входящие данные, тоже XML .

Ох и нагенерилось бы по ходу… тут на переписывание половины сервера генераторов бы было…

Парочка тестов работают с данными фотографий. Не проще ли взять немножко реальных? Или фотографии нынче тоже призывают генерить? :slight_smile:


(Quramolt Quramolt) #11

Я не совсем понял. Вы предлагаете хранить тестовые данные в базе данных?

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


(Quramolt Quramolt) #12

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

P.S. Да и это не самая главная активность на проекте. Просто я довольно часто руками одно и то же делаю, надоело. Решил немножко улучшить процесс.


(rpwheeler) #13

База данных не есть что-то обязательно большое и страшное. Она запросто может быть локальным файлом, работающим на том же MongoDB или sqlite. Такие популярные приложения как Evernote , скажем, это тоже что-то вроде “личной базы данных”. Я знавал проекты которые в MongoDB хранили конфигурации тех или иных подсистем.

Вопрос тут скорее в функциональных требованиях к хранению тестовых данных.

Варианты:

Соображение: “Мне не нравится много файлов, я хочу чтобы был один файл”. Предложение: база данных.

Соображения:

  • Пользуются несколько человек,
  • Возможны разные версии тестовых данных (под разные ветки разработки, скажем, или переделка тестовых данных под новый функционал/фикс).
    Предложение: папки-файлы, Git репозиторий.
    Выглядит может и “старомодно”, но по части веток/версий лучше вроде не придумали, в базах данных с версиями не настолько хорошо.

Генератор шаблонов мне тоже не помешал бы (неспешно ищу), но, как я уже обозначил выше, у меня слишком много разных типов входных и проверочных данных чтобы я их все хотел генерировать.


(Александр Илюшкин) #14

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


(Dmitriy Romanov) #15

Тема тестовых данных Fixtures VS RealData sets не нова. Есть аргументы за и против каждого.
Мой опыт говорит, что более надежные проекты базируются на реальных данных. В больших проектах маинтаненс тестовых данных - большая нагрузка и ее позволяет уменьшить использование тестовых данных с продакшена.
Тест кейсы, которые не находят данных, просто не ранятся, как дополнительная фишка - пойманные баги на комбинации значений из реальной жизни. Все мои, ТК которые читают данные (не меняют) также ранятся на продакшене как часть консистенси чеков.
И да, работать со сложными структурами надо с помошью ООП.


(Yurii Hunter) #16

Столкнулся с такой же проблемой.
Как сейчас делаю я: вычитываю json в объект класса, а потом обновляю поля.
Беда происходит когда в json полях лежат id и в тесте я хотел бы указать Имя пользователя, а на сервет отправить его ID


(rpwheeler) #17

Спокойствие, только спокойствие. Нет “всегда правильных” и “всегда неправильных” подходов. Очень полезно смотреть на контекст.

Боюсь, Вы забыли, что Git — это тоже база данных, они ее даже так называют: “When you do actions in Git, nearly all of them only add data to the Git database.” ( https://git-scm.com/book/en/v2/Getting-Started-Git-Basics ). То есть если Git , то данные в любом случае будут в базе данных, вопрос уже в том, какое представление этих данных будет работать.

Не согласен. Аргументы:

  1. Переход от статических данных к генерируемым ухудшает их читаемость и “обозреваемость”. С набором статически выведенных данных вы можете сказать "что есть, чего нет, какой тест тестирует какой случай … ". Как Вы этот “учет и контроль” будете вести с генератором?
  2. Как я уже сказал, для автотестов может использоваться масса сложных пакетов сущностей, использование “генерируемых” данных вместо снятых из обмена данными с сервером — это дублирование кода генерации данных, “переписывание половины сервера” (и половины клиента если проверяются ответы клиента тоже).
  3. Если в тесте “данные которые он создает сам”, то Вы и тестируете “то что создаете сами”, а не реальные данные с реального сервера/клиента.
  4. Тестовые данные могут быть задействованы не на одном, а на двух-трех проектах (клиентах, допустим). При этом одним из условий может быть одинаковая логика работы всех трех клиентов независимо от подробностей их реализации. Вот как раз для этого может использоваться выделенный набор тестовых данных, со вписанными “входом” и “выходом” (результатом).

(Александр Илюшкин) #18

Если в тесте “данные которые он создает сам”, то Вы и тестируете “то что создаете сами”, а не реальные данные с реального сервера/клиента.

Простите, но если вы заявляете, что вы тестируете данные, то о чем еще можно разговаривать. Тестируется SUT, а не данные. Данные - это способ взаимодействия с SUT.

К вопросу про генерацию данных у меня встречный вопрос: представьте, что у вас очень много тестов. Вы их наверняка захотите запускать параллельно. Иначе вы будете ждать сборки тестов пару часов, например. Как только вы захотите запустить их параллельно, ваша концепция с данными в БД порушится, т.к. начнется работа с разделяемым ресурсом. В случае с генерацией данных, такой проблемы нет. Вторая сторона вопроса: у вас данные состояние наверняка имеют. В таком случае, первый тест работает с данными из БД, меняет их, далее приходит второй тест и работает уже не с теми данными, которые ожидает на входе, а с измененными. Хорошо, если у вас все на справочниках - такие данные имеют лишь два состояния - справочник наполнен или пуст. Если же речь идет о сложном объекте, например, таблице с кучей связей и состояний, историческими данными, то наступает конец, потому как ваши готовые данные должны быть обязательно приведены в исходное состояние. Это бывает сделать в принципе невозможно в силу архитектуры ПО.


(rpwheeler) #19

Возвращаясь к напечатанному.

Это не то, что я сказал — что я тестирую данные. Тестируеся код SUT (клиентский код) которому на вход подаются данные, снятые с сервера и сохраненные в статику. Код SUT их берет, обрабатывает, происходят проверки как код SUT их обрабатывает.

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

Не обязательно. У нас есть сотни тестов, каждый со своим статическим набором данных. Они быстро прогоняются с этой статикой. Я вообще не представляю как (и зачем) это генерить. Один и тот же набор статических данных реально работает для тестирования кода на трех языках.

Не обязательно. Один и тот же дамп базы может быть вылит на разные серверы.

Один и тот же набор статики может быть скачан из git’а и запущен параллельно.

Не обязательно. Статика на вход -> Обработка кодом клиента -> Проверка обработки и выхода.


(vmaximv) #20

Вы определитесь что есть SUT - клиент или сервер, а то на выходе жуткая мешанина, в которую даже не хочется вчитываться.
Как правило, когда говорят про API testing - SUT это server-side и мокается клиент.