(데이터베이스) 통합 테스트가 좋지 않습니까?


120

어떤 사람들 은 통합 테스트가 모든 종류의 나쁘고 잘못되었다고 주장합니다. 모든 것이 반드시 단위 테스트를 거쳐야합니다. 즉, 의존성을 조롱해야합니다. 여러 가지 이유로 항상 좋아하지 않는 옵션.

어떤 경우에는 단위 테스트가 단순히 아무것도 입증하지 못한다는 것을 알았습니다.

다음과 같은 (사소하고 순진한) 리포지토리 구현 (PHP)을 예로 들어 보겠습니다.

class ProductRepository
{
    private $db;

    public function __construct(ConnectionInterface $db) {
        $this->db = $db;
    }

    public function findByKeyword($keyword) {
        // this might have a query builder, keyword processing, etc. - this is
        // a totally naive example just to illustrate the DB dependency, mkay?

        return $this->db->fetch("SELECT * FROM products p"
            . " WHERE p.name LIKE :keyword", ['keyword' => $keyword]);
    }
}

이 저장소가 실제로 다양한 키워드와 일치하는 제품을 찾을 수 있음을 테스트에서 증명하고 싶다고 가정 해 봅시다.

실제 연결 개체와의 통합 테스트가 부족하여 이것이 실제로 실제 쿼리를 생성하고 있다는 것을 어떻게 알 수 있습니까?

단위 테스트에서 연결 개체를 조롱 해야하는 경우 "예상 쿼리를 생성합니다"와 같은 것만 증명할 수 있지만 실제로 작동 한다는 의미는 아닙니다 . 즉, 아마도 쿼리를 생성하고 있습니다 나는 예상했지만 어쩌면 그 쿼리는 내가 생각하는 것을하지 않을 것입니다.

다시 말해, 생성 된 쿼리에 대한 어설 션을 만드는 테스트 인 것 같습니다. findByKeyword()메소드가 어떻게 구현 되었는지 테스트하기 때문에 실제로는 가치 가 없지만 실제로 작동 한다는 것을 증명하지는 않습니다 .

이 문제는 리포지토리 또는 데이터베이스 통합에만 국한되지 않습니다. 모의 (test-double) 사용에 대한 주장은 상황에 관계없이 구현 방식 만 입증하는 많은 경우에 적용되는 것으로 보입니다. 실제로 작동합니다.

이런 상황을 어떻게 처리합니까?

이런 경우 통합 테스트가 실제로 "나쁜"가요?

나는 한 가지를 테스트하는 것이 낫다는 점을 알고 있으며 통합 테스트가 왜 무수한 코드 경로를 가져 와서 모두 테스트 할 수 없는지 이해하지만 목적이 유일한 서비스 (예 : 저장소)의 경우 다른 구성 요소와 상호 작용하기 위해 통합 테스트없이 어떻게 실제로 테스트 할 수 있습니까?


5
agitar.com/downloads/TheWayOfTestivus.pdf를 읽으 십시오 . 특히 6 페이지 "테스트는 장치보다 중요합니다".
Doc Brown

2
@ user61852 설명에 "순진"이라고 표시되어 있습니다. 예?
mindplay.dk

4
동료가 자신의 조롱 된 데이터베이스가 실제처럼 동작하는지 어떻게 확신 할 수 있습니까?
Thorbjørn Ravn Andersen은

12
현실적이 되려고 노력하고 있습니다. 동료가 규칙을 준수하려고합니다. 항상 가치창출하는 테스트를 작성하십시오 . 유지 보수가 불가능한 테스트 작성에 시간을 낭비하지 말고 다음 중 하나를 수행하지 않는 테스트를 작성하지 마십시오. 코드의 정확성을 높이거나 유지 보수가 더 쉬운 코드를 작성하도록 강요하십시오.
jpmc26

3
@ mindplay.dk :이 단락의 핵심 문장은 "그러나 어떤 교리에 얽매 이지 말고 작성해야 할 테스트를 작성하십시오." 동료가 교리에 갇혀있는 것 같습니다. 데이터베이스에서 쿼리를 이해하는지 테스트하려면 실제 데이터베이스 에 대해 쿼리를 실행해야합니다. 모의는 말할 수 없습니다. 이.
독 브라운

답변:


129

동료는 단위 테스트 할 수있는 모든 항목을 단위 테스트해야하며, 특히 복잡한 외부 서비스에 대해 간단한 래퍼를 작성할 때 단위 테스트를 수행하면 더 이상 멀지 않을 것입니다.

