인프런 커뮤니티 질문&답변
refresh() 메서드와 픽스처에 대해 질문이 있습니다.
해결된 질문
작성
·
30
0
픽스처 함수는 픽스처로, 픽스처 내부에서 사용되는 픽스처 함수는 객체로 표현하였습니다.
=====
host_user_calendar 픽스처에서 refresh() 메서드를 통해 host_user 객체를 db와 동기화해서 host_user 객체가 calendar 객체의 존재를 아는 것으로 이해했는데요.
그런데 해당 host_user 객체는 반환되지 않고 host_user_calendar 픽스처에 남아있게 되어 접근할 수 없으니 무의미한 행동이라고 보여졌습니다.
그런데 refresh()를 사용하지 않으면 test_사용자가_변경하는_항목만_변경되고_나머지는_기존_값을_유지한다() 테스트 함수에서 update_calendar 엔드포인트 호출 시 404 에러가 발생하는 것을 확인했습니다. 즉, user.calendar로 접근 시 None으로 평가되는 것이지요.
그렇다면 host_user를 반환하지 않아도 해당 host_user 객체는 client_user_auth 픽스처에서 공유되는 것일까요? (혹은 동일한 객체일까요?) 그래야 refresh()를 진행했을 때 오류가 뜨지 않는다는 점이 설명이 되더라구여.

여기서 또하나 궁금한 점은 client_with_auth 픽스처보다 host_user_calendar 픽스처가 먼저 실행이 되어야 공유되는 host_user 객체가 calendar 정보를 가질 수 있다는 점이었습니다. 이 실행 순서를 결정하는 프로세스에 대해서도 궁금합니다!
답변 2
1
이 실행 순서를 결정하는 프로세스에 대해서도 궁금합니다!
실행 순서는 의존성 주입순입니다. client_with_auth 에 host_user_calendar 의존성 주입(pytest fixture)을 선언하면, host_user_calendar 픽스처가 먼저 실행되지요. pytest를 실행하면 fixture 의존성 그래프를 형성하는데, FastAPI와 마찬가지로 fixture 의존성 순서를 따릅니다. ( pytest.mark.usefixture 나 autouse 옵션도 우선순위에 영향을 미치는데, 일단 여기에선 의존성 선언에 따른 순서만 설명드려도 이해하실 듯 해서 생략합니다. 🙂 )
그렇다면 첨부하신 이미지에서는 질문하시는 순서라면, 테스트 함수에서 client_with_auth 와 host_user_calendar 를 함께 선언하는 경우를 염두에 두신 것 같은데, 아마 매개변수 순서일 겁니다.
그런데 해당 host_user 객체는 반환되지 않고 host_user_calendar 픽스처에 남아있게 되어 접근할 수 없으니 무의미한 행동이라고 보여졌습니다.
의문을 섬세하게 가지셨네요. 👍 이는 pytest와 TestClient의 동작 특성에 기인하는 상황이긴 합니다. 실제 환경에서는 애플리케이션 서버가 구동된 상황과 사용자가 API를 호출하는 상황은 서로 독립되고 분리된 상황입니다. 그래서 말씀하신대로 의미없습니다.
하지만, 테스트 동작 상황에서는 이들이 한 프로세스(pytest 프로세스)에서 다루는 메모리에 올라가서 동일한 맥락 안에서 동작합니다. 왜냐하면, pytest에 선언한 SQLAlchemy 세션 객체를 픽스처, pytest 테스트 함수, TestClient가 모두가 공유해서 사용하며 동작하고 있습니다. TestClient 객체는 FastAPI 객체를 사용하고, FastAPI 객체에 의존성을 오버라이딩하여 주입하는 세션 객체는 fixture 만드는 데 사용한 세션 객체와 동일하거든요. 그래서 pytest fixture에서 host_user에 calendar 데이터가 적재되지 않은 상태라는 건, TestClient가 FastAPI 객체를 사용해 동작하는 환경과 동일한 세션 객체 상황/맥락입니다.
정리하면 애플리케이션 서버를 구동해 네트워크로 HTTP 연결을 호출하는 실제 환경과 동일하게 동작하는 게 아니라 빠르게 동작시키기 위해 ASGI 애플리케이션 객체를 사용해 실제 환경처럼 동작하는 특성에 대한 의아함을 가지신 겁니다. 🙂 그래서 이 경우엔, HTTP API 관점으로 보기보다는 pytest 맥락에서 동일한 SQLAlchemy 세션 객체가 바라보는 ORM 객체 상태로 동작 상황을 머리 속에 그리시면 명확해지실 거예요.
0
안녕하세요, 인프런 AI 인턴입니다. kyo lee님.
질문해주신 내용에 대해 답변 드리겠습니다.
1. refresh() 메서드와 객체 공유
refresh() 메서드는 SQLAlchemy에서 특정 객체의 상태를 데이터베이스의 최신 상태로 업데이트하기 위해 사용됩니다. refresh()를 사용하면 객체는 데이터베이스와 동기화되어, 최신의 값들을 가지게 됩니다. 이는 session을 통해 해당 객체에 대한 참조가 유지되는 경우에 유효합니다.
2. 픽스처 간 객체 공유
FastAPI 및 유닛테스트 환경에서는 픽스처들이 공유된 세션을 통해 객체를 사용할 가능성이 있습니다. 즉, db_session이라는 동일한 세션 객체를 공유하고 있다면, host_user가 데이터베이스의 refresh()를 통해 업데이트된 값들을 반영하기에 다른 픽스처에서도 동일한 최신 상태가 보장되는 것입니다.
3. 픽스처 실행 순서
픽스처 간의 의존성은 해당 픽스처의 선언 순서나 메인 테스트 함수에서의 호출 순서에 따라 정해집니다. client_with_auth 픽스처는 host_user_calendar 픽스처가 먼저 실행되어야 이후 인증된 클라이언트를 생성할 수 있도록 합니다.
참고 URL 및 추가 자료
- pytest Fixtures: pytest의 픽스처가 어떻게 작동하는지를 설명합니다.
- FastAPI Testing with SQLAlchemy: FastAPI에서 데이터베이스 테스트 세션 관리에 대한 설명.
위 내용을 통해 픽스처의 실행 순서와 데이터베이스 동기화 메커니즘에 대해 이해하셨기를 바랍니다. 의문점이 있으시면 추가 질문해 주시기 바랍니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.





매번 친절한 답변 감사합니다!