Size: a a a

testing_in_python

2020 July 26

CS

Cat Shannon in testing_in_python
Тачами Экстович
Ты разницу между плагином для пайтеста и тулзой для консоли понимаешь?
Спасибо огромное! Сделал через оф репозиторий
источник
2020 July 27

OC

Oleg Chaplashkin in testing_in_python
Всем привет!
Система интеграционных тестов расширяется и встал вопрос о грамотных проверках.
Сейчас есть 2 слоя: слой тестовой логики (обращаемся к необходимому клиенту, что-то отправляем, вызываем проверки) и слой тестовых данных (тест-кейсы, которым передано частично управление на проверки)
Это значит, что есть тест-кейсы, например:

create_test_cases = {
 'name1':{
   'link':"",
   "description":"",
   'in':{
     "channel": 'acquiring',
     "isNew": True,
     "name": 's',
     "policy": 'Default'
   },
   'expected':{
     'code': expected_status_code,
     'type': expected_response_type,
     'structure': expected_structure,
     'types': expected_types,
     'values':{
               "channel":"acquiring",
               "comment":"",
               "createdAt":None,
               "createdBy":"apogee",
               "id":None,
               "name":"s",
               "policy":"Default",
               "updatedAt":None,
               "updatedBy":"apogee",
               "version":1
           }
   }
 }
}

И есть тестовая логика:

@pytest.mark.parametrize("data", create_test_cases.keys())
class TestCreateSubchannel():

 @allure.title("{data}")
 def test_create_subchannel(self, data):
   expected = create_test_cases[data]['expected']

   with allure.step('Send create request to the API'):
     status_code, data = self.api.subchannels.create(
       create_test_cases[data]['in'])

   if 'code' in expected:
     self.checker.status_code(status_code, expected['code'])
   if 'type' in expected:
     self.checker.is_instance(data, expected['type'])
   if 'structure' in expected:
     self.checker.structure(data, expected['structure'])
   if 'types' in expected:
     self.checker.types(data, expected['types'])
   if 'values' in expected:
     self.checker.values(data, expected['values'])

Цель: убрать вот эту копипасту-хвост в конце и сделать нормальные проверки.

К чему я пришел:

У нас может быть 3 случая ответа от сервера: словарь, список, и какое-нибудь атомарное значение (int, str, bool)
Если у нас атомарное значение, то выполняем проверку на:
- тип
- значение
- диапазон (если это int unix time)
Если у нас словарь, то:
- тип
- ключи
- тип значений по ключам
- значения
Если у нас список, то:
- тип
- внутренние типы
- длина
- значения

Однако я не могу дойти до хорошего унифицированного интерфейса так, чтобы тестовая логика была:

@allure.title("{data}")
 def test_create_subchannel(self, data):
   expected = create_test_cases[data]['expected']

   with allure.step('Send create request to the API'):
     status_code, data = self.api.subchannels.create(
       create_test_cases[data]['in'])
   
   check(status_code, data, expected)
где check - содержит в себе все необходимые проверки. При этом в тест-кейсах иногда передаётся не data, а data[0] (ибо список)

Вопрос: кто как решает эту задачу у себя? Как реализовать унифицированный интерфейс проверок?
Спасибо!
p.s. извиняюсь за портянку
источник

OC

Oleg Chaplashkin in testing_in_python
В дополнение: я помню, что здесь советовали идти по пути "сравнение целого объекта". Это прекрасно работает. А что делать если:
- объект достаточно большой длинны?
- динамические поля (это я частично решил заглушками)
источник

EB

Evgenii B in testing_in_python
1) достаточно большой длины для чего?
2) какого рода динамические поля?
источник

OC

Oleg Chaplashkin in testing_in_python
1) Типичная ситуация одной из CRUD-операций: read all entities возвращает хорошую такую портянку объектов(словарь) в списке;
2) например, ID, который нельзя угадать (подобные поля я глушу и не проверяю) или unixtime int, который тоже нельзя угадать точно (это я решил через указание диапазона - значение корректное, если оно находится в промежутке от A до B относительно времени исполнения теста)
источник

EB

Evgenii B in testing_in_python
1) и чо?
источник

EB

Evgenii B in testing_in_python
2) в современных библиотеках можно описывать динамические проперти для проверки json schema
источник

OC

Oleg Chaplashkin in testing_in_python
1) Хорошо, это тогда вопрос ближе к тест-дизайну автотестов.
Тест дизайн ручных кейсов - понятен (есть вход/выход, пред/пост условия)
Получается, если мы учитываем подобные портянки, нам нужно дизайнить тест-кейсы относительно сессии? (у меня лично не дропается бд после каждого кейса, поэтому все тесты на создание имеют накопительный эффект для теста чтения, хотя я там снижаю зависимости и перед чтением создаю сущность, чтобы вытащить ее как из стэка-списка)

Доп. вопрос: является ли нормальным тест-кейс для API, где выходной объект на 100-200 строк?
источник

KM

Konstantin Mikhed in testing_in_python
betzy
попробуй запускать в selenoid без headless
Результат тот же(
источник

ТЭ

Тачами Экстович... in testing_in_python
Konstantin Mikhed
Результат тот же(
Это все в хроме?
источник

KM

Konstantin Mikhed in testing_in_python
Да
источник

ТЭ

Тачами Экстович... in testing_in_python
Покажи капабилити с которыми запускаешь
источник

ТЭ

Тачами Экстович... in testing_in_python
А еще лучше, если в интернете есть эта страничка (которая разваливается)
источник

ТЭ

Тачами Экстович... in testing_in_python
Мб еще хром старый очень?
источник

KM

Konstantin Mikhed in testing_in_python
Тачами Экстович
Покажи капабилити с которыми запускаешь
def chrome(self):
   driver = self.driver
   options = driver.ChromeOptions()
   options.add_argument("--window-size=1920,1080")
   options.add_argument("--mute-audio")
   capabilities = {
       "browserName": "chrome",
       "version": "83.0",
       "enableVNC": True,
       "enableVideo": False
   }
   chrome = self.driver.Remote(command_executor='http://localhost:4444/wd/hub',
                               options=options,
                               desired_capabilities=capabilities)

   return chrome
источник

b

betzy in testing_in_python
та ты запусти прям как в доке попробуй
источник

b

betzy in testing_in_python
без всякой хуйни типа виндоу сайз
источник

IS

Idi Suda in testing_in_python
Oleg Chaplashkin
Всем привет!
Система интеграционных тестов расширяется и встал вопрос о грамотных проверках.
Сейчас есть 2 слоя: слой тестовой логики (обращаемся к необходимому клиенту, что-то отправляем, вызываем проверки) и слой тестовых данных (тест-кейсы, которым передано частично управление на проверки)
Это значит, что есть тест-кейсы, например:

create_test_cases = {
 'name1':{
   'link':"",
   "description":"",
   'in':{
     "channel": 'acquiring',
     "isNew": True,
     "name": 's',
     "policy": 'Default'
   },
   'expected':{
     'code': expected_status_code,
     'type': expected_response_type,
     'structure': expected_structure,
     'types': expected_types,
     'values':{
               "channel":"acquiring",
               "comment":"",
               "createdAt":None,
               "createdBy":"apogee",
               "id":None,
               "name":"s",
               "policy":"Default",
               "updatedAt":None,
               "updatedBy":"apogee",
               "version":1
           }
   }
 }
}

И есть тестовая логика:

@pytest.mark.parametrize("data", create_test_cases.keys())
class TestCreateSubchannel():

 @allure.title("{data}")
 def test_create_subchannel(self, data):
   expected = create_test_cases[data]['expected']

   with allure.step('Send create request to the API'):
     status_code, data = self.api.subchannels.create(
       create_test_cases[data]['in'])

   if 'code' in expected:
     self.checker.status_code(status_code, expected['code'])
   if 'type' in expected:
     self.checker.is_instance(data, expected['type'])
   if 'structure' in expected:
     self.checker.structure(data, expected['structure'])
   if 'types' in expected:
     self.checker.types(data, expected['types'])
   if 'values' in expected:
     self.checker.values(data, expected['values'])

Цель: убрать вот эту копипасту-хвост в конце и сделать нормальные проверки.

К чему я пришел:

У нас может быть 3 случая ответа от сервера: словарь, список, и какое-нибудь атомарное значение (int, str, bool)
Если у нас атомарное значение, то выполняем проверку на:
- тип
- значение
- диапазон (если это int unix time)
Если у нас словарь, то:
- тип
- ключи
- тип значений по ключам
- значения
Если у нас список, то:
- тип
- внутренние типы
- длина
- значения

Однако я не могу дойти до хорошего унифицированного интерфейса так, чтобы тестовая логика была:

@allure.title("{data}")
 def test_create_subchannel(self, data):
   expected = create_test_cases[data]['expected']

   with allure.step('Send create request to the API'):
     status_code, data = self.api.subchannels.create(
       create_test_cases[data]['in'])
   
   check(status_code, data, expected)
где check - содержит в себе все необходимые проверки. При этом в тест-кейсах иногда передаётся не data, а data[0] (ибо список)

Вопрос: кто как решает эту задачу у себя? Как реализовать унифицированный интерфейс проверок?
Спасибо!
p.s. извиняюсь за портянку
Если я правильно понял, тебе подойдет любая библиотека валидатор. Судя по тому, что тебе нужно чекать типы полей. В любой можно ещё кастомную валидацию напедалить как тебе кайф.

А по поводу единого интерфейса проверок, ну ебани ты что-нибудь в духе

def check(obj):
   if isinstance(obj, dict):
       blabla

   if isinstance(obj, list):
       blabla
источник

ТЭ

Тачами Экстович... in testing_in_python
Konstantin Mikhed
def chrome(self):
   driver = self.driver
   options = driver.ChromeOptions()
   options.add_argument("--window-size=1920,1080")
   options.add_argument("--mute-audio")
   capabilities = {
       "browserName": "chrome",
       "version": "83.0",
       "enableVNC": True,
       "enableVideo": False
   }
   chrome = self.driver.Remote(command_executor='http://localhost:4444/wd/hub',
                               options=options,
                               desired_capabilities=capabilities)

   return chrome
Вообще, знаешь что. Ты можешь по VNC зайти в этот контейнер, и посмотреть в консоль браузера. Возможно от тачки где запускаешь тесты нет доступа до какого-нибудь CDN  или статики, и там тупо не подгружается js/сss и все разваливается
источник

ТЭ

Тачами Экстович... in testing_in_python
Ну, или еще проще, просто зайти на эту машину запустить браузер там, и попробовать потыкать.
источник