테스트에 대한 일반적인 사고 방식은 테스트 피라미드 입니다. 이 개념은 애자일과 자주 연결되는 개념으로, Martin Fowler ( Agile성공한 Mike Cohn의 속성 ), Alistair ScottGoogle Testing 블로그를 포함하여 많은 사람들이이 개념에 대해 글을 썼습니다 .

        /\                           --------------
       /  \        UI / End-to-End    \          /
      /----\                           \--------/
     /      \     Integration/System    \      /
    /--------\                           \----/
   /          \          Unit             \  /
  --------------                           \/
  Pyramid (good)                   Ice cream cone (bad)

개념은 빠르게 실행되는 탄력적 인 단위 테스트가 테스트 프로세스의 기초라는 것입니다. 시스템 / 통합 테스트보다 집중된 단위 테스트가 있고 엔드-투-엔드 테스트보다 더 많은 시스템 / 통합 테스트가 있어야합니다. 정상에 가까워 질수록 테스트는 실행하는 데 더 많은 시간과 리소스가 소요되고 취성과 취약성이 더 커지는 경향이 있으며 어떤 시스템이나 파일이 손상되었는지 식별하는 데 덜 구체적입니다 . 당연히 "무거운"것을 피하는 것이 좋습니다.

지금까지 통합 테스트는 나쁘지 않지만 의존하는 테스트는 개별 구성 요소를 테스트하기 쉽도록 설계하지 않았 음을 나타낼 수 있습니다. 여기서 목표 는 최소한의 다른 파괴 가능한 시스템을 포함하면서 장치가 사양에 따라 수행되고 있는지 테스트하는 것입니다 . 메모리 내 데이터베이스를 시도 할 수 있습니다 (모의와 함께 단위 테스트 친화적 테스트로 두 번 계산) 예를 들어 엣지 케이스 테스트의 경우 실제 데이터베이스 엔진과의 통합 테스트를 작성하여 시스템 조립시 주요 사례가 작동하는지 확인하십시오.


부수적으로, 당신은 당신이 쓴 모의 가 그것이 작동하는지 여부가 아니라 어떤 것이 어떻게 구현되는지 간단히 테스트한다고 언급 했습니다 . 그것은 반 패턴의 일부입니다. 구현의 완벽한 거울 인 테스트는 실제로 아무것도 테스트하지 않습니다. 대신, 모든 클래스 또는 메소드 가 필요한 추상화 또는 사실 수준에서 자체 스펙에 따라 작동하는지 테스트하십시오 .


13
"구현을 완벽하게 반영한 테스트는 실제로 어떤 것도 테스트하지 않습니다." 너무 흔합니다. 나는 이것을 Doppelganger Antipattern 이라고 부릅니다 .
dodgethesteamroller

6
상황 중심의 테스트 운동 인 대립 소프트웨어 QA 는 부분적으로 테스트 피라미드와 같은 유용한 일반 규칙이 존재한다는 논란에 전념하고 있습니다. 특히, 운동 의 주요 내용 은 통합 테스트가 다른 종류의 테스트보다 훨씬 가치가있는 많은 예를 제공합니다 ( 시스템으로서 상황에 따라 시스템 을 테스트하기 때문에 ) ....
dodgethesteamroller

7
결과적으로 Fowler 등은 강력하고 유지 보수가 쉬운 방식으로 작성하기가 너무 어렵 기 때문에 통합 테스트 및 사용자 승인 테스트에 더 적은 노력을 기울여야한다고 주장하면서 실제로 이유에 대한 사후 실례를 제공하고 있습니다. 그들은 더 높은 수준에서 잘 테스트하는 방법을 찾지 못했습니다.
dodgethesteamroller

1
@dodgethesteamroller "모반 학교"에 대한 심층 토론은 아마도 자신의 대답에 가장 적합 할 것입니다. 개인적으로 Google 테스팅 블로그는 문맥 내 시스템 테스트 와 함께 빠르고 엄격한 범위의 자동 테스트의 장점을 잘 설명하고 있습니다. 확실치 않은 경우, 여기에 테스트 피라미드를 유용한 모델 또는 출발점으로 표시합니다. 엔지니어로서 생각을 멈출 이유가 아닙니다.
Jeff Bowman

1
통합 테스트에 대한 단위 테스트의 계층 구조 및 비율에 대한 권장 프레젠테이션 : vimeo.com/80533536 매우 잘 설명되어 있습니다.
szalski

88

