단위 테스트-데이터베이스 결합 앱


15

데이터베이스에 밀접하게 연결된 응용 프로그램에 통합되는 모델을 단위 테스트하는 가장 좋은 방법은 무엇입니까?

여기에있는 특정 시나리오는 쇼핑 카트입니다-장바구니에서 항목을 추가 및 제거하고 가격 책정 논리 ​​등을 테스트 할 수 있기를 원합니다. 데이터베이스 액세스는 피해야합니다.


1
"앱 코드를 다시 작성하십시오"라고 말하는 답변에 투표가
흥미 롭습니다

답변:


10

의존성 주입 은 이것을 처리하는 한 가지 방법입니다. 장바구니를 모방하도록 테스트 데이터베이스를 설정하거나 고객의 거래를 "확인하는"코드를 작성할 수도 있습니다. 그런 다음 런타임시 소프트웨어는 연결할 구성 요소를 선택합니다.

테스트하는 동안 아무것도 프로덕션 데이터베이스에 연결하지 마십시오!


1
DI와 적절한 응용 프로그램 디자인을 사용하면 주입 한 모의가 백엔드 데이터베이스에 대한 자세한 모의를 제공 할 경우 데이터베이스없이 테스트 할 수 있어야합니다.
Peter K.

4

단위 테스트에서는 테스트 대상의 경계를 정의해야합니다. 단위 테스트는 통합 테스트와 다릅니다. 가격 책정 로직이 장바구니 컨텐츠와 독립적 인 경우이를 별도로 테스트하십시오. 그렇지 않은 경우 모든 모듈이 단단히 결합 된 경우 프로덕션 환경을 최대한 모방 한 테스트 환경을 구축하고 작업하십시오. 지름길과 시뮬레이션이 장기적으로 도움이된다고 생각하지 않습니다.


2

모델은 (콘크리트) DB에 의존해서는 안됩니다. 모델에 전달 된 추상 DB ( "인터페이스"읽기) 만 알고 있으면 DB를 모의 객체로 바꿀 수 있습니다 .

에서 객체 지향 프로그래밍 , 모의 객체는 제어 방식으로 실제 객체의 동작을 모방 객체를 시뮬레이션하고 있습니다. 프로그래머는 일반적으로 자동차 디자이너가 충돌 테스트 더미사용 하여 차량 충격에서 사람의 역동적 인 행동 을 시뮬레이션 하는 것과 거의 같은 방식으로 다른 객체의 행동을 테스트하기 위해 모의 객체를 만듭니다 .


1

비슷한 문제가있었습니다. 테스트 DB가 값을 유지한다고 보장 할 수 없었습니다. 그래서 앞으로는 다른 가격을 얻습니다.

작은 sqlite -DB에 필요한 데이터를 추출 하고이 DB를 테스트에 사용했습니다. Test-DB는 이제 단위 테스트 설정의 일부입니다.


2
단위 테스트의 핵심은 코드를 개별적으로 테스트하는 것입니다. sqllite db를 사용하면 격리되지 않습니다. 또한 데이터베이스 간의 불일치 오류가 발생할 수 있습니다
톰 종복

0

"최상"은 주관적이지만 테스트 DB 연결을 사용할 수 있습니다.

고정구를 사용하여 일부 테스트 데이터 (예 : 구매할 제품)를로드 한 다음 테스트하려는 클래스 / 기능에 대한 테스트 케이스를 작성하십시오.


통합 테스트로서 데이터베이스에 작용하는 함수를 테스트하는 유닛 테스트를 설명하는 것은 @murph를 오해의 소지가 있습니다.
AD7six

1
자, 이제 깊이 혼란스러워합니다. 데이터베이스에 포함되어 있다면 자체 테스트가 아니기 때문에 단위 테스트가 아닙니다. 데이터베이스가있는 경우 상위 레벨에서 테스트를 실행하고 있으며 "결합"하는 것을 의존하는 테스트를 수행합니다. 어쨌든 이것은 문제를 해결하는 방법에 대한 명확한 설명이 아닙니다.
Murph

