$pip install pytest
prefix로 test_를 붙여줘야 pytest가 인식 가능
def create_token(user_id: str) -> str:
return user_id + "_verified"
def test_create_token():
actual = create_token("grab")
expected = "grab_verified"
assert actual == expected # AssertionError
def login(user_id: str, user_pw: str) -> str:
user_repository = UserRepository()
user = user_repository.find_by_id(user_id)
if user.id == user_id and user.pw = user_pw:
return create_token(user_id)
else:
raise Exception("로그인 인증에 실패했습니다")
def test_login_successful():
#given
user_id = "grab"
user_pw = "1234"
#when
actual = login(user_id, user_pw)
#then
assert actual == "grab_verified"
def test_login_failed():
#given
user_id = "grab"
user_pw = "1234"
#when & then
with pytest.raises(Exception):
login(user_id, user_pw)
일반적으로 통합테스트는 외부 의존성을 포함하지만, 원래는 운영 환경과 분리되어야 한다. 예를 들어 운영 DB에 연동하면 안된다.
테스트에서 재현할 수 없는 외부 의존성은 테스트 더블(대체 객체)을 사용
# HTTP 요청으로 로그인 요청 시 애플리케이션은 웹 인터페이스를 제공해야
from fastapi import FastAPI
app = FastAPI()
class LoginReq(BaseModel):
id: str
pw: str
@app.get("/login")
def login_endpoint(req: LoginRequest):
token = login(user_id=req.id, user_pw=req.pw)
return {
"token": token,
}
import requests
def test_login_endpoint():
# given
api_host = "localhost:8000"
payload = {
id: "grab",
pw: "1234"
}
# when
res = requests.post(url=f"{api_host}/login", json=payload)
# then
assert res.data() == {
"token": "grab_verified"
}
class DummyRepository(Repository):
def insert(self, data):
return True
def find_by_id(self, user_id):
return "grab"
dummy에서 최소한의 구현만 해둔. 미리 준비해둔 결과만을 반환
class StubUserRepository(Repository):
def insert(self, data):
return "OK"
def findById(self, user_id):
return {"id": user_id, "name": "test_grab", ...}
stub에서 테스트에 필요한 정보를 기록해둠.
class SpyUserRepository(Repository):
insert_called = 0
def insert(self, data):
SpyUserRepository.insert_called += 1
return "OK"
@property
def get_insert_called(self):
return SpyUserRepository.insert_called
class FakeUserRepository(Repository):
def __init__(self):
self.users = []
def insert(self, data):
self.users.append(data)
def find_by_id(self, user_id):
return [user for user in self.users if user.id == user.id]
행위 검증 함.(fake는 단순 값 반환) 여기선 메서드가 호출되었는지도 확인 가능
@mock.patch.object(UserRepository, 'insert')
def test(insert_method):
insert_method.return_value = "OK"
insert_method({"id": 1, "name": "grab"})
# requests라는 서드 파티 라이브러리에 mocking하는 사례
@patch("requests.get")
def test_get_user(mock_get):
res = mock_get.return_value
res.status_code = 200
res.json.return_value = {
"name": "Test User",
"email": "user@test.com"
}
user = get_user(1)