제 동료 중 한 명이 통합 테스트가 모든 종류의 나쁘고 잘못되었다고 주장합니다.

그것은 항생제가 나쁘다는 것을 말하는 것과 조금 다릅니다. 모든 것이 비타민으로 치료되어야합니다.

단위 테스트 모든 것을 포착 할 수 없으며 제어 된 환경에서 구성 요소가 어떻게 작동하는지 테스트합니다 . 통합 테스트는 모든 것이 함께 작동하는지 확인 하여 수행하기는 어렵지만 결국에는 더 의미가 있습니다.

훌륭하고 포괄적 인 테스트 프로세스는 가지 유형의 테스트 (단위 테스트)를 사용하여 비즈니스 규칙 및 기타 독립적으로 테스트 할 수있는 항목을 검증하고 통합 테스트를 통해 모든 것이 함께 작동하는지 확인합니다.

실제 연결 개체와의 통합 테스트가 부족하여 이것이 실제로 실제 쿼리를 생성하고 있다는 것을 어떻게 알 수 있습니까?

당신은 할 수 단위 테스트 데이터베이스 수준에서 . 다양한 매개 변수를 사용하여 쿼리를 실행하고 예상 한 결과가 나오는지 확인하십시오. 변경 사항을 "true"코드로 다시 복사 / 붙여 넣기하는 것을 의미합니다. 그러나 않습니다 당신이 다른 종속성 쿼리 독립을 테스트 할 수 있습니다.


데이터베이스에 특정 데이터가 포함되어 있는지 테스트하고 있지 않습니까?
Tulains Córdova

필터-복잡한 조인 등이 작동하는지 테스트 할 수도 있습니다. 예제 쿼리는 "단위 테스트"에 가장 적합한 후보는 아니지만 복잡한 조인 및 / 또는 집계가있는 쿼리 일 수 있습니다.
D Stanley

예-지적했듯이 내가 사용한 예는 사소한 것입니다. 실제 리포지토리는 쿼리 빌더 등을 사용하여 모든 방식의 복잡한 검색 및 정렬 옵션을 가질 수 있습니다.
mindplay.dk

2
좋은 대답이지만 단위 테스트가 빠르도록 DB가 메모리에 있어야한다고 덧붙입니다.
BЈовић

3
@ BЈовић : 불행히도, 그것은 가능하지 않을 수도 있습니다. 불행히도 거기에는 호환되는 두 개의 DB가 없으며 모두 메모리에서 작동하지 않기 때문입니다. 상용 DB에 대한 라이센싱 문제도 있습니다 (어떤 머신에서도이를 실행할 수있는 라이센스가 없을 수도 있음).
Matthieu M.

17

단위 테스트로 모든 결함이 발견되지는 않습니다. 그러나 다른 종류의 테스트에 비해 설치 및 실행이 저렴합니다. 단위 테스트는 적당한 값과 저렴한 비용의 조합으로 정당화됩니다.

다음은 다양한 종류의 테스트에 대한 결함 감지 속도를 보여주는 표입니다.

여기에 이미지 설명을 입력하십시오

출처 : McConnell의 Code Complete 2의 p.470


5
이 데이터는 1986 년 에 수집되었습니다 . 그것은 30 년 전 이었습니다. 1986 년의 단위 테스트는 오늘날의 것이 아닙니다. 나는이 데이터에 회의적이다. 말할 것도없이, 단위 테스트는 커밋되기 전에 버그 감지 하므로보고 될 것입니다.
RubberDuck

3
@RubberDuck이 차트는 2006 년 책에서 발췌 한 것이며 1986 년, 1996 년, 2002 년 데이터를 기준으로합니다 (심지어 보면). 소스에서 데이터 수집 프로토콜을 조사하지 않았으며 결함 추적을 시작한 시점과보고 방법을 말할 수 없습니다. 이 차트가 다소 오래된 것일 수 있습니까? 할 수 있습니다. 지난 12 월 나는 세미나에 있었고 강사는 통합 테스트가 단위 테스트보다 더 많은 버그를 발견했다고 언급했습니다 (2, iirc). 이 차트는 그것들이 거의 같다고 말합니다.
Nick Alexeev 2016 년

13

아니요, 나쁘지 않습니다. 바라건대, 단위 및 통합 테스트가 있어야합니다. 그것들은 개발주기의 다른 단계에서 사용되고 실행됩니다.

단위 테스트

단위 테스트는 코드가 컴파일 된 후 빌드 서버와 로컬에서 실행되어야합니다. 단위 테스트가 실패하면 테스트가 수정 될 때까지 빌드에 실패하거나 코드 업데이트를 커밋하지 않아야합니다. 단위 테스트를 분리해야하는 이유는 빌드 서버가 모든 종속성없이 모든 테스트를 실행할 수 있기를 원하기 때문입니다. 그런 다음 필요한 모든 복잡한 종속성없이 빌드를 실행할 수 있으며 매우 빠른 테스트가 많이 있습니다.

따라서 데이터베이스의 경우 다음과 같은 것이 있어야합니다.

IRespository

List<Product> GetProducts<String Size, String Color);

이제 IRepository의 실제 구현은 제품을 얻기 위해 데이터베이스로 이동하지만 단위 테스트의 경우 가짜 데이터베이스로 IRepository를 조롱하여 모든 종류의 제품 목록을 시뮬레이션 할 수 있으므로 actaul 데이터베이스없이 필요한 모든 테스트를 실행할 수 있습니다 모의 인스턴스에서 리턴되고 모의 데이터로 비즈니스 로직을 테스트합니다.

통합 테스트

통합 테스트는 일반적으로 경계 교차 테스트입니다. 이러한 테스트는 배포 서버 (실제 환경), 샌드 박스 또는 로컬 (샌드 박스를 가리킴)에서 실행하려고합니다. 빌드 서버에서 실행되지 않습니다. 소프트웨어가 환경에 배포 된 후에는 일반적으로 배포 후 활동으로 실행됩니다. 명령 줄 유틸리티를 통해 자동화 할 수 있습니다. 예를 들어, 호출하려는 모든 통합 테스트를 분류하면 명령 줄에서 nUnit을 실행할 수 있습니다. 이들은 실제로 실제 데이터베이스 호출로 실제 저장소를 호출합니다. 이러한 유형의 테스트는 다음에 도움이됩니다.

  • 환경 건강 안정성 준비
  • 실제 테스트

이러한 테스트는 때때로 설정 및 / 또는 해제해야하기 때문에 실행하기가 더 어렵습니다. 제품 추가를 고려하십시오. 제품을 추가하고 쿼리하여 제품이 추가되었는지 확인한 다음 완료 한 후 제거 할 수 있습니다. 우리는 100 ~ 1000 개의 "통합"제품을 추가하고 싶지 않으므로 추가 설정이 필요합니다.

통합 테스트는 환경을 검증하고 실제로 작동하는지 확인하는 데 매우 유용 할 수 있습니다.

둘 다 가지고 있어야합니다.

  • 모든 빌드에 대해 단위 테스트를 실행하십시오.
  • 모든 배포에 대해 통합 테스트를 실행하십시오.

커밋하고 푸시하지 않고 모든 빌드에 대해 통합 테스트를 실행하는 것이 좋습니다. 소요 시간에 따라 다르지만 여러 가지 이유로 빨리 유지하는 것이 좋습니다.
artbristol

@ArtBristol-일반적으로 빌드 서버에는 전체 환경 종속성이 구성되어 있지 않으므로 통합 테스트를 실행할 수 없습니다. 그러나 거기에서 통합 테스트를 실행할 수 있다면 계속하십시오. 빌드 후에는 배포를 확인하기 위해 통합 테스트에 사용하는 배포 샌드 박스가 설정되었습니다. 그러나 각 상황은 다릅니다.
Jon Raynor

11

데이터베이스 통합 테스트는 나쁘지 않습니다. 더 필요합니다.

아마도 응용 프로그램을 여러 계층으로 나누었을 때 좋은 방법입니다. 인접 레이어를 조롱하여 각 레이어를 개별적으로 테스트 할 수 있으며, 이것도 좋습니다. 그러나 생성하는 추상화 계층의 수에 관계없이 특정 시점에서 더티 작업을 수행하는 계층이 있어야합니다. 실제로 데이터베이스와 대화해야합니다. 테스트 하지 않으면 전혀 테스트 하지 않습니다 . 당신은 레이어 테스트 경우 N을 계층 조롱에 의해 N-1 당신이 가정을 평가하고 그 레이어 , n은 작동 조건에 그 계층 N-1 작품. 이것이 작동하려면 레이어 0이 작동한다는 것을 어떻게 든 증명해야합니다.

이론적으로 생성 된 SQL을 구문 분석하고 해석하여 테스트 데이터베이스를 단위화할 수 있지만 테스트 데이터베이스를 즉시 작성하여 대화하는 것이 훨씬 쉽고 안정적입니다.

결론

생성 된 SQL에 구문 오류가있을 때 Abstract Repository , Ethereal Object-Relational-Mapper , Generic Active Record , Theoretic Persistence 레이어 를 단위 테스트하여 얻은 신뢰도는 무엇입니까 ?


나는 당신과 비슷한 답변을 추가하려고 생각했지만 더 잘 말했습니다! 내 경험상 데이터를 가져오고 저장하는 레이어에서 테스트를 한 결과 많은 슬픔을 피할 수있었습니다.
Daniel Hollinrake

데이터베이스 통합 테스트는 좋지 않습니다. ci / cd 라인에 사용 가능한 데이터베이스가 있습니까? 그것은 꽤 복잡해 보입니다. 데이터베이스를 모의하고이를 사용하기 위해 추상화 계층을 구축하는 것이 훨씬 쉽습니다. 그것은 훨씬 더 우아한 해결책 일뿐만 아니라, 가능한 한 빠르다. 단위 테스트는 빨라야합니다. 데이터베이스를 테스트하면 단위 테스트 속도가 허용 할 수없는 수준으로 상당히 느려집니다. 단위 테스트는 수천 개가 있어도 10 분 이상 걸리지 않습니다.
David

@David ci / cd 라인에 데이터베이스가 있습니까? 물론, 그것은 표준적인 기능 입니다. BTW, 단위 테스트 대신 통합 테스트 옹호하지 않습니다 . 단위 테스트 와 함께 통합 테스트 옹호 합니다. 빠른 단위 테스트가 필수적이지만 데이터베이스는 모의 상호 작용을 통한 단위 테스트에 의존하기에는 너무 복잡합니다.
el.pescado

@ el.pescado 동의하지 않습니다. 데이터베이스 통신이 추상화 계층 뒤에있는 경우 실제로 조롱하기가 쉽습니다. 반환 할 객체를 결정할 수 있습니다. 또한 무언가가 표준이라는 사실이 좋은 것은 아닙니다.
David

@David 데이터베이스 접근 방법에 달려 있다고 생각합니다. 그것은이다 구현 세부 사항 또는 시스템의 중요한 부분은 ? (나는 후자를 향해 몸을 기울인다) . 데이터베이스를 멍청한 데이터 저장소로 취급한다면 통합 테스트없이 수행 할 수 있습니다. 그러나 데이터베이스에 제약 조건, 트리거, 외래 키, 트랜잭션 또는 데이터 계층에 일반 ORM 방법 대신 사용자 지정 SQL을 사용하는 논리가 있으면 단위 테스트만으로는 충분하지 않다고 생각합니다.
el.pescado

6

둘 다 필요합니다.

귀하의 예에서 특정 조건에서 데이터베이스를 테스트하는 경우 findByKeyword메소드가 실행될 때 데이터를 다시 가져 오면 이는 훌륭한 통합 테스트라고 생각합니다.

해당 findByKeyword방법을 사용하는 다른 코드 에서는 테스트에 제공되는 내용을 제어하려고하므로 테스트에 대한 null 또는 올바른 단어 또는 무엇이든 데이터베이스 종속성을 조롱하여 테스트가 무엇인지 정확히 알 수 있습니다 수신 (그리고 데이터베이스에 연결하고 데이터가 올바른지 확인하는 오버 헤드가 손실 됨)


6

귀하가 참조 하는 블로그 기사 의 작성자 는 주로 통합 된 테스트에서 발생할 수있는 잠재적 복잡성과 관련이 있습니다 (매우 의견이 많고 범주 방식으로 작성되었지만). 그러나 통합 테스트가 반드시 나쁘지는 않으며 일부는 실제로 순수한 단위 테스트보다 더 유용합니다. 실제로 응용 프로그램의 컨텍스트와 테스트하려는 대상에 따라 다릅니다.

오늘날 많은 응용 프로그램은 데이터베이스 서버가 다운되면 전혀 작동하지 않습니다. 적어도 테스트하려는 기능의 맥락에서 생각하십시오.

한편으로, 당신이 테스트하려는 것이 데이터베이스에 의존하지 않거나 전혀 의존하지 않을 수 있다면, 테스트를 사용하려고 시도하지 않는 방식으로 테스트를 작성하십시오. 데이터베이스 (필요에 따라 모의 데이터를 제공하십시오). 예를 들어, 웹 페이지를 제공 할 때 일부 인증 로직을 테스트하려는 경우 인증을 위해 DB에 의존하지 않는다고 가정 할 때 웹 페이지를 모두 DB에서 분리하는 것이 좋습니다. 합리적으로 쉽게 조롱 할 수 있습니다).

반면, 데이터베이스에 직접 의존하는 기능이고 데이터베이스를 사용할 수없는 경우 실제 환경에서 전혀 작동하지 않는 기능인 경우 DB 클라이언트 코드에서 DB의 기능을 조롱하는 경우 DB)가 반드시 의미가있는 것은 아닙니다.

예를 들어, 응용 프로그램이 데이터베이스 (및 특정 데이터베이스 시스템)에 의존한다는 것을 알고 있다면 데이터베이스 동작을 조롱하는 것은 종종 시간 낭비입니다. 데이터베이스 엔진 (특히 RDBMS)은 복잡한 시스템입니다. 실제로는 몇 줄의 SQL로 많은 작업을 수행 할 수 있으며, 이는 시뮬레이션하기 어렵습니다 (사실 SQL 쿼리의 길이가 몇 줄이면 더 많은 Java / PHP / C # / Python 줄이 필요할 수 있습니다) 내부적으로 동일한 결과를 생성하는 코드) : DB에서 이미 구현 한 논리를 복제하는 것은 의미가 없으며 테스트 코드를 확인하면 자체적으로 문제가됩니다.

필자가 이것을 단위 테스트통합 테스트 의 문제로 취급 하지는 않지만 테스트 대상 의 범위를 살펴보십시오. 단위 및 통합 테스트의 전반적인 문제는 여전히 남아 있습니다. 상당히 현실적인 테스트 데이터 및 테스트 사례가 필요하지만 테스트를 신속하게 실행할 수있을 정도로 작습니다.

데이터베이스를 재설정하고 테스트 데이터로 다시 채우는 시간은 고려해야 할 측면입니다. 일반적으로 모의 코드를 작성하는 데 걸리는 시간 (결국 유지 관리해야 할 시간)과 비교하여이를 평가합니다.

고려해야 할 또 다른 사항은 응용 프로그램과 데이터베이스의 종속성 정도입니다.

  • 애플리케이션이 단순히 CRUD 모델을 따르는 경우, 구성 설정을 통해 RDBMS간에 교환 할 수있는 추상화 계층이있는 경우 모의 시스템으로 매우 쉽게 작업 할 수 있습니다 (흐려짐) 인 메모리 RDBMS를 사용한 단위와 통합 테스트 간의 경계).
  • 응용 프로그램이 SQL Server, MySQL, PostgreSQL 중 하나에 특정한 복잡한 논리를 사용하는 경우 일반적으로 해당 특정 시스템을 사용하는 테스트를하는 것이 더 합리적입니다.

"오늘날 많은 응용 프로그램이 데이터베이스 서버가 다운되면 전혀 작동하지 않을 것입니다."-정말 중요한 포인트입니다!
el.pescado

SQL을 조롱하기 위해 다른 언어를 사용하는 것과 같이 복잡한 모의 한계에 대한 좋은 설명. 테스트 코드 자체가 테스트가 필요한 것처럼 보일 정도로 복잡해지면 QA 냄새가납니다.
dodgethesteamroller 18시 49 분

1

그러한 단위 테스트는 불완전한 것으로 생각할 수 있습니다. 불완전 성이 조롱되는 데이터베이스 인터페이스에 있습니다. 이러한 순진한 모의 기대 또는 주장은 불완전합니다.

테스트를 완료하려면 테스트 대상이 생성 한 SQL 문이 예상되는 작업을 수행 하도록 보장 하는 SQL 규칙 엔진을 작성하거나 통합 할 수있는 충분한 시간과 자원을 절약 해야합니다.

그러나 조롱에 대한 종종 잊혀지고 다소 비싼 대안 / 동반자는 "가상화" 입니다.

단일 함수를 테스트하기 위해 메모리에 있지만 임시 인 "실제"DB 인스턴스를 가동시킬 수 있습니까? 예 ? 거기에는 실제 데이터를 저장하고 검색하는 테스트 인 더 나은 테스트가 있습니다.

이제 단위 테스트를 통합 테스트로 바꿨습니다. 단위 테스트와 통합 테스트를 분류하기 위해 선을 그릴 위치에 대한 다양한 뷰가 있습니다. IMHO, "단위"는 임의의 정의이며 귀하의 요구에 맞아야합니다.


1
이것은 단지 몇 시간 전에 게시 된 이전의 답변 에서 언급 되고 설명 된 부분을 반복하는 것으로 보인다
gnat

0

Unit Tests하고 Integration Tests있습니다 orthgonal 서로. 그들은 당신이 만들고있는 어플리케이션에 대해 다른 관점을 제공합니다. 보통 둘 다 원합니다 . 그러나 어떤 종류의 테스트를 원할 때 시점이 다릅니다.

가장 자주 당신이 원하는 Unit Tests. 단위 테스트는 테스트중인 코드의 작은 부분에 중점을 둡니다. 정확하게는 a라고하는 unit것이 독자에게 있습니다. 그러나 테 목적은 간단하다 : 점점 빠른 피드백 코드가 파산을 . 즉, 실제 DB에 대한 호출은 nono 입니다.

반면 에 데이터베이스가없는 열악한 조건 에서만 유닛 테스트 할 수있는 것이 있습니다 . 아마도 코드에 경쟁 조건 이있을 수 있으며 DB를 호출 unique constraint하면 실제로 시스템을 사용하는 경우에만 발생할 수 있는 위반 이 발생합니다. 그러나 이러한 종류의 테스트는 비용많이 들며 자주 실행할 수 없습니다 unit tests.


0

.Net 세계에서는 UI를 뺀 코딩 / 디버깅 / 테스트 방법으로 테스트 프로젝트를 만들고 테스트를 만드는 습관이 있습니다. 이것은 내가 개발하기에 효율적인 방법입니다. 모든 빌드에 대해 모든 테스트를 실행하는 데 관심이 없었지만 (개발 작업 흐름이 느려지기 때문에) 더 큰 팀에 유용하다는 것을 이해합니다. 그럼에도 불구하고 코드를 커밋하기 전에 모든 테스트를 실행하고 통과해야한다는 규칙을 만들 수 있습니다 (데이터베이스가 실제로 적중되어 테스트 실행 시간이 더 오래 걸리는 경우).

데이터 액세스 계층 (DAO)을 모방하고 실제로 데이터베이스를 공격하지 않으면 내가 좋아하는 방식으로 코딩하고 익숙해 졌을뿐만 아니라 실제 코드 기반의 상당 부분을 놓치게됩니다. 데이터 액세스 계층과 데이터베이스를 실제로 테스트하지 않고 단순한 척을 한 다음 물건을 조롱하는 데 많은 시간을 소비한다면 실제로이 코드를 테스트하는 데이 접근법의 유용성을 파악하지 못합니다. 하나의 테스트로 큰 조각 대신 작은 조각을 테스트하고 있습니다. 내 접근 방식이 통합 테스트의 선을 따라 더 많을 수도 있지만 실제로 모의 테스트를 한 번만 작성하면 모의 단위 테스트가 중복되는 시간 낭비처럼 보입니다. 또한 개발하고 디버깅하는 좋은 방법입니다.

사실, 한동안 나는 TDD와 BDD (Behavior Driven Design)를 알고 그것을 사용하는 방법을 생각했지만 단위 테스트를 소급해서 추가하기는 어렵다. 아마도 내가 틀렸지 만 포함 된 데이터베이스로 끝까지 더 많은 코드를 다루는 테스트를 작성하면 더 많은 코드를 다루고 테스트를 작성하는보다 효율적인 방법 인 훨씬 더 완벽하고 우선 순위가 높은 테스트처럼 보입니다.

실제로, DSL (Domain Specific Language)으로 엔드 투 엔드 테스트를 시도하는 BDD (Behavior Driven Design)와 같은 방법이 필요하다고 생각합니다. .Net 세계에는 SpecFlow가 있지만 Cucumber에서 오픈 소스로 시작했습니다.

https://cucumber.io/

필자는 데이터 액세스 계층을 조롱하고 데이터베이스에 영향을 미치지 않는 필자가 작성한 테스트의 진정한 유용성에 감명받지 못했습니다. 리턴 된 오브젝트가 데이터베이스에 도달하지 않았으며 데이터로 채워지지 않았습니다. 부 자연스러운 방법으로 조롱해야 할 것은 완전히 비어있는 물건이었습니다. 시간 낭비라고 생각합니다.

스택 오버플로에 따르면 실제 객체가 단위 테스트에 통합하기에 비현실적 일 때 조롱이 사용됩니다.

https://stackoverflow.com/questions/2665812/what-is-mocking

"모의는 주로 단위 테스트에 사용됩니다. 테스트중인 오브젝트는 다른 (복잡한) 오브젝트에 종속 될 수 있습니다. 테스트하려는 오브젝트의 동작을 분리하려면 실제 오브젝트의 동작을 시뮬레이션하는 모의로 다른 오브젝트를 대체하십시오. 이것은 실제 물체가 단위 테스트에 통합하기에 비실용적 일 때 유용합니다. "

