Python · Тестирование с pytest · Начальный
Параметризованные тесты
Запускайте одну тест-функцию с несколькими входными данными через @pytest.mark.parametrize.
Краткое введение в тему и пояснения перед упражнениями (упражнения ниже):
Паттерны параметризации
#Краткий справочник по parametrize
#Упражнения:
Параметризация square(n)
#Напишите `square(n)`, которая возвращает `n * n`. Используйте `@pytest.mark.parametrize`, чтобы протестировать её минимум с 5 разными входными данными: положительное целое, отрицательное целое, ноль, число с плавающей точкой и большое число.
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),
(0.5, 0.25),
(100, 10000),
])
def test_square(n, expected):
assert square(n) == expected
Параметризация is_palindrome
#Напишите `is_palindrome(s)`, которая возвращает True, если строка одинаково читается в обоих направлениях. Используйте `@pytest.mark.parametrize` с минимум 4 палиндромами и 3 не-палиндромами, включая ожидаемое булево значение вторым параметром.
import pytest
def is_palindrome(s):
pass
@pytest.mark.parametrize("s, expected", [
# палиндромы (True) и не-палиндромы (False)
])
def test_is_palindrome(s, expected):
assert is_palindrome(s) == expected
Решение
import pytest
def is_palindrome(s):
return s == s[::-1]
@pytest.mark.parametrize("s, expected", [
("racecar", True),
("madam", True),
("level", True),
("", True),
("hello", False),
("python", False),
("abcba", True),
("abcde", False),
])
def test_is_palindrome(s, expected):
assert is_palindrome(s) == expected
Параметризация с двумя аргументами
#Используйте `@pytest.mark.parametrize` для тестирования `clamp(value, lo, hi)` минимум с 5 кейсами: значение внутри диапазона, на нижней границе, на верхней границе, ниже нижней границы и выше верхней. Используйте четыре параметра на строку: `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),
(0, 0, 10, 0),
(10, 0, 10, 10),
(-5, 0, 10, 0),
(15, 0, 10, 10),
(-1, 0, 10, 0),
])
def test_clamp(value, lo, hi, expected):
assert clamp(value, lo, hi) == expected
Добавление пользовательских ID
#Параметризованный тест ниже автоматически генерирует бесполезные ID вроде `test_parse_int[42-42]`. Добавьте `ids=[...]` в декоратор с описательными именами. Запустите `pytest -v` до и после, чтобы увидеть разницу.
import pytest
def parse_int(s):
return int(s.strip())
@pytest.mark.parametrize("s, expected", [
("42", 42),
(" 7 ", 7),
("-10", -10),
("0", 0),
])
def test_parse_int(s, expected):
assert parse_int(s) == expected
Решение
import pytest
def parse_int(s):
return int(s.strip())
@pytest.mark.parametrize("s, expected", [
("42", 42),
(" 7 ", 7),
("-10", -10),
("0", 0),
], ids=["plain-integer", "with-whitespace", "negative", "zero"])
def test_parse_int(s, expected):
assert parse_int(s) == expected
Параметризация граничных случаев валидатора
#Напишите `is_valid_username(s)`, которая возвращает True, только если строка содержит от 3 до 20 символов, состоит только из букв и цифр и не начинается с цифры. Используйте `@pytest.mark.parametrize` для проверки минимум 3 допустимых и 4 недопустимых имён пользователей.
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 s or not (3 <= len(s) <= 20):
return False
if s[0].isdigit():
return False
return all(c.isalnum() for c in s)
@pytest.mark.parametrize("username, expected", [
("alice", True),
("user123", True),
("A1b2C3", True),
("ab", False),
("a" * 21, False),
("1alice", False),
("alice!", False),
("", False),
])
def test_is_valid_username(username, expected):
assert is_valid_username(username) == expected