2009-08-05 4 views
2

단위 테스트의 경우 프레임 워크가 얼마나 낮은 지 알면 항상 어렵습니다.테스트 할 수없는 것이 있습니까?

우리가 .NET Framework, 즉 System.IO.File 클래스에 직접 의존하는 클래스를 갖고 있다면 실제로는 테스트 할 수 없습니다.

물론이 클래스를 종속 클래스에 넣을 수는 있지만 모든 .NET 클래스를 래핑하기 시작합니다. 래퍼가 곧바로 통화하지 않으면 어떻게 될까요? 어쩌면 테스트/비즈니스 로직을 먼저 수행 할 것인가?

현재 특정 수준까지 랩핑 한 다음 래퍼 단위 테스트를 방해하지 않습니다. 나중에 통합 및 탐색 테스트를 통해 테스트 될 것이므로 아마도 괜찮을 것입니다.

이 클래스는 단단히 .NET 프레임 워크에 연결되어

.. 잘 먹으 렴하지만 지금은 격리에서 테스트 어차피,이 등 존재하는 파일이 필요합니다 : 여기

그냥 내 지점을 설명하기 위해 C#의 예입니다 . 같은 것을 수행하여

우리가 할 수있는
public class PathResolver 
{ 
    public string Resolve(string filename) 
    { 
     string completePath = string.Empty; 
     if(!File.Exists(filename)) 
     { 
      return Path.Combine(@"D:\MyExample", filename); 
     } 
     return completePath; 
    } 
} 

단위 테스트이 :

public class PathResolver 
{ 
    private readonly IFileSystem _fileSystem; 

    public PathResolver(IFileSystem fileSystem) 
    { 
     _fileSystem = fileSystem; 
    } 

    public string Resolve(string filename) 
    { 
     string completePath = string.Empty; 
     if(!_fileSystem.Exists(filename)) 
     { 
      return _fileSystem.Combine(@"D:\MyExample", filename); 
     } 
     return completePath; 
    } 
} 

하지만 지금 우리는 "파일 시스템"클래스를 테스트하지 못할!

다른 사람들의 생각은 무엇입니까?

답변

1

실제로 어느 시점에서 IFileSystem과 같은 인터페이스를 구현해야하므로 응용 프로그램을 .NET 프레임 워크에 붙일 수 있습니다. 이 "glue-code-in-between"은 단위 테스트를 할 수 없습니다. 이것은 접착제 코드가 매우 단순한 한 많은 문제가 아닙니다.

접착제 코드가 원하는만큼 간단하지 않은 경우에도 자동화 통합 테스트을 사용할 수 있습니다. 일종의 자체 테스트 모드에서 조립 된 응용 프로그램을 실행하십시오.

단위 테스트가 더 자주 사용되는 이유는 생성이 쉽고 부서지기 쉽지 않기 때문입니다. 단위 테스트를 실행하기 위해 데이터베이스, 웹 서버 또는 파일 시스템을 준비 할 필요가 없습니다. 클래스 B를 변경하면 클래스 A의 단위 테스트에 대해 걱정할 필요가 없습니다. 통합 테스트는 더 많은 것들을 테스트 할 수 있지만 이러한 장점은 없습니다.

+0

그래, 나는 너의 권리를 생각해. 가능한 한 간단하게 접착제 코드를 유지하고 조금 복잡해 보이면 우리의 대체 시험 방법을 받아 들여라. 그것은 우리가 짐작할 수있는 단위 테스트를하는 것의 가치를 단지 약간 줄입니다 ... 우리가 그 클래스 중 하나에서 무언가를 부숴 버렸는지를 알지 못할 것입니다! –

5

일반적으로 .NET과 같은 테스트 프레임 워크는 사용자의 책임이 아니라 프레임 워크를 릴리스하는 사람들의 책임입니다.

+0

+1. 프레임 워크 코드의 버그를 의심하지 않는 한 이미 테스트 한 것을 테스트 할 필요가 없습니다. 가능성은 거의 없습니다. – RichardOD

+0