0

이 문제를 해결하기 위해 Symfony 1.4 (PHP) 용 플러그인을 만들었 습니다 . Django의 테스트 프레임 워크 (Python)가 작동 하는 방식을 모델로 합니다 : 프레임 워크 각 테스트가 시작되기 전에 별도의 테스트 데이터베이스를 작성하고 채우며 각 테스트가 완료되면 테스트 데이터베이스를 파괴합니다.

성능 (스키마가 변경되지 않는 경우 전체 구조를 다시 작성하는 대신 단순히 데이터를 지우지 않는 이유는 무엇입니까?)과 편의성 (때로는 데이터베이스를 검사하려는 경우) 측면 에서이 전략에 대해 몇 가지 우려가있었습니다. 테스트 실패, 무차별 적으로 파괴하지 마십시오!), 나는 약간 다른 접근법을 취했습니다.

첫 번째 테스트를 실행하기 전에 마지막 테스트 이후에 모델 변경이 발생한 경우 데이터베이스가 삭제되고 다시 작성됩니다. 이후의 각 테스트가 실행되기 전에 데이터베이스의 데이터가 지워지지 만 구조는 다시 작성되지 않습니다 (필요한 경우 수동 재 구축을 테스트에서 트리거 할 수는 있음).

각 테스트에 데이터 픽스처를 선택적으로로드함으로써 후속 테스트를 방해하지 않고 해당 테스트에 적합한 환경을 만들 수 있습니다. 픽스쳐 파일도 재사용 할 수 있으며,이 작업은 훨씬 덜 귀찮습니다 (여전히 글쓰기 테스트에서 가장 좋아하는 부분은 아니지만)!

두 테스트 프레임 워크에서 데이터베이스 어댑터는 테스트 실행으로 인해 기존 데이터가 손상되는 것을 방지하기 위해 "프로덕션"연결 대신 테스트 연결을 사용하도록 구성되어 있습니다.


0

계속해서 조명기를 사용하여 데이터를 사전로드하십시오. 데이터 조작을 테스트 할 때 단위 테스트 프레임 워크가 일반적으로 작동하는 방식입니다.

그러나 어떤 종류의 데이터베이스에 연결하지 않고 단위 테스트가 코드 외부의 아무것도 만지지 않는 지나치게 엄격한 정의로 가려면 객체 조롱을 살펴보십시오. 아이디어를 줄 수 있습니다.

예를 들어, 필요한 코드에서 SQL을 직접 삭제하는 대신 해당 SQL의 기능 만 수행하는 메서드를 호출 할 수 있습니다. Person.getPhoneNumber()예를 들어 대신을 사용하십시오 SELECT phone_number FROM person WHERE id = <foo>. 한눈에 더 깨끗하고 이해하기 쉬울뿐만 아니라 테스트하는 동안 데이터베이스를 건드리지 않고 getPhoneNumber()항상 반환 555-555-5555하거나 무언가 가 되도록 Person 객체를 조롱 할 수 있습니다 .


0

약간 긴 바람이 불면 junit을 사용하는 것이 상당히 쉽습니다.

"setup"은 임시 테이블 세트를 정의하고 채워야합니다.

그런 다음 모든 업데이트, 삽입, 삭제 기능에 대한 단위 테스트를 수행 할 수 있습니다.

각 테스트에 대해 update 메소드를 호출 한 후 SQL을 실행하여 예상 결과를 확인하십시오.

"teardown"단계에서는 모든 테이블을 삭제합니다.

이런 식으로 항상 동일한 초기 데이터에 대해 동일한 테스트를 실행합니다. 테스트 사이에 테이블을 유지하면 실패한 테스트로 인해 "오염 된"상태가되고 일관된 "삽입"테스트는 모든 테스트에서 새 키를 계속 발명해야하기 때문에 거의 불가능합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.