💻 Примеры: Requests в действии

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

⚡ Ключевые примеры

# test_companies.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
    assert resp.headers["Content-Type"] == "application/json"
    companies = resp.json()
    assert isinstance(companies, list)

def test_create_company():
    resp = requests.post(BASE_URL + "/company/create",
                         json={"name": "Test Co", "description": "Automated"})
    assert resp.status_code == 201
    assert resp.json()["name"] == "Test Co"

Пример 1: Первый GET-запрос

Получаем список компаний из X-Clients API и проверяем статус, заголовок и содержимое.

# test_companies.py
import requests

def test_simple_req():
    resp = requests.get("http://5.101.50.27:8000/company/list")
    assert resp.status_code == 200  # Проверяем, что сервер вернул 200 OK

Добавляем проверку Content-Type:

# test_companies.py
import requests

def test_simple_req():
    resp = requests.get("http://5.101.50.27:8000/company/list")

    assert resp.status_code == 200
    assert resp.headers["Content-Type"] == "application/json"  # JSON-ответ

Добавляем проверку содержимого ответа:

# test_companies.py
import requests

def test_simple_req():
    resp = requests.get("http://5.101.50.27:8000/company/list")

    response_body = resp.json()       # Разбираем JSON в Python list
    first_company = response_body[0]  # Первый элемент списка — dict

    assert resp.status_code == 200
    assert resp.headers["Content-Type"] == "application/json"
    assert first_company["name"] == "QA Студия 'ТестировщикЪ'"

Пример 2: resp.text vs resp.json()

# demo_text_vs_json.py
import requests

resp = requests.get("https://jsonplaceholder.typicode.com/posts/1")

# resp.text — всегда строка, даже если содержит JSON
print(type(resp.text))   # 
print(resp.text[:80])    # {"userId": 1, "id": 1, "title": "sunt aut...

# resp.json() — Python-объект (dict или list)
data = resp.json()
print(type(data))        # 
print(data["title"])     # sunt aut facere repellat provident...

# Если сервер вернул не JSON — JSONDecodeError
resp_html = requests.get("https://example.com")
# resp_html.json()  # Бросит: requests.exceptions.JSONDecodeError

Пример 3: POST-запрос — авторизация

# test_auth.py
import requests

BASE_URL = "http://5.101.50.27:8000"

def test_auth():
    creds = {
        "username": "harrypotter",
        "password": "expelliarmus"
    }
    resp = requests.post(BASE_URL + "/auth/login", json=creds)

    assert resp.status_code == 200
    assert resp.json()["user_token"] is not None  # Токен получен
После запуска теста можно открыть Run and Debug в VS Code и проверить объект resp — там будет полный токен авторизации.

Пример 4: POST-запрос — создание компании

# test_companies.py
import requests

BASE_URL = "http://5.101.50.27:8000"

def test_create_company():
    company = {
        "name": "python",
        "description": "requests"
    }
    resp = requests.post(BASE_URL + "/company/create", json=company)

    assert resp.status_code == 201  # 201 Created — компания создана
    body = resp.json()
    assert body["name"] == "python"
    assert body["is_active"] is True

Пример 5: PATCH-запрос — изменение компании

# company_api.py
import requests

class CompanyApi:
    def __init__(self, url):
        self.url = url

    def get_token(self, username="harrypotter", password="expelliarmus"):
        creds = {"username": username, "password": password}
        resp = requests.post(self.url + "/auth/login", json=creds)
        assert resp.status_code == 200
        return resp.json()["user_token"]

    def edit_company(self, company_id, new_name, new_descr):
        """Изменить название и описание компании"""
        token = self.get_token()
        url = f"{self.url}/company/update/{company_id}?client_token={token}"
        company_data = {"name": new_name, "description": new_descr}
        resp = requests.patch(url, json=company_data)
        assert resp.status_code == 200, f"Ошибка: {resp.status_code}"
        return resp.json()

Пример 6: DELETE-запрос — удаление компании

# company_api.py — метод удаления
    def delete_company(self, company_id):
        """Удалить компанию по ID"""
        token = self.get_token()
        url = f"{self.url}/company/{company_id}?client_token={token}"
        resp = requests.delete(url)
        assert resp.status_code == 200, f"Ошибка: {resp.status_code}"
        return resp.json()

Пример 7: Полный класс CompanyApi

# company_api.py
import requests

