Python · Тестування з pytest · Початковий
Фікстури
Використовуйте @pytest.fixture для повторного використання налаштування без зайвого коду.
Короткий вступ до теми та пояснення перед вправами (вправи нижче):
Патерни фікстур, які ви будете використовувати щодня
#Довідник: фікстури
#Вправи:
Фікстура зі списком чисел
#Напишіть фікстуру `numbers`, яка повертає `[3, 1, 4, 1, 5, 9, 2, 6]`. Напишіть дві тест-функції, що використовують цю фікстуру: `test_sum` перевіряє, що сума дорівнює `31`, і `test_max` -- що максимум дорівнює `9`.
import pytest
@pytest.fixture
def numbers():
pass # поверніть список
def test_sum(numbers):
pass
def test_max(numbers):
pass
Рішення
import pytest
@pytest.fixture
def numbers():
return [3, 1, 4, 1, 5, 9, 2, 6]
def test_sum(numbers):
assert sum(numbers) == 31
def test_max(numbers):
assert max(numbers) == 9
Yield-фікстура з tmp_path
#Напишіть фікстуру `temp_csv`, яка використовує вбудовану фікстуру `tmp_path` для створення CSV-файлу з двома рядками вмісту. Використовуйте `yield` для передачі шляху до файлу тестам. Напишіть тест, який перевіряє кількість рядків і заголовок.
import pytest
@pytest.fixture
def temp_csv(tmp_path):
path = tmp_path / 'data.csv'
# запишіть два рядки до path
yield path
# очищення
def test_csv_has_two_lines(temp_csv):
pass
Рішення
import pytest
@pytest.fixture
def temp_csv(tmp_path):
path = tmp_path / 'data.csv'
path.write_text('name,age\nAlice,30\n')
yield path
if path.exists():
path.unlink()
def test_csv_has_two_lines(temp_csv):
lines = temp_csv.read_text().strip().splitlines()
assert len(lines) == 2
def test_csv_header(temp_csv):
first_line = temp_csv.read_text().splitlines()[0]
assert first_line == 'name,age'
Фікстура зі словником конфігурації
#Напишіть `@pytest.fixture` з назвою `app_config`, що повертає `{'base_url': 'https://api.example.com', 'timeout': 10, 'retries': 3}`. Напишіть функцію `build_url(config, path)`, яка об'єднує `base_url` і `path` без подвійних слешів. Напишіть три тести з використанням фікстури.
import pytest
@pytest.fixture
def app_config():
pass # поверніть словник конфігурації
def build_url(config, path):
pass # об'єднайте base_url і path
def test_build_url(app_config):
pass
Рішення
import pytest
@pytest.fixture
def app_config():
return {'base_url': 'https://api.example.com', 'timeout': 10, 'retries': 3}
def build_url(config, path):
return config['base_url'].rstrip('/') + '/' + path.lstrip('/')
def test_build_url(app_config):
url = build_url(app_config, '/users')
assert url == 'https://api.example.com/users'
def test_build_url_no_double_slash(app_config):
url = build_url(app_config, 'products')
assert '//' not in url.split('https://')[-1]
def test_config_timeout(app_config):
assert app_config['timeout'] == 10
Дві фікстури в одному тесті
#Створіть дві фікстури: `base_url`, що повертає `'https://api.example.com'`, та `headers`, що повертає `{'Content-Type': 'application/json', 'Accept': 'application/json'}`. Напишіть тест, що використовує обидві та перевіряє, що URL є HTTPS і заголовки містять правильні ключі.
import pytest
@pytest.fixture
def base_url():
pass
@pytest.fixture
def headers():
pass
def test_request_setup(base_url, headers):
pass
Рішення
import pytest
@pytest.fixture
def base_url():
return 'https://api.example.com'
@pytest.fixture
def headers():
return {'Content-Type': 'application/json', 'Accept': 'application/json'}
def test_request_setup(base_url, headers):
assert base_url.startswith('https://')
assert 'Content-Type' in headers
assert headers['Content-Type'] == 'application/json'
assert 'Accept' in headers
Тришарова ланцюжок фікстур
#Напишіть три пов'язані фікстури: `db_config` повертає словник з `host` і `port`, `db_connection(db_config)` повертає `{'status': 'connected', 'host': ..., 'port': ...}`, `db_cursor(db_connection)` повертає `{'query': None, 'connection': db_connection}`. Напишіть тест, що запитує лише `db_cursor` і перевіряє значення через ланцюжок.
import pytest
@pytest.fixture
def db_config():
pass
@pytest.fixture
def db_connection(db_config):
pass
@pytest.fixture
def db_cursor(db_connection):
pass
def test_cursor_ready(db_cursor):
pass
Рішення
import pytest
@pytest.fixture
def db_config():
return {'host': 'localhost', 'port': 5432}
@pytest.fixture
def db_connection(db_config):
return {'status': 'connected', 'host': db_config['host'], 'port': db_config['port']}
@pytest.fixture
def db_cursor(db_connection):
return {'query': None, 'connection': db_connection}
def test_cursor_ready(db_cursor):
assert db_cursor['query'] is None
assert db_cursor['connection']['status'] == 'connected'
assert db_cursor['connection']['host'] == 'localhost'