NUnit 사용 단위 테스트(Unit Test)

  • 10 minutes to read

이 강의에서는 NUnit 테스트 프레임워크를 사용하여 단위 테스트를 진행하는 방법을 단계별로 진행합니다.

사전 요구 사항

  • .NET 7
  • Visual Studio 2022

원본 프로젝트 만들기

VisualAcademy 솔루션에 Domain.UnitTests 이름으로 C# 클래스 라이브러리 프로젝트를 생성합니다.

셸 창을 엽니다. 솔루션을 저장하기 위한 VisualAcademy라는 폴더를 만듭니다. 이 새 디렉터리 내에서 다음 명령을 실행하여 클래스 라이브러리 및 테스트 프로젝트에 대한 새 솔루션 파일을 만듭니다.

dotnet new sln

다음으로 PrimeService 폴더를 만듭니다. 다음 개요는 지금까지의 디렉터리와 파일 구조를 보여 줍니다.

/VisualAcademy
    VisualAcademy.sln
    /PrimeService

PrimeService 폴더로 이동하고 다음 명령을 실행하여 소스 프로젝트를 만듭니다. 단위 테스트를 위한 C# 클래스 라이브러리 프로젝트입니다.

dotnet new classlib

Class1.cs의 이름을 PrimeService.cs로 바꿉니다. 다음과 같이 PrimeService 클래스의 실패 구현을 만듭니다.

using System;

namespace Prime.Services
{
    public class PrimeService
    {
        public bool IsPrime(int candidate)
        {
            throw new NotImplementedException("먼저 테스트를 만드세요.");
        }
    }
}

폴더를 다시 VisualAcademy 디렉터리로 변경합니다. 다음 명령을 실행하여 클래스 라이브러리 프로젝트를 솔루션에 추가합니다. 물론 Visual Studio에서 직접 진행해도 됩니다.

dotnet sln add PrimeService/PrimeService.csproj

테스트 프로젝트 만들기

NUnit 프레임워크 관련 패키지

클래스 라이브러리 프로젝트에 NUnit 테스트 프레임워크를 사용하려면 다음 3개의 NuGet 패키지를 설치해야 합니다.

  • NUnit
  • NUnit3TestAdapter
  • Microsoft.NET.Test.Sdk
<ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.0" />
    <PackageReference Include="NUnit" Version="3.13.3" />
    <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
</ItemGroup>

Domain.UnitTests 프로젝트

PrimeService.Tests 프로젝트

다음으로 PrimeService.Tests 폴더를 만듭니다. 다음 개요에는 디렉터리 구조가 나와 있습니다.

/VisualAcademy
    VisualAcademy.sln
    /PrimeService
        Source Files
        PrimeService.csproj
    /PrimeService.Tests

PrimeService.Tests 폴더로 이동하고 다음 명령을 사용하여 새 프로젝트를 만듭니다.

dotnet new nunit

dotnet new 명령은 NUnit를 테스트 라이브러리로 사용하는 테스트 프로젝트를 만듭니다. 생성된 템플릿은 PrimeService.Tests.csproj 파일에 Test Runner를 구성합니다.

<ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.0" />
    <PackageReference Include="NUnit" Version="3.13.3" />
    <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
</ItemGroup>

테스트 프로젝트는 다른 패키지에 단위 테스트를 만들고 실행하도록 요구합니다. dotnet new 이전 단계의 명령은 Microsoft 테스트 SDK, NUnit 테스트 프레임워크 및 NUnit 테스트 어댑터를 추가했습니다. 이제 PrimeService 클래스 라이브러리를 프로젝트에 다른 종속성으로 추가합니다. dotnet add reference 명령을 사용합니다.

dotnet add reference ../PrimeService/PrimeService.csproj

GitHub의 샘플 리포지토리에서 전체 파일을 볼 수 있습니다.

다음 개요에는 최종 솔루션 레이아웃이 나와 있습니다.

/VisualAcademy
    VisualAcademy.sln
    /PrimeService
        Source Files
        PrimeService.csproj
    /PrimeService.Tests
        Test Source Files
        PrimeService.Tests.csproj

VisualAcademy 디렉터리에서 다음 명령을 실행합니다.

dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj

NUnit 테스트 특성

  • [TestFixture]: 테스트를 포함하는 클래스에 지정
  • [Test]: 테스트 메서드에 지정
  • [SetUp]: 테스트 실행 전에 먼저 실행할 코드 지정(생성자와 비슷)
  • [Category]: 카테고리로 조직화할 때 사용
  • [TestCase]: 하나 이상의 데이터를 매개 변수로 전달해서 테스트
  • [Values]: 매개 변수로 전달할 값 리스트
  • [Sequential]: 테스트 데이터 조합
  • [OneTimeSetup]: 테스트 실행 전에 딱 한 번 실행할 기능

NUnit 어설션(Assertions)

  • Assert.That()
  • Assert.AreEqual()

Arrange, Act, Assert

  • Arrange: 준비
  • Act: 실행
  • Assert: 확인

첫 번째 테스트 만들기

Domain.UnitTests

코드: TodoTests.cs

using Domain.Entities;
using NUnit.Framework;

namespace Domain.UnitTests.Entities;

[TestFixture]
public class TodoTests
{
    private Todo _todo = null!;
    private const int Id = 1;
    private const string Name = "Test";

    [SetUp]
    public void SetUp()
    {
        _todo = new Todo();
    }

    [Test]
    public void TestSetAndGetId()
    {
        _todo.Id = Id;

        Assert.That(_todo.Id, Is.EqualTo(Id));
    }

    [Test]
    public void TestSetAndGetName()
    {
        _todo.Name = Name;

        Assert.That(_todo.Name, Is.EqualTo(Name));
    }
}

