본문 바로가기

소프트웨어 이야기/테스트 자동화

(Pytest) mongoengine + factoryboy 조합으로 사용할 때, 데이터 리셋시키기

mongoengine + factory boy 조합 문제점

원래 factoryboy를 쓰면, 테스트 데이터가 롤백된다. 

그런데 mongoengine을 factory boy로 매핑해서 사용하면, 데이터가 롤백되지 않는다.

mongo에 테스트 데이터가 계속 쌓인다.


해결방법

테스트코드가 돌때마다 몽고 디비를 drop 시키면 된다. ( 이렇게하면 몹시 느리다 ㅋ )


A. 몽고 DB Drop fixture 만들기

### FILE: fixtures.py
import pytest
import mongoengine as me
@pytest.fixture(scope=’function’)
def mongo(request):
db = me.connect(‘testdb’, host=’mongodb://localhost’)
yield db
db.drop_database(‘testdb’)
db.close()

여기서 scope는 이 함수를 실행시킬 범위를 의미한다. 

fuction이면, 테스트 함수가 돌때마다 mongo db를 drop 시킨다. scope가 class이면, 테스트 클래스 하나가 돌 때, mongo db를 drop 시킨다.


그런데 fixture 파일에 이렇게 테스트 db명과 호스트명을 명시해두면, test.py에 있는 설정값이 중복되는 문제가 있다.

그러니 이 fixture에서 database 환경설정에 있는 값을 가져다가 쓰도록 수정해서 쓰는게 좋다. 


B. 테스트코드에 몽고 DB DROP Fixture 달기

B-1. 필요한 함수마다 fixture를 넣어주기 

from utils.fixtures import mongo
from ..models import Site
class SiteTests:
def test_object_creation(self, mongo): # use the fixture
site = Site(name=’test_site’)
site.save()
assert Site.objects.first().name == site.name
   def test_object_creation2(self, mongo):   # use the fixture
site = Site(name=’test_site2')
site.save()
assert Site.objects.first().name == site.name

B-2. 클래스에 명시해서, 모든 테스트 함수에서 몽고를 drop 시키기

from utils.fixtures import mongo
@pytest.mark.usefixtures('mongo')
class SiteTests:
   def test_object_creation(self):
site = Site(name='test_site')
site.save()
assert Site.objects.first().name == site.name



mongoengine에 factory boy 달아본 후기 

테스트 함수마다 mongo를 drop시키면 엄청 느리다. ㅋㅋ 

( 테스트코드 라이브러리에서 기본으로 지원해주는 데이터저장소가 아닌걸 사용하면, 매번 이런 문제가 생기는듯... 테스트 캐시 flush 할때도 이런 문제가 매번 있었다. )

몽고엔진에서는 mongomock을 권장한다고 한다. 

이렇게 해야 테스트코드가 도는 속도도 빠르고, 테스트 디비가 없어도 된다. 그래서 CI 환경에서 설정하기도 편하다. d@_@b


참고

Django + Mongo = Pytest FTW! A clean way to manage connecting and dropping of database between tests.


<끝>