--- /dev/null
+# ν
μ€ν
+
+<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>