태그 보관물: domain-driven-design

domain-driven-design

비즈니스 로직이 변경 될 때 단위 테스트가 실패하면 부서지기 쉬운 것으로 간주됩니까? 사람이 제안을받을 수 있는지 여부를 테스트합니다

아래 코드를 참조하십시오; 그것은 여성의 성별을 가진 사람이 제안을받을 수 있는지 여부를 테스트합니다 1 :

[Fact]
public void ReturnsFalseWhenGivenAPersonWithAGenderOfFemale()
{
    var personId = Guid.NewGuid();
    var gender = "F";
    var person = new Person(personId, gender);

    var id = Guid.NewGuid();
    var offer1 = new Offer1(id,"Offer1");
    Assert.False(offer1.IsEligible(person));
}

이 단위 테스트가 성공합니다. 그러나 앞으로 여성에게 ‘Offer1’이 제공되면 실패 할 것입니다.

오퍼 1을 둘러싼 비즈니스 로직이 변경되면 단위 테스트가 변경되어야합니다. 경우에 따라 (일부 오퍼의 경우) 비즈니스 로직이 데이터베이스에서 다음과 같이 변경됩니다.

update Offers set Gender='M' where offer=1;

그리고 어떤 경우에는 다음과 같은 도메인 모델에서 :

if (Gender=Gender.Male)
{
  //do something
}

경우에 따라 도메인 논리 뒤에있는 규칙이 정기적으로 변경 사항을 제공하지만 경우에 따라 변경되지 않는 경우도 있습니다.



답변

이것은 일반적인 의미에서 취하지 않습니다. 테스트중인 동작에 영향을 미치지 않는 구현 변경으로 인해 단위 테스트가 중단되면 취약한 것으로 간주됩니다. 비즈니스 로직 자체가 변화하지만,이 논리의 테스트가되어 가정 파괴 할 수 있습니다.

즉, 비즈니스 로직이 실제로 자주 변경되면 기대치를 단위 테스트에 하드 코딩하는 것이 적절하지 않을 수 있습니다. 대신 데이터베이스의 구성이 오퍼에 영향을 미치는지 테스트 할 수 있습니다.

테스트 이름은 Returns False When Given A Person With A Gender Of Female비즈니스 규칙을 설명하지 않습니다. 비즈니스 규칙은 다음과 같습니다 Offers Applicable to M should not be applied to persons of gender F.

따라서 오퍼가 M 유형 개인에게만 적용 가능한 것으로 정의 된 경우 F 유형 사람이 해당 자격을 갖춘 것으로 표시되지 않음 을 확인하는 테스트를 작성할 수 있습니다. 이 테스트는 특정 오퍼 구성이 변경 되더라도 로직이 작동하는지 확인합니다.


답변

속성이 프로덕션 데이터베이스 (또는 테스트 용 복제본)에 정의되어 있으면 단위 테스트 가 아닙니다 . 단위 테스트는 작업 단위를 확인하며 특정 외부 상태가 필요하지 않습니다. 이는 Offer1데이터베이스에 남성 전용 오퍼로 정의되어 있다고 가정 합니다. 외부 상태입니다. 따라서 이것은 통합 테스트 , 특히 시스템 또는 승인 테스트에 대한 것입니다. 승인 테스트는 종종 스크립팅되지 않습니다 (테스트 프레임 워크에서 실행되지 않고 사람이 수동으로 수행).

특성이 if명령문 과 함께 도메인 모델에 정의 된 경우 동일한 테스트는 단위 테스트입니다. 그리고 취하기 쉬울 수 있습니다. 그러나 실제 문제는 코드가 취약하다는 것입니다. 일반적으로 비즈니스 행동을 하드 코딩하는 대신 구성 할 수 있으면 코드의 탄력성이 향상됩니다. 작은 코딩 오류를 해결하기위한 급한 배포가 드물기 때문입니다. 그러나 사전 통지없이 변경되는 비즈니스 요구 사항은 화요일 (매주 발생하는 일)입니다.

테스트를 실행하기 위해 단위 테스트 프레임 워크를 사용 중일 수 있습니다. 그러나 단위 테스트 프레임 워크는 단위 테스트 실행으로 제한되지 않습니다. 통합 테스트도 수행 할 수 있습니다.

당신이 단위 테스트를 작성한다면, 당신은 둘을 만들 것입니다 personoffer1데이터베이스 상태에 의존하지 않음으로 처음부터. 같은 것

[Fact]
public void ReturnsFalseWhenGivenAPersonWithAGenderOfFemale()
{
    var personId = Guid.NewGuid();
    var gender = "F";
    var person = new Person(personId, gender);

    var id = Guid.NewGuid();
    var offer1 = new Offer1(id, "ReturnsFalseWhenGivenAPersonWithAGenderOfFemale");
    offer1.markLimitedToGender("M");

    Assert.False(offer1.IsEligible(person));
}

이것은 비즈니스 로직에 따라 변경되지 않습니다. offer1여성 을 거부 한다고 주장하는 것은 아닙니다 . offer1여성을 거부하는 제안 유형을 만들고 있습니다.

테스트의 일부로 데이터베이스를 작성하고 구성 할 수 있습니다. C #에서 NUnit을 사용하거나 Java의 JUnit에서 Setup메소드로 데이터베이스를 설정합니다 . 아마도 당신의 테스트 프레임 워크는 비슷한 개념을 가지고있을 것입니다. 이 방법에서는 SQL을 사용하여 데이터베이스에 레코드를 삽입 할 수 있습니다.

프로덕션 데이터베이스를 테스트 데이터베이스로 대체하는 코드를 작성하기 어려운 경우 애플리케이션의 테스트 취약점처럼 들립니다. 테스트의 경우 대체를 허용하는 종속성 주입과 같은 것을 사용하는 것이 좋습니다. 그런 다음 현재 비즈니스 규칙과 독립적 인 테스트를 작성할 수 있습니다.

이것의 부수적 인 이점은 종종 비즈니스 소유자 (회사 계층에서이 제품을 담당하는 사람과 같은 회사 소유자 일 필요는 없음)가 비즈니스 규칙을 직접 구성하는 것이 더 쉽다는 것입니다. 이러한 종류의 기술 프레임 워크가있는 경우 비즈니스 소유자가 UI (사용자 인터페이스)를 사용하여 오퍼를 구성하기가 쉽습니다. 비즈니스 소유자는 UI에서 제한을 선택하고 markLimitedToGender("M")호출을 발행합니다 . 그런 다음 오퍼가 데이터베이스에 지속되면이를 저장합니다. 그러나 오퍼를 사용하기 위해 오퍼를 저장하지 않아도됩니다. 따라서 테스트에서 데이터베이스에 존재하지 않는 오퍼를 작성하고 구성 할 수 있습니다.

설명 된대로 시스템에서 비즈니스 소유자는 기술 그룹에 요청하여 적절한 SQL을 발행하고 테스트를 업데이트해야합니다. 또는 기술 그룹에서 코드와 테스트를 편집해야합니다 (또는 테스트 한 다음 코드). 다소 무거운 접근법입니다. 넌 할 수있어. 그러나 테스트하지 않아도 소프트웨어는 덜 취하기 쉽습니다.

TL; DR : 이와 같은 테스트를 작성할 수 있지만 소프트웨어를 작성하지 않아도되기 때문에 소프트웨어를 작성하는 것이 좋습니다.


답변