committed by
GitHub
1 changed files with 108 additions and 0 deletions
@ -0,0 +1,108 @@ |
|||
# ๋น๋๊ธฐ ํ
์คํธ ์ฝ๋ ์์ฑ |
|||
|
|||
์ด์ ์ฅ์์ `TestClient` ๋ฅผ ์ด์ฉํด **FastAPI** ์ดํ๋ฆฌ์ผ์ด์
ํ
์คํธ๋ฅผ ์์ฑํ๋ ๋ฒ์ ๋ฐฐ์ฐ์
จ์ํ
๋ฐ์. |
|||
์ง๊ธ๊น์ง๋ `async` ํค์๋ ์ฌ์ฉ์์ด ๋๊ธฐ ํจ์์ ํ
์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฒ๋ง ์ตํ์ต๋๋ค. |
|||
|
|||
ํ์ง๋ง ๋น๋๊ธฐ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ํ
์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋งค์ฐ ์ ์ฉํ ์ ์์ต๋๋ค. |
|||
์๋ฅผ ๋ค๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋น๋๊ธฐ๋ก ์ฟผ๋ฆฌํ๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด๋ด
์๋ค. |
|||
FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์์ฒญ์ ๋ณด๋ด๊ณ , ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐฑ์๋๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฌ๋ฐ๋ฅด๊ฒ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋กํ๋์ง ํ์ธํ๊ณ ์ถ์ ๋๊ฐ ์์ ๊ฒ๋๋ค. |
|||
|
|||
์ด๋ฐ ๊ฒฝ์ฐ์ ํ
์คํธ ์ฝ๋๋ฅผ ์ด๋ป๊ฒ ๋น๋๊ธฐ๋ก ์์ฑํ๋์ง ์์๋ด
์๋ค. |
|||
|
|||
## pytest.mark.anyio |
|||
|
|||
์์์ ์์ฑํ ํ
์คํธ ํจ์์์ ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ๊ณ ์ถ๋ค๋ฉด, ํ
์คํธ ์ฝ๋๋ ๋น๋๊ธฐ ํจ์์ฌ์ผํฉ๋๋ค. |
|||
AnyIO๋ ํน์ ํ
์คํธ ํจ์๋ฅผ ๋น๋๊ธฐ ํจ์๋ก ํธ์ถ ํ ์ ์๋ ๊น๋ํ ํ๋ฌ๊ทธ์ธ์ ์ ๊ณตํฉ๋๋ค. |
|||
|
|||
|
|||
## HTTPX |
|||
|
|||
**FastAPI** ์ ํ๋ฆฌ์ผ์ด์
์ด `async def` ๋์ `def` ํค์๋๋ก ์ ์ธ๋ ํจ์๋ฅผ ์ฌ์ฉํ๋๋ผ๋, ๋ด๋ถ์ ์ผ๋ก๋ ์ฌ์ ํ `๋น๋๊ธฐ` ์ ํ๋ฆฌ์ผ์ด์
์
๋๋ค. |
|||
|
|||
`TestClient`๋ pytest ํ์ค์ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์ผ๋ฐ์ ์ธ `def` ํ
์คํธ ํจ์ ๋ด์์ ํธ์ถํ ์ ์๋๋ก ๋ด๋ถ์์ ๋ง์ ์ ๋ถ๋ฆฝ๋๋ค. ํ์ง๋ง ์ด ๋ง์ ์ ๋น๋๊ธฐ ํจ์ ๋ด๋ถ์์ ์ฌ์ฉํ ๋๋ ๋ ์ด์ ์๋ํ์ง ์์ต๋๋ค. ํ
์คํธ๋ฅผ ๋น๋๊ธฐ๋ก ์คํํ๋ฉด, ๋ ์ด์ ํ
์คํธ ํจ์ ๋ด๋ถ์์ `TestClient`๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. |
|||
|
|||
`TestClient`๋ <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ณ ์์ผ๋ฉฐ, ๋คํํ ์ด๋ฅผ ์ง์ ์ฌ์ฉํ์ฌ API๋ฅผ ํ
์คํธํ ์ ์์ต๋๋ค. |
|||
|
|||
## ์์ |
|||
|
|||
๊ฐ๋จํ ์์๋ฅผ ์ํด [๋ ํฐ ์ดํ๋ฆฌ์ผ์ด์
๋ง๋ค๊ธฐ](../ko/tutorial/bigger-applications.md){.internal-link target=_blank} ์ [ํ
์คํธ](../ko/tutorial/testing.md){.internal-link target=_blank}:์์ ๋ค๋ฃฌ ํ์ผ ๊ตฌ์กฐ์ ๋น์ทํ ํํ๋ฅผ ํ์ธํด๋ด
์๋ค: |
|||
|
|||
``` |
|||
. |
|||
โโโ app |
|||
โย ย โโโ __init__.py |
|||
โย ย โโโ main.py |
|||
โย ย โโโ test_main.py |
|||
``` |
|||
|
|||
`main.py`๋ ์๋์ ๊ฐ์์ผ ํฉ๋๋ค: |
|||
|
|||
{* ../../docs_src/async_tests/main.py *} |
|||
|
|||
`test_main.py` ํ์ผ์ `main.py`์ ๋ํ ํ
์คํธ๊ฐ ์์ ํ
๋ฐ, ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค: |
|||
|
|||
{* ../../docs_src/async_tests/test_main.py *} |
|||
|
|||
## ์คํํ๊ธฐ |
|||
|
|||
์๋์ ๋ช
๋ น์ด๋ก ํ
์คํธ ์ฝ๋๋ฅผ ์คํํฉ๋๋ค: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pytest |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
## ์์ธํ ๋ณด๊ธฐ |
|||
|
|||
`@pytest.mark.anyio` ๋ง์ปค๋ pytest์๊ฒ ์ด ํ
์คํธ ํจ์๊ฐ ๋น๋๊ธฐ๋ก ํธ์ถ๋์ด์ผ ํจ์ ์๋ ค์ค๋๋ค: |
|||
|
|||
{* ../../docs_src/async_tests/test_main.py hl[7] *} |
|||
|
|||
/// tip | ํ |
|||
|
|||
ํ
์คํธ ํจ์๊ฐ ์ด์ `TestClient`๋ฅผ ์ฌ์ฉํ ๋์ฒ๋ผ ๋จ์ํ `def`๊ฐ ์๋๋ผ `async def`๋ก ์์ฑ๋ ์ ์ ์ฃผ๋ชฉํด์ฃผ์ธ์. |
|||
|
|||
/// |
|||
|
|||
๊ทธ ๋ค์์ `AsyncClient` ๋ก ์ฑ์ ๋ง๋ค๊ณ ๋น๋๊ธฐ ์์ฒญ์ `await` ํค์๋๋ก ๋ณด๋ผ ์ ์์ต๋๋ค: |
|||
|
|||
{* ../../docs_src/async_tests/test_main.py hl[9:12] *} |
|||
|
|||
์์ ์ฝ๋๋: |
|||
|
|||
```Python |
|||
response = client.get('/') |
|||
``` |
|||
|
|||
`TestClient` ์ ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ๊ณผ ๋์ผํฉ๋๋ค. |
|||
|
|||
/// tip | ํ |
|||
|
|||
์๋ก์ด `AsyncClient`๋ฅผ ์ฌ์ฉํ ๋ async/await๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ ์ ์ ์ฃผ๋ชฉํ์ธ์. ์ด ์์ฒญ์ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค. |
|||
|
|||
/// |
|||
|
|||
/// warning | ๊ฒฝ๊ณ |
|||
|
|||
๋ง์ฝ์ ์ดํ๋ฆฌ์ผ์ด์
์ด Lifespan ์ด๋ฒคํธ์ ์์กด์ฑ์ ๊ฐ๊ณ ์๋ค๋ฉด `AsyncClient` ๊ฐ ์ด๋ฌํ ์ด๋ฒคํธ๋ฅผ ์คํ์ํค์ง ์์ต๋๋ค. |
|||
`AsyncClient` ๊ฐ ํ
์คํธ๋ฅผ ์คํ์์ผฐ๋ค๋ ๊ฒ์ ํ์ธํ๊ธฐ ์ํด |
|||
`LifespanManager` from <a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>.ํ์ธํด์ฃผ์ธ์. |
|||
|
|||
|
|||
/// |
|||
|
|||
## ๊ทธ ์ธ์ ๋น๋๊ธฐ ํจ์ ํธ์ถ |
|||
|
|||
ํ
์คํธ ํจ์๊ฐ ์ด์ ๋น๋๊ธฐ ํจ์์ด๋ฏ๋ก, FastAPI ์ ํ๋ฆฌ์ผ์ด์
์ ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ ์ธ์๋ ๋ค๋ฅธ `async` ํจ์๋ฅผ ํธ์ถํ๊ณ `await` ํค์๋๋ฅผ ์ฌ์ฉ ํ ์ ์์ต๋๋ค. |
|||
|
|||
/// tip | ํ |
|||
|
|||
ํ
์คํธ์ ๋น๋๊ธฐ ํจ์ ํธ์ถ์ ํตํฉํ ๋ (์: <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MongoDB์ MotorClient</a>๋ฅผ ์ฌ์ฉํ ๋) `RuntimeError: Task attached to a different loop` ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค๋ฉด, ์ด๋ฒคํธ ๋ฃจํ๊ฐ ํ์ํ ๊ฐ์ฒด๋ ๋ฐ๋์ ๋น๋๊ธฐ ํจ์ ๋ด์์๋ง ์ธ์คํด์คํํด์ผ ํ๋ค๋ ์ ์ ์ฃผ์ํ์ธ์! |
|||
์๋ฅผ ๋ค์ด `@app.on_event("startup")` ์ฝ๋ฐฑ ๋ด์์ ์ธ์คํด์คํํ๋ ๊ฒ์ด ์ข์ต๋๋ค. |
|||
|
|||
/// |
Loadingโฆ
Reference in new issue