committed by
GitHub
1 changed files with 243 additions and 0 deletions
@ -0,0 +1,243 @@ |
|||||
|
# ํ
์คํ
|
||||
|
|
||||
|
<a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette</a> ๋๋ถ์ **FastAPI** ๋ฅผ ํ
์คํธํ๋ ์ผ์ ์ฝ๊ณ ์ฆ๊ฑฐ์ด ์ผ์ด ๋์์ต๋๋ค. |
||||
|
|
||||
|
Starlette๋ <a href="https://www.python-httpx.org\" class="external-link" target="_blank">HTTPX</a>๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฉฐ, ์ด๋ Requests๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณ๋์๊ธฐ ๋๋ฌธ์ ๋งค์ฐ ์น์ํ๊ณ ์ง๊ด์ ์
๋๋ค. |
||||
|
|
||||
|
์ด๋ฅผ ์ฌ์ฉํ๋ฉด FastAPI์์ <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a>๋ฅผ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค. |
||||
|
|
||||
|
## `TestClient` ์ฌ์ฉํ๊ธฐ |
||||
|
|
||||
|
/// info | ์ ๋ณด |
||||
|
|
||||
|
`TestClient` ์ฌ์ฉํ๋ ค๋ฉด, ์ฐ์ <a href="https://www.python-httpx.org" class="external-link" target="_blank">`httpx`</a> ๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค. |
||||
|
|
||||
|
[virtual environment](../virtual-environments.md){.internal-link target=_blank} ๋ฅผ ๋ง๋ค๊ณ , ํ์ฑํ ์ํจ ๋ค์ ์ค์นํ์ธ์. ์์: |
||||
|
|
||||
|
```console |
||||
|
$ pip install httpx |
||||
|
``` |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
`TestClient` ๋ฅผ ์ํฌํธํ์ธ์. |
||||
|
|
||||
|
**FastAPI** ์ดํ๋ฆฌ์ผ์ด์
์ ์ ๋ฌํ์ฌ `TestClient` ๋ฅผ ๋ง๋์ธ์. |
||||
|
|
||||
|
์ด๋ฆ์ด `test_` ๋ก ์์ํ๋ ํจ์๋ฅผ ๋ง๋์ธ์(`pytest` ์ ํ์ค์ ์ธ ๊ด๋ก์
๋๋ค). |
||||
|
|
||||
|
`httpx` ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก `TestClient` ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ธ์. |
||||
|
|
||||
|
ํ์ค์ ์ธ ํ์ด์ฌ ๋ฌธ๋ฒ์ ์ด์ฉํ์ฌ ํ์ธ์ด ํ์ํ ๊ณณ์ ๊ฐ๋จํ `assert` ๋ฌธ์ฅ์ ์์ฑํ์ธ์(์ญ์ ํ์ค์ ์ธ `pytest` ๊ด๋ก์
๋๋ค). |
||||
|
|
||||
|
{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *} |
||||
|
|
||||
|
/// tip | ํ |
||||
|
|
||||
|
ํ
์คํธ๋ฅผ ์ํ ํจ์๋ `async def` ๊ฐ ์๋๋ผ `def` ๋ก ์์ฑ๋จ์ ์ฃผ์ํ์ธ์. |
||||
|
|
||||
|
๊ทธ๋ฆฌ๊ณ ํด๋ผ์ด์ธํธ์ ๋ํ ํธ์ถ๋ `await` ๋ฅผ ์ฌ์ฉํ์ง ์๋ ์ผ๋ฐ ํธ์ถ์
๋๋ค. |
||||
|
|
||||
|
์ด๋ ๊ฒ ํ์ฌ ๋ณต์กํ ๊ณผ์ ์์ด `pytest` ๋ฅผ ์ง์ ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// note | ๊ธฐ์ ์ธ๋ถ์ฌํญ |
||||
|
|
||||
|
`from starlette.testclient import TestClient` ์ญ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. |
||||
|
|
||||
|
**FastAPI** ๋ ๊ฐ๋ฐ์์ ํธ์๋ฅผ ์ํด `starlette.testclient` ๋ฅผ `fastapi.testclient` ๋ก๋ ์ ๊ณตํ ๋ฟ์
๋๋ค. ์ด๋ ๋จ์ง `Starlette` ์์ ์ง์ ๊ฐ์ ธ์ค๋์ง์ ์ฐจ์ด์ผ ๋ฟ์
๋๋ค. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
/// tip | ํ |
||||
|
|
||||
|
FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ ์ธ์๋ ํ
์คํธ์์ `async` ํจ์๋ฅผ ํธ์ถํ๊ณ ์ถ๋ค๋ฉด (์: ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํจ์), ์ฌํ ํํ ๋ฆฌ์ผ์ [Async Tests](../advanced/async-tests.md){.internal-link target=_blank} ๋ฅผ ์ฐธ์กฐํ์ธ์. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## ํ
์คํธ ๋ถ๋ฆฌํ๊ธฐ |
||||
|
|
||||
|
์ค์ ์ ํ๋ฆฌ์ผ์ด์
์์๋ ํ
์คํธ๋ฅผ ๋ณ๋์ ํ์ผ๋ก ๋๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. |
||||
|
|
||||
|
|
||||
|
๊ทธ๋ฆฌ๊ณ **FastAPI** ์ ํ๋ฆฌ์ผ์ด์
๋ ์ฌ๋ฌ ํ์ผ์ด๋ ๋ชจ๋ ๋ฑ์ผ๋ก ๊ตฌ์ฑ๋ ์ ์์ต๋๋ค. |
||||
|
|
||||
|
### **FastAPI** app ํ์ผ |
||||
|
|
||||
|
[Bigger Applications](bigger-applications.md){.internal-link target=_blank} ์ ๋ฌ์ฌ๋ ํ์ผ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ผ๋ก ๊ฐ์ ํด๋ด
์๋ค. |
||||
|
|
||||
|
``` |
||||
|
. |
||||
|
โโโ app |
||||
|
โย ย โโโ __init__.py |
||||
|
โย ย โโโ main.py |
||||
|
``` |
||||
|
|
||||
|
`main.py` ํ์ผ ์์ **FastAPI** app ์ ๋ง๋ค์์ต๋๋ค: |
||||
|
|
||||
|
{* ../../docs_src/app_testing/main.py *} |
||||
|
|
||||
|
### ํ
์คํธ ํ์ผ |
||||
|
|
||||
|
ํ
์คํธ๋ฅผ ์ํด `test_main.py` ๋ผ๋ ํ์ผ์ ์์ฑํ ์ ์์ต๋๋ค. ์ด ํ์ผ์ ๋์ผํ Python ํจํค์ง(์ฆ, `__init__.py` ํ์ผ์ด ์๋ ๋์ผํ ๋๋ ํฐ๋ฆฌ)์ ์์นํ ์ ์์ต๋๋ค. |
||||
|
|
||||
|
``` hl_lines="5" |
||||
|
. |
||||
|
โโโ app |
||||
|
โย ย โโโ __init__.py |
||||
|
โย ย โโโ main.py |
||||
|
โย ย โโโ test_main.py |
||||
|
``` |
||||
|
|
||||
|
ํ์ผ๋ค์ด ๋์ผํ ํจํค์ง์ ์์นํด ์์ผ๋ฏ๋ก, ์๋ ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ์ฌ `main` ์์ `app` ๊ฐ์ฒด๋ฅผ ์ํฌํธ ํด์ฌ ์ ์์ต๋๋ค. |
||||
|
|
||||
|
{* ../../docs_src/app_testing/test_main.py hl[3] *} |
||||
|
|
||||
|
|
||||
|
...๊ทธ๋ฆฌ๊ณ ์ด์ ์ ์์ฑํ๋ ๊ฒ๊ณผ ๊ฐ์ ํ
์คํธ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. |
||||
|
|
||||
|
## ํ
์คํธ: ํ์ฅ๋ ์์ |
||||
|
|
||||
|
์ด์ ์์ ์์๋ฅผ ํ์ฅํ๊ณ ๋ ๋ง์ ์ธ๋ถ ์ฌํญ์ ์ถ๊ฐํ์ฌ ๋ค์ํ ๋ถ๋ถ์ ์ด๋ป๊ฒ ํ
์คํธํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค. |
||||
|
|
||||
|
### ํ์ฅ๋ FastAPI ์ ํ๋ฆฌ์ผ์ด์
ํ์ผ |
||||
|
|
||||
|
์ด์ ๊ณผ ๊ฐ์ ํ์ผ ๊ตฌ์กฐ๋ฅผ ๊ณ์ ์ฌ์ฉํด ๋ณด๊ฒ ์ต๋๋ค. |
||||
|
|
||||
|
``` |
||||
|
. |
||||
|
โโโ app |
||||
|
โย ย โโโ __init__.py |
||||
|
โย ย โโโ main.py |
||||
|
โย ย โโโ test_main.py |
||||
|
``` |
||||
|
|
||||
|
์ด์ **FastAPI** ์ฑ์ด ์๋ `main.py` ํ์ผ์ ๋ช ๊ฐ์ง ๋ค๋ฅธ **๊ฒฝ๋ก ์์
** ์ด ์ถ๊ฐ๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด๋ด
์๋ค. |
||||
|
|
||||
|
๋จ์ผ ์ค๋ฅ๋ฅผ ๋ฐํํ ์ ์๋ `GET` ์์
์ด ์์ต๋๋ค. |
||||
|
|
||||
|
์ฌ๋ฌ ๋ค๋ฅธ ์ค๋ฅ๋ฅผ ๋ฐํํ ์ ์๋ `POST` ์์
์ด ์์ต๋๋ค. |
||||
|
|
||||
|
๋ *๊ฒฝ๋ก ์์
* ๋ชจ๋ `X-Token` ํค๋๋ฅผ ์๊ตฌํฉ๋๋ค. |
||||
|
|
||||
|
//// tab | Python 3.10+ |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/app_testing/app_b_an_py310/main.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.9+ |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/app_testing/app_b_an_py39/main.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.8+ |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/app_testing/app_b_an/main.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.10+ non-Annotated |
||||
|
|
||||
|
/// tip | ํ |
||||
|
|
||||
|
๋ ์ ์์ผ๋ฉด `Annotated` ๋ฒ์ ์ฌ์ฉ์ ๊ถ์ฅํฉ๋๋ค. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/app_testing/app_b_py310/main.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
//// tab | Python 3.8+ non-Annotated |
||||
|
|
||||
|
/// tip | ํ |
||||
|
|
||||
|
๋ ์ ์์ผ๋ฉด `Annotated` ๋ฒ์ ์ฌ์ฉ์ ๊ถ์ฅํฉ๋๋ค. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
```Python |
||||
|
{!> ../../docs_src/app_testing/app_b/main.py!} |
||||
|
``` |
||||
|
|
||||
|
//// |
||||
|
|
||||
|
### ํ์ฅ๋ ํ
์คํธ ํ์ผ |
||||
|
|
||||
|
์ด์ ๋ `test_main.py` ๋ฅผ ํ์ฅ๋ ํ
์คํธ๋ค๋ก ์์ ํ ์ ์์ต๋๋ค: |
||||
|
|
||||
|
{* ../../docs_src/app_testing/app_b/test_main.py *} |
||||
|
|
||||
|
|
||||
|
ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ์ ๋ณด๋ฅผ ์ ๋ฌํด์ผ ํ๋๋ฐ ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด, `httpx`์์ ํด๋น ์์
์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๊ฒ์(Google)ํ๊ฑฐ๋, `requests`์์์ ๋ฐฉ๋ฒ์ ๊ฒ์ํด๋ณด์ธ์. HTTPX๋ Requests์ ๋์์ธ์ ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณ๋์์ต๋๋ค. |
||||
|
|
||||
|
๊ทธ ํ, ํ
์คํธ์์๋ ๋์ผํ๊ฒ ์ ์ฉํ๋ฉด ๋ฉ๋๋ค. |
||||
|
|
||||
|
์์: |
||||
|
|
||||
|
* *๊ฒฝ๋ก* ํน์ *์ฟผ๋ฆฌ* ๋งค๊ฐ๋ณ์๋ฅผ ์ ๋ฌํ๋ ค๋ฉด, URL ์์ฒด์ ์ถ๊ฐํ๋ค. |
||||
|
* JSON ๋ณธ๋ฌธ์ ์ ๋ฌํ๋ ค๋ฉด, ํ์ด์ฌ ๊ฐ์ฒด (์๋ฅผ๋ค๋ฉด `dict`) ๋ฅผ `json` ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ๋ค. |
||||
|
* JSON ๋์ *ํผ ๋ฐ์ดํฐ* ๋ฅผ ๋ณด๋ด์ผํ๋ค๋ฉด, `data` ํ๋ผ๋ฏธํฐ๋ฅผ ๋์ ์ ๋ฌํ๋ค. |
||||
|
* *ํค๋* ๋ฅผ ์ ๋ฌํ๋ ค๋ฉด, `headers` ํ๋ผ๋ฏธํฐ์ `dict` ๋ฅผ ์ ๋ฌํ๋ค. |
||||
|
* *์ฟ ํค* ๋ฅผ ์ ๋ฌํ๋ ค๋ฉด, `cookies` ํ๋ผ๋ฏธํฐ์ `dict` ๋ฅผ ์ ๋ฌํ๋ค. |
||||
|
|
||||
|
๋ฐฑ์๋๋ก ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ๋ณด๋ด๋์ง ์ ๋ณด๋ฅผ ๋ ์ป์ผ๋ ค๋ฉด (`httpx` ํน์ `TestClient` ๋ฅผ ์ด์ฉํด์) <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX documentation</a> ๋ฅผ ํ์ธํ์ธ์. |
||||
|
|
||||
|
/// info | ์ ๋ณด |
||||
|
|
||||
|
`TestClient` ๋ Pydantic ๋ชจ๋ธ์ด ์๋๋ผ JSON ์ผ๋ก ๋ณํ๋ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ต๋๋ค. |
||||
|
|
||||
|
๋ง์ฝ ํ
์คํธ์ค Pydantic ๋ชจ๋ธ์ ์ดํ๋ฆฌ์ผ์ด์
์ผ๋ก์ ๋ณด๋ด๊ณ ์ถ๋ค๋ฉด, [JSON ํธํ ๊ฐ๋ฅ ์ธ์ฝ๋](encoder.md){.internal-link target=_blank} ์ ์ค๋ช
๋์ด ์๋ `jsonable_encoder` ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. |
||||
|
|
||||
|
/// |
||||
|
|
||||
|
## ์คํํ๊ธฐ |
||||
|
|
||||
|
ํ
์คํธ ์ฝ๋๋ฅผ ์์ฑํ๊ณ , `pytest` ๋ฅผ ์ค์นํด์ผํฉ๋๋ค. |
||||
|
|
||||
|
[virtual environment](../virtual-environments.md){.internal-link target=_blank} ๋ฅผ ๋ง๋ค๊ณ , ํ์ฑํ ์ํจ ๋ค์ ์ค์นํ์ธ์. ์์: |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ pip install pytest |
||||
|
|
||||
|
---> 100% |
||||
|
``` |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
`pytest` ํ์ผ๊ณผ ํ
์คํธ๋ฅผ ์๋์ผ๋ก ๊ฐ์งํ๊ณ ์คํํ ๋ค์, ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ ๊ฒ์
๋๋ค. |
||||
|
|
||||
|
ํ
์คํธ๋ฅผ ๋ค์ ๋ช
๋ น์ด๋ก ์คํํ์ธ์. |
||||
|
|
||||
|
<div class="termy"> |
||||
|
|
||||
|
```console |
||||
|
$ pytest |
||||
|
|
||||
|
================ test session starts ================ |
||||
|
platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 |
||||
|
rootdir: /home/user/code/superawesome-cli/app |
||||
|
plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1 |
||||
|
collected 6 items |
||||
|
|
||||
|
---> 100% |
||||
|
|
||||
|
test_main.py <span style="color: green; white-space: pre;">...... [100%]</span> |
||||
|
|
||||
|
<span style="color: green;">================= 1 passed in 0.03s =================</span> |
||||
|
``` |
||||
|
|
||||
|
</div> |
Loadingโฆ
Reference in new issue