올바른 결과가 리턴되도록 TDD하는 방법


12

새 프로젝트를 시작하고 있으며 TDD를 사용하여 설계를 추진하기 위해 매우 열심히 노력하고 있습니다. 나는 몇 년 동안 추진해 왔으며 마침내이 프로젝트를 제대로 수행하는 방법을 배우는 동안이 프로젝트를 사용하기 위해 추가 시간을 할애하는 승인을 받았습니다.

기존 시스템에 연결하기위한 새로운 모듈입니다. 현재 모든 데이터 액세스는 웹 서비스를 통해 이루어지며 이는 대부분 데이터베이스 저장 프로 시저에 대한 간단한 래퍼입니다.

하나의 요구 사항은 주어진 상점에 대해이 응용 프로그램에 유효한 것으로 간주되는 모든 구매 주문을 리턴하는 것입니다. 배송 날짜가 상점 개점 날짜로부터 지정된 범위에 해당하는 경우 PO가 유효한 것으로 간주됩니다 (새 상점의 경우).

이제이 논리를 응용 프로그램 코드에 넣을 수는 없습니다. 위의 제약 조건에서이 저장소에 적용 할 수있는 수십 개를 얻기 위해 백만 개의 PO를 다시 가져 오지 않을 것이기 때문입니다.

날짜 범위를 GetValidPOs proc에 전달하고 해당 값을 사용하여 유효한 PO를 반환하도록 할 수 있다고 생각했습니다. 그러나 유효한 PO로 간주되는 사항에 다른 요구 사항을 추가하면 어떻게됩니까?

그리고 이것을 테스트하고 계속 작동하는지 어떻게 확인합니까? 우리는 ORM을 사용하지 않으며 일어날 가능성이 적습니다. 그리고 테스트에서 DB를 호출 할 수 없습니다.

나는 붙어있다.

내 다른 생각은 유효한 데이터를 반환하는 모의 객체와 잘못된 데이터를 반환하는 모의 객체가 있고 잘못된 데이터가 발생하면 로컬 저장소에서 예외가 발생하고 GetValidPOs proc에 의해 잘못된 데이터가 반환되면 예외가 발생하는지 테스트하는 것입니다. 테스트에 사용되는 모형).

이게 말이 되요? 아니면 더 좋은 방법이 있습니까?

업데이트 : EF를 사용할 수 있습니다. 이제는 저장 프로 시저를 계속 사용할 수 있고 여러 데이터베이스에 데이터를 분산시키는 데 어려움을 겪으면서 사용법을 알아 내고 테스트 할 수 있도록해야합니다.


호기심으로 일반 SQL 문으로 유효한 PO 만 선택할 수없는 이유는 무엇입니까? (이 질문 또는 답변은 해결책을 의미하지 않습니다.)
scarfridge

답변:


7

이것은 TDD 시대에 저장 프로 시저의 주요 단점입니다. 그들은 지금까지도 실질적인 단점이 있지만, 저장 프로 시저를 실행하는 테스트는 단위 테스트가 아닙니다. 기껏해야 통합 테스트입니다.

아키텍처가 ORM을 대신 사용하도록 변경할 수 없다고 가정하면 일반적인 솔루션은 이러한 테스트를 단위 테스트 스위트에 배치하지 않는 것입니다. 대신 테스트를 통합 스위트에 넣습니다. 테스트가 작동하는지 확인하고 싶을 때마다 테스트를 계속 실행할 수 있지만 테스트 설정에 고유 한 비용 (적절한 테스트 데이터로 DB를 초기화하는 데 드는 비용)이 높고 빌드 봇의 단위 테스트 에이전트가 제공하지 않는 리소스에 닿기 때문에 액세스 할 수 있으면 단위 테스트 스위트에 있지 않아야합니다.

단위 테스트 할 수없는 항목 (ADO.NET 클래스)을 모의 할 수있는 DAO 클래스로 추상화하여 데이터가 필요한 코드를 계속 테스트 할 수 있습니다. 그런 다음 코드를 사용하여 예상 호출이 이루어 졌는지 확인하고 다양한 사용 사례를 테스트 할 수있는 실제 결과 (예 : 결과 없음)를 재현 할 수 있습니다. 그러나 저장된 proc을 호출하기위한 SqlCommand의 실제 설정은 명령 실행에서 명령 생성을 분리하고 명령 실행자를 조롱함으로써 단위 테스트를 수행 할 수있는 가장 마지막입니다. 이것이 많은 우려의 분리처럼 들린다면, 그것은 가능할 수 있습니다. "너무 많은 간접 계층을 갖는 것을 제외하고 다른 간접 계층으로 해결할 수없는 문제는 없다"는 것을 기억하십시오. 어느 시점에서 당신은 "충분합니다; 나는 이것을 단위 테스트 할 수 없습니다.

다른 옵션:

  • SQLite와 같은 "짧은 수명"DBMS 인스턴스를 사용하여 저장된 프로 시저를 테스트하십시오. 일반적으로 ORM을 사용할 때이 작업을 수행하는 것이 더 쉽지만 테스트는 "메모리 내"(또는 테스트 스위트에 포함 된 사전 설정 데이터베이스 파일)로 수행 할 수 있습니다. 여전히 단위 테스트는 아니지만 높은 수준의 격리로 실행할 수 있습니다 (DBMS는 실행중인 프로세스의 일부이며 다른 사람의 충돌하는 테스트 스위트의 중간에있을 수있는 원격 연결은 아닙니다). 단점은 저장된 proc에 대한 변경 사항이 테스트에서 변경 사항을 반영하지 않고 프로덕션 환경에서 발생할 수 있으므로 테스트 환경에서 변경 사항이 처음으로 작성되도록 훈련해야합니다.

  • ORM으로 업그레이드하십시오. Linq 제공자가있는 ORM (일반적으로 공통적으로 사용되는 모든 것이 하나 있음)을 사용하면 조회를 Linq 문으로 정의 할 수 있습니다. 그런 다음 메모리에 테스트 데이터를 수집하여 적용 할 모의 리포지토리에 해당 명령문을 제공 할 수 있습니다. 따라서 DB를 건드리지 않고도 쿼리가 올바른지 확인할 수 있습니다 (Linq 공급자가 쿼리를 올바르게 다이제스트 할 수 있는지 테스트하려면 통합 환경에서 쿼리를 계속 실행해야 함).


2
TDD! = 단위 테스트이므로 -1입니다. TDD를 수행 할 때 통합 레벨 테스트를 포함하는 것이 좋습니다.
Steven A. Lowe

단위 테스트는 테스트 중심 개발의 일부입니다. 테스트 중심 개발에서는 시스템의 골격을 만든 다음 해당 시스템에서 단위, 통합 및 기능 테스트를 실행합니다. 통합, 단위 또는 승인 테스트에 실패하면 추가 테스트를 통과하고 작성하게됩니다.
CodeART

1
둘 다 이해합니다 통합 테스트가 필요하다는 것을 어디에서 TDD 할 수 없다고 말했습니까? 내 요점은 저장 프로 시저를 독립적으로 테스트 할 수 없다는 것입니다. 이는 가능한 많은 코드베이스에서 수행하려는 것입니다. SP를 테스트하려면 더 복잡하고 오래 실행되는 통합 테스트가 필요합니다. 수동 테스트보다 여전히 우수하지만 통합이 많은 테스트 스위트는 실행하는 데 몇 시간이 걸리고 CI 노력에 해로운 영향을 줄 수 있습니다.
KeithS

SP 테스트에는 종종 테스트 데이터베이스에 특정 데이터 세트가 필요합니다. 예상 결과를 달성하기 위해 데이터베이스를 올바른 상태로 만드는 코드는 실제로 실행하는 코드보다 LoC가 더 많고 몇 배 더 오래 실행됩니다. 이것은 테스트 스위트의 시간 복잡성을 더욱 복잡하게 만들고 종종 개별 테스트마다 설정을 반복해야합니다 (그리고 쿼리의 각 기능 요구 사항이 충족되는지 테스트하려면 각 SP마다 여러 개가 있어야 함).
KeithS

저장 프로시 저는 별도로 테스트 할 수 있습니다. 그것들은 다른 방법으로 검증됩니까? Transact SQL의 경우 tSQLt ( tsqlt.org )
kevin cline

4

나의 조언은 나누고 정복하는 것 입니다. 당분간 데이터베이스와 지속성을 잊고 리포지토리 또는 데이터 액세스 개체의 가짜 구현 테스트에 집중하십시오.

이제이 논리를 응용 프로그램 코드에 넣을 수는 없습니다. 위의 제약 조건에서이 저장소에 적용 할 수있는 수십 개를 얻기 위해 백만 개의 PO를 다시 가져 오지 않을 것이기 때문입니다.

