⚖️ Старый vs Новый подход

← К оглавлению урока

⚡ Главные эволюции

  • Хардкод URL в тестах → BASE_URL переменная → класс с self.url
  • resp.text + ручной разбор → resp.json() напрямую
  • Запросы разбросаны по тестам → класс-обёртка CompanyApi
  • Проверка статуса после каждого вызова → проверка внутри метода класса

Сравнение 1: хардкод URL → base_url → класс

Из лекции (начальный подход) — URL в каждом тесте

# test_v1_hardcode.py
import requests

def test_get_companies():
    resp = requests.get("http://5.101.50.27:8000/company/list")  # хардкод
    assert resp.status_code == 200

def test_auth():
    resp = requests.post("http://5.101.50.27:8000/auth/login",   # хардкод снова
                         json={"username": "harrypotter", "password": "expelliarmus"})
    assert resp.status_code == 200
Проблема: при смене сервера или порта нужно менять URL в каждом тесте вручную.

Из лекции (улучшение) — переменная base_url

# test_v2_base_url.py
import requests

base_url = "http://5.101.50.27:8000"  # один раз вверху файла

def test_get_companies():
    resp = requests.get(base_url + "/company/list")
    assert resp.status_code == 200

def test_auth():
    resp = requests.post(base_url + "/auth/login",
                         json={"username": "harrypotter", "password": "expelliarmus"})
    assert resp.status_code == 200

Современный подход — класс CompanyApi

# company_api.py
import requests


class CompanyApi:
    def __init__(self, url):
        self.url = url  # URL хранится в объекте, легко переопределить

    def get_company_list(self):
        resp = requests.get(self.url + "/company/list")
        assert resp.status_code == 200
        return resp.json()


# test_v3_class.py
from company_api import CompanyApi

BASE_URL = "http://5.101.50.27:8000"

def test_get_companies():
    api = CompanyApi(BASE_URL)
    companies = api.get_company_list()
    assert len(companies) > 0
Преимущества класса: URL в одном месте; методы переиспользуются; тест не знает деталей HTTP-вызова.

Сравнение 2: resp.text vs resp.json()

Устаревший способ — ручной разбор через text

# Из лекции: так делать неудобно
import requests
import json

resp = requests.get("http://5.101.50.27:8000/company/list")
# resp.text — строка, нужно вручную вызывать json.loads()
body = json.loads(resp.text)
first_name = body[0]["name"]  # работает, но verbose

Современный способ — resp.json()

# Рекомендуется: requests делает разбор за нас
import requests

resp = requests.get("http://5.101.50.27:8000/company/list")
body = resp.json()           # сразу dict/list, без json.loads()
first_name = body[0]["name"] # чище и короче
Когда всё же нужен resp.text: если сервер возвращает не JSON (XML, HTML, plain text), или для отладки — вывести сырой ответ.

Сравнение 3: повторение кода запроса в тестах → инкапсуляция

Из лекции: дублирование в каждом тесте

# test_duplicated.py — плохой паттерн
import requests

BASE_URL = "http://5.101.50.27:8000"

def test_create_company_increases_count():
    # Получаем список ДО
    resp = requests.get(BASE_URL + "/company/list")
    assert resp.status_code == 200
    initial_count = len(resp.json())

    # Создаём компанию
    resp2 = requests.post(BASE_URL + "/company/create",
                          json={"name": "Test", "description": "desc"})
    assert resp2.status_code == 201

    # Получаем список ПОСЛЕ
    resp3 = requests.get(BASE_URL + "/company/list")
    assert resp3.status_code == 200
    assert len(resp3.json()) == initial_count + 1

Современный подход — метод класса

# test_clean.py — с CompanyApi
from company_api import CompanyApi

BASE_URL = "http://5.101.50.27:8000"

def test_create_company_increases_count():
    api = CompanyApi(BASE_URL)

    initial_count = len(api.get_company_list())   # статус проверяется внутри метода
    api.create_company("Test", "desc")
    assert len(api.get_company_list()) == initial_count + 1
Результат: тест в 3 строки вместо 12; проверки статусов — внутри класса; читаемость максимальная.

Сравнение 4: фиксированный ID → динамический

Ненадёжный тест с хардкод-ID (из лекции: так делать нельзя)

# Плохо: ID может не существовать или измениться
def test_get_company_bad():
    resp = requests.get(BASE_URL + "/company/7")  # ID 7 может не быть!
    assert resp.status_code == 200

Надёжный тест: создаём компанию, берём ID из ответа

# Хорошо: ID получаем из ответа на создание
def test_get_company_good():
    api = CompanyApi(BASE_URL)
    result = api.create_company("Dynamic Company", "no hardcode")
    new_id = result["id"]           # ID из ответа, не из головы

    company = api.get_company(new_id)
    assert company["name"] == "Dynamic Company"