Рад приветствовать читателей Хабр. Меня зовут Азамат Акчурин, я QA инженер в Bimeister.
Часто при приемке разного рода фич нам, тестировщикам, не хватает сущностей/данных в тестируемой системе. Тестировать на пустых данных не “comme il faut”, поэтому, чтобы наполнить систему данными, мы можем обратиться к разработчикам, QA automation, добавить данные в БД и т. д. — способов очень много.
И сегодня я расскажу про один из таких способов, который "дешево и сердито" позволит тестировщику самостоятельно, не отвлекая других сотрудников, заполнить систему данными.
Все, что нам нужно
Установить Python.
Установить IDE для Python — лично пользуюсь PyCharm.
Дочитать эту статью, чтобы научиться применять такой способ в решении задач.
N.B.
В данной статье опущу пункты установки Python и IDE — будем считать, что они уже установлены. Перейдем, непосредственно, к практике.
Кейс #1
Представим, что разработали новую таблицу, в которой содержатся объекты со свойством «Строка» — то есть мы можем создать объекты, в которых содержатся любые символы. Нам необходимо проверить фильтрацию объектов, поиск, пагинацию и т. д.
А если таких свойств будет 5/10/15 штук в одном объекте? Какая бы “Самая быстрая рука на Диком Западе” не была у тестировщика, заполнять систему данными он будет неприлично долго.
Пришло время научить машину делать рутинную работу за нас:
Открываем devtools → networks и создаем один объект руками.
-
Ловим запрос, который ушел при создании объекта, и во вкладке Networks запоминаем следующие параметры:
- Request Url "https://[что-то типа google.com]/api/BimExemplars".
- Request Method "post".В этом примере я авторизован под учетной записью в системе, поэтому из Request Headears также фиксирую Bearer Token "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6….и еще куча символов".
Из вкладки Payload искомого запроса записываем данные для Request Payload.
Все исходные данные мы собрали. Теперь перейдем к написанию скрипта:
import requests as r # Для импорта библиотеки requests, с помощью этой библиотеки будем отправлять запросы.
import random # Данная библиотека нужна для формирования рандомных значений.
url = 'https://[что-то типа google.com]/api/BimExemplars' # В переменную url сохранили значение Request Url (см. п2).
bearer = 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmYmMyMzRhZC01NjQ1LTQ3MTktODFmNC0zZDQyNzliMTMxYWEiLCJpc3...еще много символов' # В переменную bearer сохранили значение Bearer Token (см. п2).
for i in range(15): # Создаем цикл, в данном случае код — под этим циклом исполнится 15 раз. Почему 15? Да просто пример из головы. Если нам нужно 100 объектов, просто делаем цикл на 100 повторений.
payload = { # В переменную payload сохраняем значение из Requests Payload (см. п3). Но, если оставить в таком виде и запустить код, в системе будет 15 совершенно одинаковых объектов. Давайте подумаем, что можно изменить?
"projectId": "76dfd02a-9016-43f3-93f1-7744acd98f54", # ID проекта оставляем неизменным, так как именно в этом проекте мне необходимы созданные объекты.
"title": "Test obj", # Поле отвечающее за наименование объекта. Отличное поле для рандомных значений. Заменим значение "Test obj" на f"Test obj {random.randint(1, 1000)}". Что это нам даст? Будет создан Объект "Test obj {здесь будет случайное значение от 1 до 100}".
"bimClassId": "94e9f5ff-1afa-47ec-beb0-59109cc3d9dd", # bimClassId и ниже bimPropertyId отвечают за поля свойств у объекта, поэтому оставим их неизменными.
"bimExemplarProperties": [
{
"bimPropertyId": "8f2a6659-feb4-42d6-899d-8e7ebc99d5e4",
"value": "111" # Поле, отвечающее за значения в поле Свойства. Тоже отличное поле для рандомных значений. Идем по протоптанной дорожке и заменяем "123" на f"random.randint(1, 100)". Что здесь происходит? Думаю, уже понятно.
},
{
"bimPropertyId": "391fb437-8771-4d80-a22e-af86ce0fd6a8",
"value": "222" # Аналогично заменим здесь.
},
{
"bimPropertyId": "65f144fa-56d2-4bf1-88f3-452242f03a68",
"value": "333" # Здесь.
},
{
"bimPropertyId": "0d80ff51-5771-4d4d-9a1b-645faaac8c25",
"value": "444" # И здесь.
},
{
"bimPropertyId": "9d64cfc4-bcfc-44d2-88b0-8f8d511db06c",
"value": "555" # И здесь.
}
]
}
requests = r.post(url, headers={'authorization':bearer}, json=payload) # Что происходит: r.post(url, headers={'authorization':bearer}, json=payload) — говорим системе сделать Post запрос (см. п2 Requests Method "post"); url — запрос, который добавляет объекты; headers={'authorization':bearer} — хедеры, которые отправляются вместе с запросом, тут как бы говорим системе, что пользователь авторизован; json=payload — здесь передаем тело запроса.
print(requests.status_code) # После запуска кода выведет статус код каждого запроса. Сугубо личная вещь, сделано для удобства.
В таком виде мы создадим 15 одинаковых объектов, содержащих одинаковую информацию, соответствующую payload.
Добавим уникальности объектам через random.randint(1, 100)
import requests as r
import random
url = 'https://[что-то типа google.com]/api/BimExemplars'
bearer = 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmYmMyMzRhZC01NjQ1LTQ3MTktODFmNC0zZDQyNzliMTMxYWEiLCJpc3...еще много символов'
for i in range(15):
payload = {
"projectId": "76dfd02a-9016-43f3-93f1-7744acd98f54",
"title": f"Test obj {random.randint(1, 100)}", # {random.randint(1, 100)} Подставит любое целое число от 1 до 100
"bimClassId": "94e9f5ff-1afa-47ec-beb0-59109cc3d9dd",
"bimExemplarProperties": [
{
"bimPropertyId": "8f2a6659-feb4-42d6-899d-8e7ebc99d5e4",
"value": f"{random.randint(1, 100)}"
},
{
"bimPropertyId": "391fb437-8771-4d80-a22e-af86ce0fd6a8",
"value": f"{random.randint(1, 100)}"
},
{
"bimPropertyId": "65f144fa-56d2-4bf1-88f3-452242f03a68",
"value": f"{random.randint(1, 100)}"
},
{
"bimPropertyId": "0d80ff51-5771-4d4d-9a1b-645faaac8c25",
"value": f"{random.randint(1, 100)}"
},
{
"bimPropertyId": "9d64cfc4-bcfc-44d2-88b0-8f8d511db06c",
"value": f"{random.randint(1, 100)}"
}
]
}
requests = r.post(url, headers={'authorization':bearer}, json=payload)
print(requests.status_code)
Теперь запустим код и посмотрим, что произойдет в системе:
Запускаем код.
Смотрим, что все запросы вернулись с кодом 201.
Смотрим, что в системе создалось 15 объектов, и все они имеют рандомные наименования.
Кейс #2
Чтобы закрепить материал, рассмотрим другой пример. Если открыть любой из созданных объектов и изменить какие-либо значения свойств, то можно сохранить новую версию объекта:
Затем, после сохранения "как новой версии" пользователю доступен список всех версий
В практике столкнулся с тем, что необходимо было проверить открытие (до 1 сек.) и отображение дропдауна с 1000 версий. И тут снова пригодился Python. Повторим, знакомые нам, шаги:
Открываем devtools → networks.
Создаем новую версию объектами руками.
-
Ловим запрос, который сохраняет версию и фиксируем параметры:
Request Url "https://[что-то типа google.com]/api/BimExemplarVersions",
Request Method "Post".Из Request Headears запоминаем Bearer Token "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp...и еще много символов".
Из вкладки Payload скопируем значение Request Payload:
{
"bimExemplarId": "92ea9b30-a097-4a7e-a472-48d020eecc13",
"title": "Test obj 893",
"bimExemplarProperties": [
{
"bimPropertyId": "57c5ae3d-3aa2-40c4-a77b-bc90b3cf84f7",
"value": "73"
},
{
"bimPropertyId": "4a23533f-1757-4a0c-931b-57e28a45c1bd",
"value": "162 значение изменено для сохранения новой версии"
},
{
"bimPropertyId": "588b3da1-73bc-4ea6-95d2-035f6082216d",
"value": "987 значение изменено для сохранения новой версии"
},
{
"bimPropertyId": "8740ae93-2a9e-4a17-8e56-5bede7405554",
"value": "51"
},
{
"bimPropertyId": "521ca3e8-64ef-4d3a-af2d-d8facdaf37df",
"value": "608"
},
{
"bimPropertyId": "fc4a6ce2-eb55-4543-9913-fc4238ce739e",
"value": "593"
},
{
"bimPropertyId": "d18c9d75-2298-45d7-9542-1644b900ed45",
"value": "535"
}
],
"bimExemplarVersionId": "f813654e-43b9-437b-930a-4882f1d71d73"
}
Нужные данные для скрипта мы записали. Перейдем к финальному скрипту. Рандомные значение проставили только для полей Объекта, так как, меняя только поля объекта, можно сохранить новую версию:
import requests as r
import random
url = 'https://[что-то типа google.com]/api/BimExemplarVersions'
bearer = 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNmZjYThmYi1iYjgwLTQzZGItYmY4NC02MDk3NzM5ZGEzZ...и еще много символов'
for i in range(1000):
payload = {
"bimExemplarId": "92ea9b30-a097-4a7e-a472-48d020eecc13",
"title": "Test obj 893",
"bimExemplarProperties": [
{
"bimPropertyId": "57c5ae3d-3aa2-40c4-a77b-bc90b3cf84f7",
"value": f"{random.randint(1, 100)}" # Меняем значение свойства.
},
{
"bimPropertyId": "4a23533f-1757-4a0c-931b-57e28a45c1bd",
"value": f"{random.randint(1, 100)}" # Меняем значение свойства.
},
{
"bimPropertyId": "588b3da1-73bc-4ea6-95d2-035f6082216d",
"value": f"{random.randint(1, 100)}" # Меняем значение свойства.
},
{
"bimPropertyId": "8740ae93-2a9e-4a17-8e56-5bede7405554",
"value": f"{random.randint(1, 100)}" # Меняем значение свойства.
},
{
"bimPropertyId": "521ca3e8-64ef-4d3a-af2d-d8facdaf37df",
"value": f"{random.randint(1, 100)}" # Меняем значение свойства.
},
{
"bimPropertyId": "fc4a6ce2-eb55-4543-9913-fc4238ce739e",
"value": f"{random.randint(1, 100)}" # Меняем значение свойства.
},
{
"bimPropertyId": "d18c9d75-2298-45d7-9542-1644b900ed45",
"value": f"{random.randint(1, 100)}" # Меняем значение свойства.
}
],
"bimExemplarVersionId": "f813654e-43b9-437b-930a-4882f1d71d73"
}
requests = r.post(url, headers={'authorization':bearer}, json=payload)
print(requests.status_code)
В этом примере хватило 5 минут, чтобы создать 1000 версий для дальнейших тестов:
В заключение
Мы разобрали два простых кейса из опыта, в которых буквально за 5-10 минут сгенерировали данные для тестирования. Этот способ, на мой взгляд, поможет тестировщику без каких-либо фундаментальных знаний программирования решать рутинные задач подобного рода. Если данная тема будет актуальна для читателей, то в следующей статье разберу более сложные примеры, в которых используются несколько запросов и параметры из одного запроса прокидываются в другой запрос.
Прошу подсказать читателей, интересна ли тема и каким инструментом пользуйтесь при решении таких задач?
P.S.
Данная инструкция не является призывом к действию, эталоном и панацеей. Это всего лишь один из способов для решения вопросов "одному.здесь.сейчас", который возможно принесет пользу и вам.
iig
Изобретаете Apache Jmeter?
conopus
Скорее VCR https://vcrpy.readthedocs.io/en/latest/