[pytest] request.getfixturevalue()의 dirty optimization 제거
PR 링크: pytest-dev/pytest#14290 상태: Merged | 변경: +5 / -8
들어가며
pytest의 FixtureRequest는 테스트가 의존하는 fixture를 관리합니다. 내부적으로 _arg2fixturedefs는 컬렉션 시점에 정적으로 결정된 fixture 매핑을 보관하는데, request.getfixturevalue()로 동적 요청된 fixture도 이 딕셔너리에 추가하는 "dirty optimization"이 있었습니다. 이 최적화는 실질적 효과가 없고 코드의 의미를 혼란스럽게 만들어 제거되었습니다.
핵심 코드 분석
1. 동적 fixture 추가 코드 제거
Before (fixtures.py):
fixturedefs = self._fixturemanager.getfixturedefs(argname, self._pyfuncitem)
if fixturedefs is not None:
self._arg2fixturedefs[argname] = fixturedefs
After:
fixturedefs = self._fixturemanager.getfixturedefs(argname, self._pyfuncitem)
동적으로 조회한 fixture를 _arg2fixturedefs에 추가하던 2줄이 제거되었습니다. 이 코드는 동일 테스트에서 같은 fixture를 두 번 getfixturevalue()로 요청할 때 두 번째 호출에서 fixturemanager.getfixturedefs()를 건너뛰는 최적화였지만, 실제로 이런 패턴은 드물고 fixture_defs 캐시가 이미 존재합니다.
2. 타입을 dict에서 Mapping으로 변경
Before:
arg2fixturedefs: dict[str, Sequence[FixtureDef[Any]]]
# ...
arg2fixturedefs=pyfuncitem._fixtureinfo.name2fixturedefs.copy()
After:
arg2fixturedefs: Mapping[str, Sequence[FixtureDef[Any]]]
# ...
arg2fixturedefs=pyfuncitem._fixtureinfo.name2fixturedefs
Mapping 타입으로 변경하여 읽기 전용 의미를 강제하고, .copy()도 불필요해져 제거되었습니다. 주석도 "동적 요청이 추가됨"에서 "동적 요청은 포함되지 않음"으로 수정되었습니다.
왜 이게 좋은가
_arg2fixturedefs의 의미가 명확해집니다: "컬렉션 시점에 정적으로 결정된 fixture 매핑"Mapping타입으로 불변성이 타입 레벨에서 보장됩니다..copy()제거로 매 테스트 초기화 시 딕셔너리 복사 비용이 절약됩니다.
정리
- 최적화의 실효성을 정기적으로 검증하라: 코드가 복잡해진 후에는 초기 최적화가 오히려 혼란만 줄 수 있습니다.
- 읽기 전용 데이터는 Mapping 타입으로 보호하라:
dict대신Mapping을 사용하면 실수로 변경하는 것을 타입 체커가 방지합니다.
참고 자료
- pytest-dev/pytest#14290 — PR 전체 diff
- pytest fixture 문서 — fixture 시스템
⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.
관련 포스트
PR Analysis 의 다른글
- 이전글 [axolotl] transformers 5.3.0 / TRL 0.29.0 업그레이드: API 변경 대응과 deprecated 설정 처리
- 현재글 : [pytest] request.getfixturevalue()의 dirty optimization 제거
- 다음글 [ray] Ray Serve P99 레이턴시 회귀 수정 — 큐 길이 캐시 미감소 버그
댓글