장고에서의 단위 테스트


12

큰 장고 프로젝트에 효과적인 단위 테스트를 작성하는 데 어려움을 겪고 있습니다. 나는 상당히 좋은 테스트 범위를 가지고 있지만, 작성한 테스트는 전혀 단위 테스트가 아닌 통합 / 수락 테스트이며, 효과적으로 테스트되지 않는 응용 프로그램의 중요한 부분을 가지고 있음을 알게되었습니다. 이 문제를 최대한 빨리 해결하고 싶습니다.

여기 내 문제가 있습니다. 내 스키마는 깊이 관계가 있고 시간 지향적이므로 모델 객체에 높은 내부 커플 링과 많은 상태를 제공합니다. 많은 모델 메소드가 시간 간격을 기준으로 쿼리 auto_now_add하며 타임 스탬프 가 지정된 필드에서 많은 작업을 수행했습니다 . 예를 들어 다음과 같은 방법을 사용하십시오.

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()

    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.key_method(startTime, endTime) for object in objects)

이런 식으로 테스트하는 방법은 무엇입니까?

내가 지금까지 여기 있습니다. 단위 테스트 목표 에 인수에 대한 조롱 된 행동주어져야 하며 올바른 결과를 생성하기 위해 올바르게 필터링 / 집계되고 있습니까?by key_methodsummary

datetime.now ()를 조롱하는 것은 간단하지만 나머지 동작을 어떻게 조롱 할 수 있습니까?

  • 조명기를 사용할 수는 있지만 데이터를 구축하기 위해 조명기를 사용하는 장단점이 있다고 들었습니다.
  • ORM을 통해 데이터를 설정할 수도 있지만 관련 개체도 만들어야하므로 제한적일 수 있습니다. ORM을 사용하면 auto_now_add필드를 수동으로 엉망으로 만들 수 없습니다 .
  • ORM을 조롱하는 것은 또 다른 옵션이지만, 깊이 중첩 된 ORM 메소드를 조롱하는 것은 까다로울뿐만 아니라 ORM 코드의 로직은 테스트에서 조롱되며, 조롱은 테스트가 테스트의 내부 및 종속성에 실제로 의존하는 것으로 보입니다. 테스트 대상 기능.

가장 까다로운 너트는 이와 같은 기능으로, 몇 가지 모델 계층과 하위 수준 기능에 있으며 시간에 크게 의존합니다. 내 전반적인 문제는 내가 어떻게 슬라이스하는지에 관계없이 테스트가 테스트하는 기능보다 훨씬 복잡해 보인다는 것입니다.


이제 단위 테스트를 먼저 작성해야합니다. 실제 테스트 코드를 작성하기 전에 설계에서 테스트 가능성 문제를 발견하는 데 도움이됩니다.
Chedy2149

2
도움이되지만 본질적으로 상태가 풍부한 ORM이 많은 응용 프로그램을 가장 잘 테스트하는 방법 문제는 다루지 않습니다.
acjay

퍼시스턴스 레이어를 추상화해야합니다
Chedy2149

1
가상적으로 들리지만 프로젝트 유지 관리와 관련하여 비즈니스 논리와 매우 잘 문서화 된 Django ORM 사이에 맞춤형 지속성 레이어를 삽입하는 데 사소한 비용이 들지 않습니다. 갑자기 수업은 시간이 지남에 따라 리팩토링되어야하는 작은 중개 방법으로 가득 차게됩니다. 그러나 이것은 아마도 테스트 가능성이 중요한 곳에서 정당화 될 수 있습니다.
acjay

이것을 확인하십시오 : vimeo.com/43612849 및 이것 : vimeo.com/15007792
Chedy2149

답변:


6

계속해서 지금까지 내가 생각해 낸 것에 대한 답변을 등록하겠습니다.

내 가설은 깊은 결합과 상태를 가진 함수의 경우 실제로 외부 컨텍스트를 제어하기 위해 많은 줄을 가져야한다는 것입니다.

다음은 표준 Mock 라이브러리를 사용하여 테스트 사례를 대략적으로 보여줍니다.

  1. 표준 ORM을 사용하여 이벤트 순서를 설정합니다.
  2. 나는 내 자신의 시작을 만들고 내 디자인의 고정 된 타임 라인에 맞게 시간을 datetime파괴합니다 auto_now_add. ORM이 이것을 허용하지 않는다고 생각했지만 정상적으로 작동합니다.
  3. 테스트중인 함수를 사용 from datetime import datetime하여 datetime.now()해당 함수 만 패치 할 수 있도록합니다 (전체 datetime클래스를 조롱 하면 ORM이 적합 함).
  4. 나는 object.key_method()인수에 의존하는 간단하지만 잘 정의 된 기능을 사용하여에 대한 자체 대체를 만듭니다 . 테스트 대상 함수의 논리가 작동하는지 알 수 없기 때문에 인수에 의존하기를 원합니다. 필자의 경우 startTime와 사이의 초 수를 반환합니다 endTime. 나는 람다로 감싸고 object.key_method()new_callablekwarg 를 사용하여 직접 패치 하여 패치합니다 patch.
  5. 마지막으로, 나는 summary모의의 주어진 행동을 고려하여 예상되는 수동 계산 결과와의 평등을 확인하기 위해 다른 인수로 다양한 호출에 대해 일련의 주장을 실행합니다.key_method

말할 필요도없이, 이것은 함수 자체보다 훨씬 길고 복잡합니다. 그것은 DB에 달려 있으며 실제로 단위 테스트처럼 느껴지지 않습니다. 그러나 그것은 함수의 내부와도 상당히 분리되어있다. 서명과 의존성 만있다. 그래도 실제로는 단위 테스트 일 수 있습니다.

내 응용 프로그램에서 기능은 매우 중추적이며 성능을 최적화하기 위해 리팩토링이 적용됩니다. 그래서 문제는 그만한 가치가 있다고 생각합니다. 그러나 나는 여전히 이것에 접근하는 방법에 대한 더 나은 아이디어에 열려 있습니다. 좀 더 테스트 중심의 개발 스타일을 향한 긴 여정의 모든 부분 ...

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