Тест, которого вы хотите достичь, легко выполнить с помощью pytest. Никаких особых хитростей не требуется, просто следуйте документам и руководствам pytest:
import pytest
def test_phonenumber():
pn = PhoneNumber(id=1, country="country", country_code="code", number="number", extension="extension")
assert pn.id == 1
assert pn.country == 'country'
assert pn.country_code == 'code'
assert pn.number == 'number'
assert pn.extension == 'extension'
Но я согласен с этим комментарием:
Вообще говоря, такие тесты не пишутся. Пидантик имеет
хороший набор тестов (включая модульный тест, подобный тому, который вы предлагаете)
. Ваш тест должен охватывать написанный вами код и логику, а не
пакеты, которые вы импортировали.
Если у вас есть такая модель, как модель PhoneNumber
, которая довольно проста и не имеет «особого»/«причудливого» поведения, то написание тестов, которые просто создают ее экземпляры и проверяют атрибуты, не будет таким полезным. Подобные тесты подобны тестированию самого Pydantic.
Если, однако, ваша модель имеет некоторые функции-валидаторы, которые выполняют какие-то "специальные"/"причудливые" проверки, например, она проверяет соответствие country
и country_code
:
from pydantic import BaseModel, root_validator
class PhoneNumber(BaseModel):
...
@root_validator(pre=True)
def check_country(cls, values):
"""Check that country_code is the 1st 2 letters of country"""
country: str = values.get('country')
country_code: str = values.get('country_code')
if not country.lower().startswith(country_code.lower()):
raise ValueError('country_code and country do not match')
return values
... тогда модульный тест для этого конкретного поведения был бы более полезен:
import pytest
def test_phonenumber_country_code():
"""Expect test to fail because country_code and country do not match"""
with pytest.raises(ValueError):
PhoneNumber(id=1, country='JAPAN', country_code='XY', number='123', extension='456')
Кроме того, как я упоминал в моем комментарии, поскольку вы упомянули FastAPI, если вы используете эту модель как часть определения маршрута (будь то параметр запроса или модель ответа), то более полезным тестом было бы убедиться, что ваш маршрут может правильно использовать вашу модель.
@app.post("/phonenumber")
async def add_phonenumber(phonenumber: PhoneNumber):
"""The model is used here as part of the Request Body"""
# Do something with phonenumber
return JSONResponse({'message': 'OK'}, status_code=200)
from fastapi.testclient import TestClient
client = TestClient(app)
def test_add_phonenumber_ok():
"""Valid PhoneNumber, should be 200/OK"""
# This would be what the JSON body of the request would look like
body = {
"id": 1,
"country": "Japan",
"country_code": "JA",
"number": "123",
"extension": "81",
}
response = client.post("/phonenumber", json=body)
assert response.status_code == 200
def test_add_phonenumber_error():
"""Invalid PhoneNumber, should be a validation error"""
# This would be what the JSON body of the request would look like
body = {
"id": 1,
"country": "Japan",
# `country_code` is missing
"number": 99999, # `number` is int, not str
"extension": "81",
}
response = client.post("/phonenumber", json=body)
assert response.status_code == 422
assert response.json() == {
'detail': [{
'loc': ['body', 'country_code'],
'msg': 'field required',
'type': 'value_error.missing'
}]
}
Что, по вашему мнению, должен проверить тест? Как это связано с FastAPI? Поскольку вы можете использовать модели pydantic без с помощью FastAPI.
@GinoMempin Пожалуйста, проверьте мое редактирование.
@ Марк Да, это было. Я внес изменения. Спасибо, что указали на это.
Вообще говоря, вы не пишете такие тесты. У Pydantic есть хороший набор тестов (включая модульный тест, подобный тому, который вы предлагаете). Ваш тест должен охватывать написанный вами код и логику, а не импортированные вами пакеты.
@Марк О! Я понимаю. Большое спасибо!
Поскольку вы пометили это с помощью FastAPI и если вы используете эту модель как часть маршрута (либо в качестве параметра запроса, либо в качестве модели ответа), более полезным тестом является проверка того, что вызов вашего маршрута/API правильно использует вашу модель ( например, передача тела JSON правильно преобразуется в вашу модель PhoneNumber).
@GinoMempin Теперь я понимаю. Спасибо!