그래, 동의하지만, 프레임 워크를 테스트하려하지 않는다. 코드가 제대로 작동하는지 테스트하는 중이 야. –

+0

프레임 워크는 재미있는 사례를 제시합니다. 왜냐하면 그들은 스크래치 응용 프로그램에서 단위 테스트가 될 특정 사항을 통합 테스트로 효과적으로 전환하기 때문입니다 (이제는 자신의 코드 대신 프레임 워크에서 "단위"를 사용하기 때문에). – Amber

0

System.IO를 테스트 하시겠습니까? 그렇지 않다면 왜 의존성을 없애기 위해 조롱/스터핑 방식을 사용하지 않을까요?

+0

예, 제가 보여준 예제 ... 그리고 질문입니다. 모든 .NET 클래스를 조롱/스터 빙 (즉 랩핑) 할 가치가 있습니다. 우리 코드가이 코드와 상호 작용하는지 확인하십시오. –

+0

예, 일반적으로 코드 만 테스트하려고합니다.클래스 B의 메소드에 의존하는 클래스 A의 메소드를 테스트한다면, 클래스 B의 메소드에 의존해야합니다. 따라서 클래스 A 메소드의 로직만을 테스트하십시오. (물론, 특별한 경우가 있습니다. 모듈 - 통합 테스트라고 함) – Ray

+0

죄송합니다. 조롱 한 프레임 워크를 사용하는 것에 동의했습니다. 시스템을 테스트하고 싶지 않습니다 .IO! 조롱 문제는 NMock2가 인터페이스만을 지원하기 때문에 File (우리가 사용하지 않는 인터페이스)이 필요합니다. 따라서 우리는이 인터페이스를 랩핑하고 삽입해야합니다 ... 그러나 이것은 우리가 많은 .NET 클래스를 래핑하기 시작한다는 것을 의미합니다 , 조금 틀린 느낌 ... 내 질문입니다. 우리는 모든 것을 포장합니까?, 그것을 테스트하지 않고 남겨 두었습니까? 아니면 다른 접근 방법이 있습니까? –

0

종속성 삽입을 사용하는 경우 클래스의 외부 호출이 외부 라이브러리가 아닌 스텁을 향하도록 할 수 있습니다.

+0

그래, 내 질문에 두 번째 예제가 보여주는 것 ...! –

0

단위 테스트를 할 때 불행히도 애플리케이션의 모든 것을 테스트 할 수 없습니다. 이것이 테스트를 할 때 테스트가 프로젝트에 대해 90 %의 코드 커버리지를 수행하는 것을 목표로하는 이유입니다. 이 테스트의 작업이

1

그것은 전체 프레임 워크 의존성을 스텁 필요는 없습니다 오히려 비용이 많이들 수 있기 때문에

하여 통합 테스트 또는 엔드 - 투 - 엔드 테스트도 일부의 일환으로이 테스트를 수행 - 당신의 코드를 단위 테스트하는 능력을 방해하는 부분들. 따라서 데이터베이스 호출과 함께 System.IO.File 작업을 자유롭게 작성해야한다고 생각합니다. 또한 DateTime.UtcNow를 호출하는 대신 IClock 인터페이스를 사용하여 시간을 알려주는 것이 매우 유용하다는 것을 알았습니다. 이렇게하면 단위 테스트에서 시간 경과를 제어 할 수 있습니다.

+0

그래,이게 내 처음 접근 이었어.하지만, 메시지 큐, 파일 시스템, 데이터베이스, 날짜, 랜덤 클래스 등을 감싸는 것이 점점 더 많아지는 것 같다. .hmm –

0

아래의 프레임 워크가 아니라 클래스를 테스트하면됩니다.

이 경우 테스트 케이스를 설정하는 테스트 드라이버가 필요합니다. 예를 들어 해결할 파일을 만들고 클래스를 인스턴스화하고 작업을 수행하십시오.

좋은 테스트 드라이버는 테스트 시나리오도 정리하고 시스템을 테스트 전과 동일한 상태로 둡니다.

+0