구매 주문을 반환하는 저장소를 조롱합니다. 20 개의 홀수 구매 주문으로 모의 품을 만드십시오.

날짜 범위를 GetValidPOs proc에 전달하고 해당 값을 사용하여 유효한 PO를 반환하도록 할 수 있다고 생각했습니다. 그러나 유효한 PO로 간주되는 사항에 다른 요구 사항을 추가하면 어떻게됩니까?

데이터베이스 프로 시저가 아닌 모의를 호출하도록 GetValidPO에 대한 호출을 스텁하십시오.

그리고 이것을 테스트하고 계속 작동하는지 어떻게 확인합니까? 우리는 ORM을 사용하지 않으며 일어날 가능성이 적습니다. 그리고 테스트에서 DB를 호출 할 수 없습니다.

모형에서 올바른 데이터가 반환되는지 확인하려면 단위 테스트가 필요합니다.

또한 데이터베이스에서 올바른 데이터가 리턴되는지 확인하기 위해 통합 테스트가 필요합니다. 통합 테스트에는 일부 구성 및 정리가 필요합니다. 예를 들어, 통합 테스트를 실행하기 전에 스크립트를 실행하여 데이터베이스를 시드하십시오. 스크립트가 작동했는지 확인하십시오. 저장 프로 시저를 호출하여 데이터베이스를 쿼리하십시오. 결과가 올바른지 확인하십시오. 데이터베이스를 정리하십시오.

내 다른 생각은 유효한 데이터를 반환하는 모의 객체와 잘못된 데이터를 반환하는 모의 객체가 있고 잘못된 데이터가 발생하면 로컬 저장소에서 예외가 발생하고 GetValidPOs proc에 의해 잘못된 데이터가 반환되면 예외가 발생하는지 테스트하는 것입니다. 테스트에 사용되는 모형).

이미 말했듯이 쿼리 할 수있는 데이터를 적어도 반환하는 모의가 필요합니다.

데이터를 쿼리 할 때 시스템이 예외를 정상적으로 처리 할 수 ​​있는지 확인하려고합니다. 따라서 특정 시나리오에서 예외가 발생하도록 동작을 조롱합니다. 그런 다음 시스템이 이러한 예외를 정상적으로 처리 할 수 ​​있도록 테스트를 작성하십시오.


그것이 내가하려는 일입니다. 데이터 액세스가 ORM 사용에 도움이되지 않기 때문에 실제 구현을 작성하는 데 어려움이 있습니다. 필요한 대부분의 데이터는 여러 시스템에 있으며 업데이트 할 때도 웹 서비스를 통해 액세스해야합니다.
CaffGeek

0

Java 또는 Javascript 단위 테스트는 Java 용 Java 언어를 사용하여 단위 테스트를 작성하고 Javascript를 사용한 Javascript 기능을 단위 테스트하는 것을 의미하는 것처럼, 저장 프로 시저를 작성하기 위해 자동화 된 테스트를 작성하면 찾고있는 단위 테스트 라이브러리가 저장된 기반이됩니다. 절차.

다른 방법으로 다음과 같은 이유로 저장 프로 시저를 사용하여 저장 프로 시저를 테스트하십시오.

  • 프로 시저 언어로 개발 중이므로 프로 시저 언어로 테스트를 작성하는 기술이 있어야합니다.
  • 프로 시저 언어로 테스트를 작성하면 프로 시저 언어에 대한 기술이 향상되어 제품 개발에 도움이됩니다.
  • DB가 제공하는 모든 도구에 직접 액세스 할 수 있으며 해당 도구를 사용하여 단위 테스트를 가능한 한 간단하게 유지할 수 있습니다
  • 테스트하는 절차와 동일한 DB에 저장된 단위 테스트는 시스템 경계를 넘지 않기 때문에 속도와 같은 단위 테스트와 가장 가까운 것입니다.

OO 언어의 TDD와 마찬가지로 단위 테스트에서 한 행 정도의 데이터 만 설정하여 프로 시저에 필요한 내용 (미니멀리즘, 간단한 테스트에만 필요한 내용 만)을 테스트하려고합니다. 그 결과 각 저장 프로 시저에 대해 몇 가지 간단한 단위 테스트가 수행됩니다. 이러한 간단한 테스트는 테스트에 실제로 필요한 것으로 쉽게 매핑되지 않는 대규모 데이터 세트에 의존하는 복잡한 테스트보다 유지 관리가 더 쉽습니다.

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