테스트 생성

기존 유닛 테스트에서 테스트는 몇 가지 항목으로 구성됩니다.

다음은 예제 테스트 구조입니다.

[Test]
void MyTest() {
    // data
    ArrayList a = new ArrayList();

    // method sequence
    a.Add(5);

    // assertions
    Assert.IsTrue(a.Count==1);
    Assert.AreEqual(a[0], 5);
}

IntelliTest는 메서드 호출 및 어설션의 시퀀스를 제공하는 더욱 일반적인 매개 변수가 있는 단위 테스트에 대한 관련 인수 값을 자동으로 결정할 수 있습니다.

테스트 생성기

IntelliTest는 실행할 테스트에서 구현의 메서드 시퀀스를 선택하고 파생 데이터에 대한 어설션을 확인하는 동안 메서드에 대한 입력을 생성하는 방식으로 테스트 사례를 생성합니다.

매개 변수가 있는 단위 테스트는 본문에 메서드 호출의 시퀀스를 직접 명시합니다.

IntelliTest에서 개체를 생성해야 할 경우 필요에 따라 생성자 및 팩터리 메서드 호출이 자동으로 시퀀스에 추가됩니다.

매개 변수가 있는 유닛 테스트

PUT(매개 변수가 있는 단위 테스트)는 매개 변수를 사용하는 테스트입니다. 일반적으로 폐쇄형 메서드인 기존 단위 테스트와 달리 PUT는 모든 매개 변수 집합을 사용합니다. 그렇게 간단한가요? 예 - 기존 테스트에서는 IntelliTest가 테스트에서 도달할 수 있는 코드를 완전히 검사하는 (최소) 입력 집합을 생성하려고 합니다.

PUT는 MSTest(또는 NUnit, xUnit)와 비슷한 방식으로 PexMethod 사용자 지정 특성을 사용하여 정의됩니다. PUT는 PexClass 태그가 지정된 클래스에서 논리적으로 그룹화되는 인스턴스 메서드입니다. 다음 예제에서는 MyPexTest 클래스에 저장된 간단한 PUT를 보여 줍니다.

[PexMethod]
void ReplaceFirstChar(string target, char c) {

    string result = StringHelper.ReplaceFirstChar(target, c);

    Assert.AreEqual(result[0], c);
}

여기서 ReplaceFirstChar은 문자열의 첫 번째 문제를 바꾸는 메서드입니다.

class StringHelper {
    static string ReplaceFirstChar(string target, char c) {
        if (target == null) throw new ArgumentNullException();
        if (target.Length == 0) throw new ArgumentOutOfRangeException();
        return c + target.Substring(1);
    }
}

이 테스트에서 IntelliTest는 테스트된 코드의 많은 실행 경로를 검사하는 PUT에 대한 입력을 자동으로 생성할 수 있습니다. 다른 실행 경로를 검사하는 각 입력은 단위 테스트로 “직렬화”됩니다.

[TestMethod, ExpectedException(typeof(ArgumentNullException))]
void ReplaceFirstChar0() {
    this.ReplaceFirstChar(null, 0);
}
...
[TestMethod]
void ReplaceFirstChar10() {
    this.ReplaceFirstChar("a", 'c');
}

제네릭 매개 변수가 있는 유닛 테스트

매개 변수가 있는 단위 테스트는 제네릭 메서드일 수 있습니다. 이 경우 사용자는 PexGenericArguments를 사용하여 메서드를 인스턴스화하는 데 사용되는 형식을 지정해야 합니다.

[PexClass]
public partial class ListTest {
    [PexMethod]
    [PexGenericArguments(typeof(int))]
    [PexGenericArguments(typeof(object))]
    public void AddItem<T>(List<T> list, T value)
    { ... }
}

예외 허용

IntelliTest는 예외를 예상된 예외 및 예기치 않은 예외로 심사하는 데 유용한 다양한 유효성 검사 특성을 제공합니다.

예상된 예외는 ExpectedException(typeof(xxx))와 같은 적절한 주석과 함께 부정적인 테스트 사례를 생성하지만, 예기치 않은 예외는 실패한 테스트 사례를 생성합니다.

[PexMethod, PexAllowedException(typeof(ArgumentNullException))]
void SomeTest() {...}

유효성 검사기는 다음과 같습니다.

internal 형식 테스트

IntelliTest는 볼 수 있는 internal 형식을 “테스트”할 수 있습니다. IntelliTest가 형식을 볼 수 있도록 Visual Studio IntelliTest 마법사를 통해 다음 특성이 제품 또는 테스트 프로젝트에 추가됩니다.

[assembly: InternalsVisibleTo("Microsoft.Pex, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]

가정 및 어설션

사용자는 가정 및 어설션을 사용하여 테스트에 대한 사전 조건(가정) 및 사후 조건(어설션)을 표현할 수 있습니다. IntelliTest가 매개 변수 값 집합을 생성하고 코드를 “탐색”하면 테스트의 가정을 위반할 수 있습니다. 이 문제가 발생하면 IntelliTest는 해당 경로에 대한 테스트를 생성하지 않고 해당 경로를 자동으로 무시합니다.

어설션은 일반 단위 테스트 프레임워크에서 잘 알려진 개념이므로 IntelliTest는 각 지원되는 프레임워크에서 제공된 기본 제공 Assert 클래스를 이미 “이해”합니다. 그러나 대부분의 프레임워크는 Assume 클래스를 제공하지 않습니다. 이 경우 IntelliTest는 PexAssume 클래스를 제공합니다. 기존 테스트 프레임워크를 사용하지 않을 경우에도 IntelliTest에는 PexAssert 클래스가 있습니다.

[PexMethod]
public void Test1(object o) {
    // precondition: o should not be null
    PexAssume.IsNotNull(o);

    ...
}

특히 null이 아닌 가정은 사용자 지정 특성으로 인코드할 수 있습니다.

[PexMethod]
public void Test2([PexAssumeNotNull] object o)
// precondition: o should not be null
{
   ...
}

Precondition

메서드의 사전 조건은 메서드가 성공하는 조건을 표현합니다.

일반적으로 사전 조건을 적용하려면 매개 변수 및 개체 상태를 확인하고 위반될 경우 ArgumentException 또는 InvalidOperationException을 throw합니다.

IntelliTest에서 매개 변수가 있는 단위 테스트의 사전 조건은 PexAssume을 사용하여 표현됩니다.

사후 조건

메서드의 사후 조건은 사전 조건이 처음에 유효했다는 가정 아래 메서드를 실행하는 동안과 그 후에 유지되어야 하는 조건을 표현합니다.

일반적으로 사후 조건은 Assert 메서드 호출을 통해 적용됩니다.

IntelliTest에서 매개 변수가 있는 단위 테스트의 사후 조건은 PexAssert를 사용하여 표현됩니다.

테스트 실패

생성된 테스트 사례가 실패하는 경우는 언제인가요?

  1. 구성된 경로 경계 내에서 종료되지 않을 경우 TestExcludePathBoundsExceeded 옵션이 설정되지 않는 한 실패로 간주합니다.

  2. 테스트에서 PexAssumeFailedException을 throw할 경우 테스트가 성공합니다. 그러나 일반적으로 TestEmissionFilterAll로 설정된 경우가 아니면 테스트가 필터링됩니다.

  3. 테스트가 어설션을 위반하면(예: 유닛 테스트 프레임워크의 어설션 위반 예외 throw) 테스트가 실패합니다.

위의 아무것도 의사 결정을 생성하지 않으면 예외를 throw하지 않는 경우에만 테스트가 성공합니다. 어설션 위반은 예외와 같은 방식으로 처리됩니다.

설치 및 해체

테스트 프레임워크와 통합하는 과정의 일부로 IntelliTest는 설치 및 해제 메서드를 검색 및 실행하는 기능을 지원합니다.

예제

using Microsoft.Pex.Framework;
using NUnit.Framework;

namespace MyTests
{
    [PexClass]
    [TestFixture]
    public partial class MyTestClass
    {
        [SetUp]
        public void Init()
        {
            // monitored
        }

        [PexMethod]
        public void MyTest(int i)
        {
        }

        [TearDown]
        public void Dispose()
        {
            // monitored
        }
    }
}

추가 참고 자료

피드백이 있으신가요?

아이디어와 기능 요청을 개발자 커뮤니티에 게시하세요.