내 주장은 개발자로 무엇이든 체크인하기 전에 엔드 투 엔드 (웹 UI에서 비즈니스 계층으로, 데이터 액세스 계층에서 데이터베이스로, 왕복 여행)를 코딩하는 경우이 왕복 흐름을 테스트 할 것입니다. UI를 잘라 내고 테스트에서 시작 하여이 흐름을 디버그하고 테스트하면 UI가 부족한 모든 것을 테스트하고 UI가 기대하는 것을 정확하게 반환합니다. 내가 남은 것은 원하는 UI를 보내는 것입니다.

내 자연 개발 워크 플로의 일부인 더 완벽한 테스트가 있습니다. 나에게는 이것이 실제 사용자 사양 테스트를 가능한 한 많이하는 것을 포함하는 가장 우선 순위가 높은 테스트 여야합니다. 더 세부적인 다른 테스트를 작성하지 않으면 적어도 원하는 기능이 작동 함을 입증하는이 하나 이상의 완전한 테스트가 있습니다.

Stack Exchange의 공동 설립자는 100 % 단위 테스트 적용 범위의 이점에 대해 확신하지 않습니다. 나는 또한 아니다. 나는 하루 종일 많은 데이터베이스 모의를 유지하는 것보다 데이터베이스에 충돌하는보다 완전한 "통합 테스트"를 취할 것입니다.

https://www.joelonsoftware.com/2009/01/31/from-podcast-38/


단위 테스트와 통합 테스트의 차이점을 이해하지 못하는 것이 분명합니다.
BЈовић

나는 그것이 프로젝트에 달려 있다고 생각합니다. 테스터의 부족으로 인해 테스트 및 회귀 테스트에 대한 개발자의 전반적인 책임이 더 적은 소규모 프로젝트의 경우, 문서를 코드와 동기화하여 유지해야합니다. 테스트를 작성하는 데 시간을 할애한다면 내 돈에 가장 큰 돈을 줘. 가능한 한 돌로 많은 새를 죽이고 싶습니다. 대부분의 논리와 버그가 보고서를 생성하는 데이터베이스 저장 프로시 저나 프런트 엔드 JavaScript에서 온 경우 중간 계층에서 전체 단위 테스트 적용 범위를 갖는 것이 큰 도움이되지 않습니다.
user3198764

-1

외부 종속성은 제어 할 수 없기 때문에 조롱해야합니다 (통합 테스트 단계에서는 통과하지만 프로덕션에서는 실패 할 수 있음). 드라이브가 실패하거나, 여러 가지 이유로 데이터베이스 연결이 실패하거나, 네트워크 문제가 발생할 수 있습니다. 통합 테스트를 수행해도 런타임시 발생할 수있는 모든 문제이기 때문에 추가 신뢰를 얻지 못합니다.

실제 단위 테스트를 사용하면 샌드 박스의 한계 내에서 테스트하고 있으며 명확해야합니다. 개발자가 QA / PROD에서 실패한 SQL 쿼리를 작성한 경우 해당 시간 전에 한 번도 테스트하지 않았 음을 의미합니다.


+1로 제어 할 수 없습니다 (통합 테스트 단계에서는 통과 할 수 있지만 프로덕션에서는 실패 함) .
Tulains Córdova

당신 만족할 정도로 그들을 제어 할 수 있습니다 .
el.pescado

나는 당신의 요점을 얻었지만 이것이 오늘날보다 더 사실이라고 생각합니까? Docker와 같은 자동화 및 도구를 사용하면 통합 테스트 슈트에 대해 모든 바이너리 / 서버 종속성 설정을 실제로 정확하고 안정적으로 복제하고 반복 할 수 있습니다. 물론 물리적 하드웨어 (및 타사 서비스 등)가 실패 할 수 있습니다.
mindplay.dk

5
나는 절대 동의하지 않습니다. 당신은 (추가) 통합 테스트를 작성해야 하기 때문에 extenal 의존성이 실패 할 수 있습니다. 외부 의존성에는 자체 단점이있을 수 있으므로 모든 것을 조롱하면 놓칠 수 있습니다.
Paul Kertscher

1
@PaulK는 여전히 허용 된 것으로 표시하는 답변을 숙고하지만 동일한 결론에 기울고 있습니다.
mindplay.dk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.