Python · Тестування з pytest · Початковий
Параметризовані тести
Запускайте одну тест-функцію з кількома вхідними даними за допомогою @pytest.mark.parametrize.
Короткий вступ до теми та пояснення перед вправами (вправи нижче):
Патерни parametrize
#Довідник: parametrize
#Вправи:
Параметризоване тестування square(n)
#Реалізуйте `square(n)`, яка повертає `n * n`. Параметризуйте `test_square` принаймні з п'ятьма кейсами: додатне ціле, від'ємне ціле, нуль, float і велике число.
import pytest
def square(n):
pass # реалізуйте тут
@pytest.mark.parametrize("n, expected", [
# додайте 5 рядків
])
def test_square(n, expected):
assert square(n) == expected
Рішення
import pytest
def square(n):
return n * n
@pytest.mark.parametrize("n, expected", [
(3, 9),
(-4, 16),
(0, 0),
(2.5, 6.25),
(1000, 1_000_000),
])
def test_square(n, expected):
assert square(n) == expected
Параметризоване тестування is_palindrome
#Реалізуйте `is_palindrome(s)`, яка повертає `True`, якщо `s` читається однаково з обох боків. Параметризуйте принаймні чотирма паліндромами (повертають `True`) і трьома не-паліндромами (повертають `False`). Включіть порожній рядок (має повертати `True`).
import pytest
def is_palindrome(s):
pass # реалізуйте тут
@pytest.mark.parametrize("text, expected", [
# паліндроми (True) і не-паліндроми (False)
])
def test_is_palindrome(text, expected):
assert is_palindrome(text) == expected
Рішення
import pytest
def is_palindrome(s):
return s == s[::-1]
@pytest.mark.parametrize("text, expected", [
("racecar", True),
("level", True),
("madam", True),
("", True),
("hello", False),
("python", False),
("abcba", True),
("abcde", False),
])
def test_is_palindrome(text, expected):
assert is_palindrome(text) == expected
Параметризоване тестування з двома аргументами
#`clamp(value, lo, hi)` вже реалізовано. Параметризуйте `test_clamp` принаймні шістьма кейсами -- включіть значення у межах діапазону, нижче нижньої межі, вище верхньої та граничні значення. Кожен рядок має містити чотири елементи: `value, lo, hi, expected`.
import pytest
def clamp(value, lo, hi):
return max(lo, min(value, hi))
@pytest.mark.parametrize("value, lo, hi, expected", [
# додайте рядки тут
])
def test_clamp(value, lo, hi, expected):
assert clamp(value, lo, hi) == expected
Рішення
import pytest
def clamp(value, lo, hi):
return max(lo, min(value, hi))
@pytest.mark.parametrize("value, lo, hi, expected", [
(5, 0, 10, 5), # у межах діапазону
(-5, 0, 10, 0), # нижче нижньої межі
(15, 0, 10, 10), # вище верхньої межі
(0, 0, 10, 0), # на нижній межі
(10, 0, 10, 10), # на верхній межі
(50, 40, 60, 50), # інший діапазон
])
def test_clamp(value, lo, hi, expected):
assert clamp(value, lo, hi) == expected
Власні IDs для параметризованого тесту
#Параметризований тест нижче автоматично генерує малозрозумілі ID на кшталт `test_parse_int[42-42]`. Додайте `ids=[...]` до декоратора з описовими назвами. Запустіть `pytest -v` до і після, щоб побачити різницю.
import pytest
def parse_int(s):
return int(s.strip())
@pytest.mark.parametrize("text, expected", [
("42", 42),
(" 7 ", 7),
("-3", -3),
("0", 0),
])
def test_parse_int(text, expected):
assert parse_int(text) == expected
Рішення
import pytest
def parse_int(s):
return int(s.strip())
@pytest.mark.parametrize("text, expected", [
("42", 42),
(" 7 ", 7),
("-3", -3),
("0", 0),
], ids=["plain-integer", "with-whitespace", "negative", "zero"])
def test_parse_int(text, expected):
assert parse_int(text) == expected
Параметризовані граничні випадки для валідатора
#Реалізуйте `is_valid_username(s)` з трьома правилами: довжина від 3 до 20 символів, лише алфанумерні символи, не може починатися з цифри. Параметризуйте принаймні трьома коректними і чотирма некоректними іменами користувача.
import pytest
def is_valid_username(s):
pass # реалізуйте три правила валідації
@pytest.mark.parametrize("username, expected", [
# коректні (True) і некоректні (False) кейси
])
def test_is_valid_username(username, expected):
assert is_valid_username(username) == expected
Рішення
import pytest
def is_valid_username(s):
if not isinstance(s, str):
return False
if not (3 <= len(s) <= 20):
return False
if not s.isalnum():
return False
if s[0].isdigit():
return False
return True
@pytest.mark.parametrize("username, expected", [
("alice", True),
("User123", True),
("abc", True), # мінімальна довжина
("ab", False), # задовго коротко
("1alice", False), # починається з цифри
("user name", False), # пробіл
("a" * 21, False), # задовго довго
])
def test_is_valid_username(username, expected):
assert is_valid_username(username) == expected