알아! 프레임 워크를 테스트하려고하지 않습니다! 나는 그것이 issolated되기를 바란다. 그러나 그것은 .NET 클래스의로드를 래핑하는 비용이 든다. 이것이 나의 요점이다. –

+0

프로젝트의 다른 클래스를 사용하지 않으면 클래스가 분리됩니다. 프레임 워크에서 프레임을 분리 할 필요가 없습니다. 클래스에 대한 입력을 테스트하고 클래스의 결과가 틀린 경우, 클래스의 무언가가 프레임 워크를 호출하는 것이 잘못된 것일 수 있지만 이미이 테스트를 통해 표시됩니다. –

+0

"프로젝트의 다른 클래스를 사용하지 않으면 수업이 격리됩니다."완전한 정의인지 확실하지 않습니까? - 파일 시스템, 데이터베이스, 메시지 대기열 등과도 상호 작용하지 않는 경우 테스트를 수행한다고 생각합니다. 이 경우 File 클래스가 파일 시스템과 상호 작용하고 있습니다 ... 테스트를 실행하지 않습니까? –

0

클래스를 테스트 할 수는 없지만 격리 프레임 워크 (Rhino Mocks, Typemock, Moq)를 사용하여 조롱 할 수있는 경우 "테스트 할 수없는"클래스의 세부 사항을 속일 수 있습니다.

1

이것은 단위 테스트와 통합 테스트의 차이점을 보여주는 좋은 예입니다. 단위 테스트 PathResolver의 경우 손으로 또는 모의 프레임 워크 (예 : 내 즐겨 찾기 Moq)를 사용하여 만든 모의 객체를 전달해야합니다. mock 객체를 사용하면 Combine 메서드가 호출되었는지 테스트 할 수 있습니다.

[Test] 
public void ShouldCombinePath() 
{ 
    IFileSystem fs = new Mock<IFileSystem>(); 

    PathResolver resolver = new PathResolver(fs.Object); 

    resolver.Resolve("Test.filename"); 

    fs.Verify(fs => fs.Combine()); 
} 

단위 테스트가 외부 종속성없이 빠르게 실행되도록되어 있습니다 :

단위 테스트는 다음과 같이 (MOQ를 사용하여)을 볼 것이다. 그들은 모든 컴파일마다 호출되어야합니다.

하지만 맞습니다. 구체적인 클래스를 테스트해야합니다. 이것이 통합 테스트입니다. "MyProject.IntegrationTest"라는 별도의 프로젝트를 만들고 프로젝트에 포함 된 테스트 파일을 사용하여 SystemFileSystem을 직접 테스트하는 것이 좋습니다.

통합 테스트는 지속적인 통합 소프트웨어를 사용하여, 커밋 새로운에서 소프트웨어의 빌드를 만들 때 일반적으로 불리는이

[Test] 
public void ShouldCombinePath() 
{ 
    DotNetFileSystem fileSystem = new DotNetFileSystem(); 

    string resultPath = fileSystem.Combine("Test.filename"); 

    Assert.That(resultPath, Text.Contains("@D:\MyExample\Test.filename")); 
} 

통합 테스트처럼 보일 것입니다. 외부 종속성을 사용하기 때문에 속도가 느려질 수 있습니다.

+0

본질적으로 현재의 접근 방식에 동의하고 테스트되지 않은 코드를 통합/탐색과 같은 다른 테스트에 맡기고 있습니까? –

+0

필요할 때 구체적인 구현을 테스트하십시오. 내가 제안한 것처럼, 이런 종류의 테스트에는 시간이 걸리기 때문에 다른 프로젝트를 사용하십시오. 현재 프로젝트에서 NHibernate 통합 테스트를 실행하는 데 약 1 분이 걸립니다. 내가 개발 한 NHibernate를 늦게까지 통합 했으므로 테스트를 통해 사이트를 시작하고 UI를 사용하여 테스트하는 것보다 테스트가 실제로 문제를 빨리 찾는데 도움이되었습니다. 그것은 가치. –

관련 문제