t.me/atinfo_chat Telegram группа по автоматизации тестирования

Как отловить несколько ошибок при проверке dictionary

pytest
python
Теги: #<Tag:0x00007f21e15eac40> #<Tag:0x00007f21e15ea8d0>

(Evgen Koshevoy) #1

День добрый.

Задача такая: сравниваю текущее состояние main menu с референс файлом.
С двух сторон dict. При проверке pytest отлавливает первый не совпадающий пункт меню и заканчивает тест.
Как бы так сделать что бы ловил все несоответствия?

Понятно что по первому != asset кидает AssertionError… а вот как бы и AssertionError словить и тест продолжить )

def execute_test(self, menu_item):
	test_current = self.current[menu_item]
	test_reference = self.reference[menu_item]
	with allure.step('Проверка кол-ва подпунктов меню'):
		assert len(test_current) == len(test_reference)
	for i in range(len(test_current)):
		with allure.step('Валидация меню ' + menu_item):
			assert test_current[i] == test_reference[i]

def testLuminar3File(self):
	self.execute_test(menu_item='File')

(Михаил Братухин) #2

Для этой цели придумали soft assert’ы, либо писать свою обёртку для сравнений, сравнивать списки или словари целиком, а не поэлементно.
https://github.com/dvazar/automated-testing-notes/blob/master/soft_assert.py
http://pythontesting.net/strategy/delayed-assert/
upd. при работе с soft-assert’ами нужно быть осторожными, т.к. сами они не кидают эксепшен, а складывают куда-то и далее их нужно обработать, иначе тест не увидет эту ошибку и останется зелёным. Это может привести к ложно-положительным срабатываниям.


(Evgen Koshevoy) #3

Спасибо :slight_smile: delayed-assert зашел :slight_smile:


(Vatslau) #4

https://validatorpy.readthedocs.io/en/latest/
вот довольно удобная либа для сравнения


(Nikita Barchugov) #5

Ты что проверяешь, данные или типы? На валидацию типов есть дохрена либ. А если данные, то либо ловишь эксепшн и продолжаешь (софт ассерт), либо библиотеки под это дело


(Vatslau) #6

можно проверять всё и данные и множества и типы

# let's say that my dictionary needs to meet the following rules...
rules = {
    "foo": [Required, Equals(123)], # foo must be exactly equal to 123
    "bar": [Required, Truthy()],    # bar must be equivalent to True
    "baz": [In(["spam", "eggs", "bacon"])], # baz must be one of these options
    "qux": [Not(Range(1, 100))] # qux must not be a number between 1 and 100 inclusive
}

# then this following dict would pass:
passes = {
    "foo": 123,
    "bar": True, # or a non-empty string, or a non-zero int, etc...
    "baz": "spam",
    "qux": 101
}
>>> validate(rules, passes)
(True, {})

# but this one would fail
fails = {
    "foo": 321,
    "bar": False, # or 0, or [], or an empty string, etc...
    "baz": "barf",
    "qux": 99
}
>>> validate(rules, fails)
(False, {
 'foo': ["must be equal to 123"],
 'bar': ['must be True-equivalent value'],
 'baz': ["must be one of ['spam', 'eggs', 'bacon']"],
 'qux': ['must not fall between 1 and 100']
})

(Nikita Barchugov) #7

Во-первых спрашивал я у ТС, во-вторых она убогая. Я бы пользовался другими


(Evgen Koshevoy) #8

Я проверяю данные. Собственно подключил delayed-assert, допилил его немного под нужны и он отлично зашел :slight_smile: