데이터베이스에 밀접하게 연결된 응용 프로그램에 통합되는 모델을 단위 테스트하는 가장 좋은 방법은 무엇입니까?
여기에있는 특정 시나리오는 쇼핑 카트입니다-장바구니에서 항목을 추가 및 제거하고 가격 책정 논리 등을 테스트 할 수 있기를 원합니다. 데이터베이스 액세스는 피해야합니다.
데이터베이스에 밀접하게 연결된 응용 프로그램에 통합되는 모델을 단위 테스트하는 가장 좋은 방법은 무엇입니까?
여기에있는 특정 시나리오는 쇼핑 카트입니다-장바구니에서 항목을 추가 및 제거하고 가격 책정 논리 등을 테스트 할 수 있기를 원합니다. 데이터베이스 액세스는 피해야합니다.
답변:
"최상"은 주관적이지만 테스트 DB 연결을 사용할 수 있습니다.
고정구를 사용하여 일부 테스트 데이터 (예 : 구매할 제품)를로드 한 다음 테스트하려는 클래스 / 기능에 대한 테스트 케이스를 작성하십시오.
이 문제를 해결하기 위해 Symfony 1.4 (PHP) 용 플러그인을 만들었 습니다 . Django의 테스트 프레임 워크 (Python)가 작동 하는 방식을 모델로 합니다 : 프레임 워크 는 각 테스트가 시작되기 전에 별도의 테스트 데이터베이스를 작성하고 채우며 각 테스트가 완료되면 테스트 데이터베이스를 파괴합니다.
성능 (스키마가 변경되지 않는 경우 전체 구조를 다시 작성하는 대신 단순히 데이터를 지우지 않는 이유는 무엇입니까?)과 편의성 (때로는 데이터베이스를 검사하려는 경우) 측면 에서이 전략에 대해 몇 가지 우려가있었습니다. 테스트 실패, 무차별 적으로 파괴하지 마십시오!), 나는 약간 다른 접근법을 취했습니다.
첫 번째 테스트를 실행하기 전에 마지막 테스트 이후에 모델 변경이 발생한 경우 데이터베이스가 삭제되고 다시 작성됩니다. 이후의 각 테스트가 실행되기 전에 데이터베이스의 데이터가 지워지지 만 구조는 다시 작성되지 않습니다 (필요한 경우 수동 재 구축을 테스트에서 트리거 할 수는 있음).
각 테스트에 데이터 픽스처를 선택적으로로드함으로써 후속 테스트를 방해하지 않고 해당 테스트에 적합한 환경을 만들 수 있습니다. 픽스쳐 파일도 재사용 할 수 있으며,이 작업은 훨씬 덜 귀찮습니다 (여전히 글쓰기 테스트에서 가장 좋아하는 부분은 아니지만)!
두 테스트 프레임 워크에서 데이터베이스 어댑터는 테스트 실행으로 인해 기존 데이터가 손상되는 것을 방지하기 위해 "프로덕션"연결 대신 테스트 연결을 사용하도록 구성되어 있습니다.
계속해서 조명기를 사용하여 데이터를 사전로드하십시오. 데이터 조작을 테스트 할 때 단위 테스트 프레임 워크가 일반적으로 작동하는 방식입니다.
그러나 어떤 종류의 데이터베이스에 연결하지 않고 단위 테스트가 코드 외부의 아무것도 만지지 않는 지나치게 엄격한 정의로 가려면 객체 조롱을 살펴보십시오. 아이디어를 줄 수 있습니다.
예를 들어, 필요한 코드에서 SQL을 직접 삭제하는 대신 해당 SQL의 기능 만 수행하는 메서드를 호출 할 수 있습니다. Person.getPhoneNumber()
예를 들어 대신을 사용하십시오 SELECT phone_number FROM person WHERE id = <foo>
. 한눈에 더 깨끗하고 이해하기 쉬울뿐만 아니라 테스트하는 동안 데이터베이스를 건드리지 않고 getPhoneNumber()
항상 반환 555-555-5555
하거나 무언가 가 되도록 Person 객체를 조롱 할 수 있습니다 .
약간 긴 바람이 불면 junit을 사용하는 것이 상당히 쉽습니다.
"setup"은 임시 테이블 세트를 정의하고 채워야합니다.
그런 다음 모든 업데이트, 삽입, 삭제 기능에 대한 단위 테스트를 수행 할 수 있습니다.
각 테스트에 대해 update 메소드를 호출 한 후 SQL을 실행하여 예상 결과를 확인하십시오.
"teardown"단계에서는 모든 테이블을 삭제합니다.
이런 식으로 항상 동일한 초기 데이터에 대해 동일한 테스트를 실행합니다. 테스트 사이에 테이블을 유지하면 실패한 테스트로 인해 "오염 된"상태가되고 일관된 "삽입"테스트는 모든 테스트에서 새 키를 계속 발명해야하기 때문에 거의 불가능합니다.