코드: BrothTests.cs

using Domain.Entities.Buffets;
using NUnit.Framework;

namespace Domain.UnitTests.Entities.Buffets;

[TestFixture]
public class BrothTests
{
    private Broth _broth = null!;
    private const int Id = 1;
    private const string Name = "콩국물";

    [SetUp]
    public void SetUp()
    {
        _broth = new Broth();
    }

    [Test]
    public void TestSetAndGetId()
    {
        _broth.Id = Id;

        Assert.That(_broth.Id,
            Is.EqualTo(Id));
    }

    [Test]
    public void TestSetAndGetName()
    {
        _broth.Name = Name;

        Assert.That(_broth.Name,
            Is.EqualTo(Name));
    }
}

Prime.UnitTests

실패한 테스트 하나를 작성하고 통과한 다음 프로세스를 반복합니다. PrimeService.Tests 디렉터리에서 UnitTest1.cs 파일의 이름을 PrimeService_IsPrimeShould.cs로 변경하고 전체 내용을 다음 코드로 바꿉니다.

using NUnit.Framework;
using Prime.Services;

namespace Prime.UnitTests.Services
{
    [TestFixture]
    public class PrimeService_IsPrimeShould
    {
        private PrimeService _primeService;

        [SetUp]
        public void SetUp()
        {
            _primeService = new PrimeService();
        }

        [Test]
        public void IsPrime_InputIs1_ReturnFalse()
        {
            var result = _primeService.IsPrime(1);

            Assert.IsFalse(result, "1 should not be prime");
        }
    }
}

[TestFixture] 특성은 단위 테스트가 포함된 클래스를 나타냅니다. [Test] 특성은 메서드가 테스트 메서드임을 나타냅니다.

이 파일을 저장하고 명령을 실행 dotnet test 하여 테스트 및 클래스 라이브러리를 빌드하고 테스트를 실행합니다. NUnit Test Runner에는 테스트를 실행할 프로그램 진입점이 포함되어 있습니다. dotnet test는 만든 단위 테스트 프로젝트를 사용하여 Test Runner를 시작합니다.

테스트가 실패합니다. 구현은 아직 만들지 않았습니다. 작동하는 클래스에서 PrimeService 가장 간단한 코드를 작성하여 테스트를 통과합니다.

public bool IsPrime(int candidate)
{
    if (candidate == 1)
    {
        return false;
    }
    throw new NotImplementedException("먼저 테스트를 만드세요.");
}

VisualAcademy 디렉터리에서 dotnet test를 다시 실행합니다. dotnet test 명령은 PrimeService 프로젝트에 대한 빌드를 실행한 다음 PrimeService.Tests 프로젝트에 대한 빌드를 실행합니다. 두 프로젝트를 모두 빌드한 후 이 단일 테스트를 실행합니다. 전달합니다.

더 많은 기능 추가

이제 하나의 테스트를 통과했으므로 더 작성할 수 있습니다. 0-1을 추가로 입력하는 다른 간단한 테스트 사례가 있습니다. 새 테스트를 [Test] 특성과 함께 추가할 수도 있지만, 이렇게 하면 금방 지루해질 수 있습니다. 유사한 테스트 모음을 작성하는 데 사용할 수 있는 다른 NUnit 특성이 있습니다. [TestCase] 특성은 같은 코드를 실행하는 테스트 모음을 만드는 데 사용되지만, 서로 다른 입력 인수를 가지고 있습니다. [TestCase] 특성을 사용하여 그러한 입력의 값을 지정할 수 있습니다.

새 테스트를 만드는 대신 이 특성을 적용하여 단일 데이터 기반 테스트를 만듭니다. 이 데이터 기반 테스트는 가장 작은 소수인 2보다 작은 몇 가지 값을 테스트하는 메서드입니다.

[TestCase(-1)]
[TestCase(0)]
[TestCase(1)]
public void IsPrime_ValuesLessThan2_ReturnFalse(int value)
{
    var result = _primeService.IsPrime(value);

    Assert.IsFalse(result, $"{value}은(는) 소수가 아닙니다.");
}
[TestCase(-1)]
[TestCase(0)]
[TestCase(1)]
public void IsPrime_ValuesLessThan2_ReturnFalse(int value)
{
    var result = _primeService.IsPrime(value);

    Assert.IsFalse(result, $"{value} should not be prime");
}

dotnet test를 실행합니다. 그러면 이러한 테스트 중 2개가 실패합니다. 모든 테스트를 통과하려면 PrimeService.cs 파일에서 Main 메서드의 시작 부분에 있는 if 절을 변경합니다.

if (candidate < 2)

기본 라이브러리에 더 많은 테스트, 이론 및 코드를 추가하여 계속 반복합니다.

작은 라이브러리 및 이 라이브러리에 대한 단위 테스트 집합을 작성했습니다. 또한 새 패키지 및 테스트를 추가하는 것이 표준 워크플로의 일부가 되도록 솔루션을 구성했습니다. 애플리케이션의 목표를 해결하는 데 대부분의 시간과 노력을 들였습니다.

좋은 테스트의 조건

  • 빠른 테스트
  • 반복 가능 테스트
  • 독립적 테스트
  • 테스트 결과에 대한 확인
VisualAcademy Docs의 모든 콘텐츠, 이미지, 동영상의 저작권은 박용준에게 있습니다. 저작권법에 의해 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다. 사이트의 콘텐츠를 복제하여 블로그, 웹사이트 등에 게시할 수 없습니다. 단, 링크와 SNS 공유, Youtube 동영상 공유는 허용합니다. www.VisualAcademy.com
박용준 강사의 모든 동영상 강의는 데브렉에서 독점으로 제공됩니다. www.devlec.com