class CompanyApi:
    """Клиент для работы с API компаний X-Clients"""

    def __init__(self, url):
        self.url = url

    def get_token(self, username="harrypotter", password="expelliarmus"):
        """Получить токен авторизации"""
        creds = {"username": username, "password": password}
        resp = requests.post(self.url + "/auth/login", json=creds)
        assert resp.status_code == 200, f"Ошибка авторизации: {resp.status_code}"
        return resp.json()["user_token"]

    def get_company_list(self):
        """Получить список всех компаний"""
        resp = requests.get(self.url + "/company/list")
        assert resp.status_code == 200, f"Ошибка: {resp.status_code}"
        return resp.json()

    def get_company(self, company_id):
        """Получить компанию по ID"""
        resp = requests.get(self.url + f"/company/{company_id}")
        assert resp.status_code == 200, f"Ошибка: {resp.status_code}"
        return resp.json()

    def create_company(self, name, description=""):
        """Создать новую компанию"""
        company = {"name": name, "description": description}
        resp = requests.post(self.url + "/company/create", json=company)
        assert resp.status_code == 201, f"Ошибка: {resp.status_code}"
        return resp.json()

    def edit_company(self, company_id, new_name, new_descr):
        """Изменить компанию"""
        token = self.get_token()
        url = f"{self.url}/company/update/{company_id}?client_token={token}"
        resp = requests.patch(url, json={"name": new_name, "description": new_descr})
        assert resp.status_code == 200, f"Ошибка: {resp.status_code}"
        return resp.json()

    def delete_company(self, company_id):
        """Удалить компанию"""
        token = self.get_token()
        url = f"{self.url}/company/{company_id}?client_token={token}"
        resp = requests.delete(url)
        assert resp.status_code == 200, f"Ошибка: {resp.status_code}"
        return resp.json()

    def set_active_state(self, company_id, is_active):
        """Изменить статус активности компании"""
        token = self.get_token()
        url = f"{self.url}/company/status_update/{company_id}?client_token={token}"
        resp = requests.patch(url, json={"is_active": is_active})
        assert resp.status_code == 200, f"Ошибка: {resp.status_code}"
        return resp.json()

Пример 8: Тест с использованием CompanyApi

# test_x_clients.py
from company_api import CompanyApi

BASE_URL = "http://5.101.50.27:8000"

def test_create_company_increases_count():
    """Тест: создание компании увеличивает список на 1"""
    api = CompanyApi(BASE_URL)

    # 1. Запоминаем начальное количество
    companies_before = api.get_company_list()
    initial_count = len(companies_before)

    # 2. Создаём новую компанию
    api.create_company(name="Test Company", description="Automated test")

    # 3. Снова получаем список
    companies_after = api.get_company_list()
    final_count = len(companies_after)

    # 4. Проверяем: стало на 1 больше
    assert final_count == initial_count + 1, \
        f"Ожидалось {initial_count + 1}, получено {final_count}"


def test_get_one_company():
    """Тест: создать компанию и получить её по ID"""
    api = CompanyApi(BASE_URL)
    name = "PyCharm"
    descr = "IDE"

    # Создаём и сразу получаем ID
    result = api.create_company(name, descr)
    new_id = result["id"]

    # Получаем по ID и проверяем данные
    company = api.get_company(new_id)
    assert company["name"] == name
    assert company["description"] == descr
    assert company["is_active"] is True


def test_deactivate_company():
    """Тест: деактивация компании"""
    api = CompanyApi(BASE_URL)

    result = api.create_company("Company to deactivate")
    company_id = result["id"]

    body = api.set_active_state(company_id, False)
    assert body["is_active"] is False

Пример 9: Параметризованный тест через reqres.in

⚠️ С 2024 года reqres.in требует бесплатный API-ключ. Без заголовка x-api-key: reqres-free-v1 запрос вернёт 401 Unauthorized, и тест упадёт. Поэтому ниже передаём заголовок HEADERS. Актуальность ключа проверяйте на reqres.in.
# test_reqres.py
import requests
import pytest

BASE_URL = "https://reqres.in/api/users"
# С 2024 reqres.in требует бесплатный API-ключ в заголовке
HEADERS = {"x-api-key": "reqres-free-v1"}

@pytest.mark.parametrize("user_id, expected_first_name, expected_email", [
    (2, "Janet", "janet.weaver@reqres.in"),
])
def test_get_existing_user(user_id, expected_first_name, expected_email):
    """Тест: получение существующего пользователя"""
    response = requests.get(f"{BASE_URL}/{user_id}", headers=HEADERS)

    assert response.status_code == 200
    data = response.json()
    assert "data" in data

    user = data["data"]
    assert user["id"] == user_id
    assert user["first_name"] == expected_first_name
    assert user["email"] == expected_email


def test_get_non_existing_user():
    """Тест: несуществующий пользователь → 404"""
    response = requests.get(f"{BASE_URL}/23", headers=HEADERS)
    assert response.status_code == 404
    assert response.text == "{}"