자습서: Visual Studio Code를 사용하여 .NET 클래스 라이브러리 테스트

이 자습서에서는 솔루션에 테스트 프로젝트를 추가하여 단위 테스트를 자동화하는 방법을 보여 줍니다.

필수 조건

단위 테스트 프로젝트 만들기

단위 테스트는 개발 및 게시 동안 자동화된 소프트웨어 테스트를 제공합니다. 이 자습서에서 사용하는 테스트 프레임워크는 MSTest입니다. MSTest는 선택할 수 있는 세 가지 테스트 프레임워크 중 하나입니다. 다른 프레임워크는 xUnitnUnit입니다.

  1. Visual Studio Code 시작

  2. Visual Studio Code를 사용하여 .NET 클래스 라이브러리 만들기에서 만든 ClassLibraryProjects 솔루션을 엽니다.

  3. “StringLibraryTest”라는 단위 테스트 프로젝트를 만듭니다.

    dotnet new mstest -o StringLibraryTest
    

    프로젝트 템플릿에서 다음 코드를 사용하여 UnitTest1.cs 파일이 만들어집니다.

    namespace StringLibraryTest;
    
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
    

    단위 테스트 템플릿을 통해 만들어진 소스 코드는 다음을 수행합니다.

    [TestClass]로 태그가 지정된 테스트 클래스에서 [TestMethod]로 태그가 지정된 각 메서드는 단위 테스트가 호출될 때 자동으로 실행됩니다.

  4. 테스트 프로젝트를 솔루션에 추가합니다.

    dotnet sln add StringLibraryTest/StringLibraryTest.csproj
    

프로젝트 참조 추가

테스트 라이브러리가 StringLibrary 클래스에 대해 작동하도록 하기 위해 StringLibraryTest 프로젝트의 참조를 StringLibrary 프로젝트에 추가합니다.

  1. 다음 명령을 실행합니다.

    dotnet add StringLibraryTest/StringLibraryTest.csproj reference StringLibrary/StringLibrary.csproj
    

단위 테스트 메서드 추가 및 실행

Visual Studio는 단위 테스트를 호출할 때 TestClassAttribute 특성이 표시된 클래스에서 TestMethodAttribute 특성이 표시된 각 메서드를 실행합니다. 테스트 메서드는 첫 번째 오류가 발생하거나 메서드에 포함된 모든 테스트가 성공적으로 수행되면 종료됩니다.

가장 일반적인 테스트는 Assert 클래스의 멤버를 호출합니다. 많은 어설션 메서드에는 2개 이상의 매개 변수가 포함되며, 그 중 하나는 예상된 테스트 결과이고, 다른 하나는 실제 테스트 결과입니다. Assert 클래스에서 가장 자주 호출되는 일부 메서드는 다음 표에 나와 있습니다.

Assert 메서드 함수
Assert.AreEqual 두 개의 값이나 개체가 같은지를 확인합니다. 값이나 개체가 같지 않으면 어설션이 실패합니다.
Assert.AreSame 두 개의 개체 변수가 같은 개체를 참조하는지를 확인합니다. 변수가 서로 다른 개체를 참조하면 어설션이 실패합니다.
Assert.IsFalse 조건이 false인지 확인합니다. 조건이 true이면 어설션이 실패합니다.
Assert.IsNotNull 개체가 null이 아닌지를 확인합니다. 개체가 null이면 어설션이 실패합니다.

테스트 메서드에서 Assert.ThrowsException 메서드를 사용하여 throw될 것으로 예상되는 예외의 유형을 나타낼 수도 있습니다. 지정된 예외가 throw되지 않으면 테스트가 실패한 것입니다.

StringLibrary.StartsWithUpper 메서드를 테스트할 때 대문자로 시작하는 많은 문자열을 제공하려고 합니다. 이러한 경우에 메서드가 true를 반환할 것으로 기대하므로 Assert.IsTrue 메서드를 호출할 수 있습니다. 마찬가지로, 대문자 이외의 문자로 시작하는 많은 문자열을 제공하려고 합니다. 이러한 경우에 메서드가 false를 반환할 것으로 기대하므로 Assert.IsFalse 메서드를 호출할 수 있습니다.

라이브러리 메서드가 문자열을 처리하므로, 이 메서드에서 빈 문자열(String.Empty)null 문자열이 성공적으로 처리되는지도 확인해야 합니다. 빈 문자열은 문자가 없고 Length가 0인 문자열입니다. null 문자열은 초기화되지 않은 문자열입니다. StartsWithUpper를 직접 정적 메서드로 호출하고 단일 String 인수를 전달할 수 있습니다. 또는 null에 할당된 string 변수에 대한 확장 메서드로 StartsWithUpper를 호출할 수 있습니다.

각 메서드가 문자열 배열의 각 요소에 대해 해당 Assert 메서드를 호출하는 메서드 세 개를 정의해 보겠습니다. 테스트에 실패할 경우 표시될 오류 메시지를 지정할 수 있도록 하는 메서드 오버로드를 호출합니다. 메시지는 실패를 일으킨 문자열을 식별합니다.

테스트 메서드를 만들려면

  1. StringLibraryTest/UnitTest1.cs를 열고 모든 코드를 다음 코드로 바꿉니다.

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using UtilityLibraries;
    
    namespace StringLibraryTest;
    
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestStartsWithUpper()
        {
            // Tests that we expect to return true.
            string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва" };
            foreach (var word in words)
            {
                bool result = word.StartsWithUpper();
                Assert.IsTrue(result,
                       string.Format("Expected for '{0}': true; Actual: {1}",
                                     word, result));
            }
        }
    
        [TestMethod]
        public void TestDoesNotStartWithUpper()
        {
            // Tests that we expect to return false.
            string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                                   "1234", ".", ";", " " };
            foreach (var word in words)
            {
                bool result = word.StartsWithUpper();
                Assert.IsFalse(result,
                       string.Format("Expected for '{0}': false; Actual: {1}",
                                     word, result));
            }
        }
    
        [TestMethod]
        public void DirectCallWithNullOrEmpty()
        {
            // Tests that we expect to return false.
            string?[] words = { string.Empty, null };
            foreach (var word in words)
            {
                bool result = StringLibrary.StartsWithUpper(word);
                Assert.IsFalse(result,
                       string.Format("Expected for '{0}': false; Actual: {1}",
                                     word == null ? "<null>" : word, result));
            }
        }
    }
    

    TestStartsWithUpper 메서드의 대문자 테스트에는 그리스어 대문자 알파(U+0391) 및 키릴 자모 대문자 EM(U+041C)이 포함됩니다. TestDoesNotStartWithUpper 메서드의 소문자 테스트에는 그리스어 소문자 알파(U+03B1) 및 키릴 자모 소문자 Ghe(U+0433)가 포함됩니다.

  2. 변경 내용을 저장합니다.

  3. 테스트를 실행합니다.

    dotnet test StringLibraryTest/StringLibraryTest.csproj
    

    터미널 출력에 모든 테스트를 통과했음이 확인됩니다.

    Starting test execution, please wait...
    A total of 1 test files matched the specified pattern.
    
    Passed!  - Failed:     0, Passed:     3, Skipped:     0, Total:     3, Duration: 3 ms - StringLibraryTest.dll (net8.0)
    

테스트 실패 처리

TDD(테스트 기반 개발)를 수행하는 경우 먼저 테스트를 작성하고 첫 실행에서 실패합니다. 그런 다음, 테스트를 성공하게 만드는 코드를 앱에 추가합니다. 이 자습서에서는 유효성을 검사하는 앱 코드를 작성한 후에 테스트를 만들었으므로 테스트에 실패하지 않았습니다. 테스트가 실패할 것으로 예상되는 시점에 테스트가 실패하는지 확인하려면 테스트 입력에 잘못된 값을 추가하세요.

  1. TestDoesNotStartWithUpper 메서드의 words 배열이 "Error" 문자열을 포함하도록 수정합니다.

    string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                       "1234", ".", ";", " " };
    
  2. 테스트를 실행합니다.

    dotnet test StringLibraryTest/StringLibraryTest.csproj
    

    터미널 출력에는 하나의 테스트가 실패했음이 표시되고 실패한 테스트에 대한 오류 메시지인 "Assert.IsFalse 실패"가 표시됩니다. 'Error'에 필요한 값: false, 실제: True"가 표시됩니다. 이 오류 때문에 "Error" 다음에 나오는 배열의 문자열은 테스트되지 않았습니다.

    Starting test execution, please wait...
    A total of 1 test files matched the specified pattern.
      Failed TestDoesNotStartWithUpper [28 ms]
      Error Message:
       Assert.IsFalse failed. Expected for 'Error': false; Actual: True
      Stack Trace:
         at StringLibraryTest.UnitTest1.TestDoesNotStartWithUpper() in C:\ClassLibraryProjects\StringLibraryTest\UnitTest1.cs:line 33
    
    Failed!  - Failed:     1, Passed:     2, Skipped:     0, Total:     3, Duration: 31 ms - StringLibraryTest.dll (net5.0)
    
  3. 1단계에서 추가한 "Error" 문자열을 제거합니다. 테스트를 다시 실행하면 테스트를 통과합니다.

라이브러리의 릴리스 버전 테스트

라이브러리의 디버그 빌드를 실행할 때 테스트에 모두 통과했으므로 라이브러리의 릴리스 빌드에 대해 추가로 테스트를 실행합니다. 컴파일러 최적화를 비롯한 여러 가지 요인 때문에 디버그 및 릴리스 빌드 간에 서로 다른 동작이 발생할 수도 있습니다.

  1. 릴리스 빌드 구성을 사용하여 테스트를 실행합니다.

    dotnet test StringLibraryTest/StringLibraryTest.csproj --configuration Release
    

    테스트를 통과합니다.

테스트 디버그

Visual Studio Code를 IDE로 사용하는 경우 Visual Studio Code를 사용하여 .NET 콘솔 애플리케이션 디버그에 표시된 것과 동일한 프로세스를 사용하여 단위 테스트 프로젝트를 사용하는 코드를 디버그할 수 있습니다. ShowCase 앱 프로젝트를 시작하는 대신 StringLibraryTest/UnitTest1.cs를 열고 줄 7과 8 사이에서 Debug All Tests를 선택합니다. 이를 찾을 수 없는 경우 Ctrl+Shift+P를 눌러 명령 팔레트를 열고 Reload Window를 입력합니다.

Visual Studio Code가 디버거와 연결된 상태로 테스트 프로젝트를 시작합니다. 테스트 프로젝트에 추가한 중단점 또는 기본 라이브러리 코드에서 실행이 중지됩니다.

추가 리소스

다음 단계

이 자습서에서는 클래스 라이브러리의 단위 테스트를 실행했습니다. NuGet에 패키지로 라이브러리를 게시하면 다른 사용자가 사용할 수 있습니다. 방법을 알아보려면 NuGet 자습서를 따릅니다.

라이브러리를 NuGet 패키지로 게시하면 다른 사용자가 설치하고 사용할 수 있습니다. 방법을 알아보려면 NuGet 자습서를 따릅니다.

라이브러리는 패키지로 배포하지 않아도 됩니다. 라이브러리를 사용하는 콘솔 앱과 함께 제공할 수 있습니다. 콘솔 앱을 게시하는 방법을 알아보려면 이 시리즈의 이전 자습서를 참조하세요.

Visual Studio Code 확장 C# Dev Kit는 C# 앱 및 라이브러리 개발을 위한 추가 도구를 제공합니다.

이 자습서에서는 솔루션에 테스트 프로젝트를 추가하여 단위 테스트를 자동화하는 방법을 보여 줍니다.

필수 조건

단위 테스트 프로젝트 만들기

단위 테스트는 개발 및 게시 동안 자동화된 소프트웨어 테스트를 제공합니다. 이 자습서에서 사용하는 테스트 프레임워크는 MSTest입니다. MSTest는 선택할 수 있는 세 가지 테스트 프레임워크 중 하나입니다. 다른 프레임워크는 xUnitnUnit입니다.

  1. Visual Studio Code 시작

  2. Visual Studio Code를 사용하여 .NET 클래스 라이브러리 만들기에서 만든 ClassLibraryProjects 솔루션을 엽니다.

  3. “StringLibraryTest”라는 단위 테스트 프로젝트를 만듭니다.

    dotnet new mstest -o StringLibraryTest
    

    프로젝트 템플릿에서 다음 코드를 사용하여 UnitTest1.cs 파일이 만들어집니다.

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestMethod1()
            {
            }
        }
    }
    

    단위 테스트 템플릿을 통해 만들어진 소스 코드는 다음을 수행합니다.

    [TestClass]로 태그가 지정된 테스트 클래스에서 [TestMethod]로 태그가 지정된 각 메서드는 단위 테스트가 호출될 때 자동으로 실행됩니다.

  4. 테스트 프로젝트를 솔루션에 추가합니다.

    dotnet sln add StringLibraryTest/StringLibraryTest.csproj
    

프로젝트 참조 추가

테스트 라이브러리가 StringLibrary 클래스에 대해 작동하도록 하기 위해 StringLibraryTest 프로젝트의 참조를 StringLibrary 프로젝트에 추가합니다.

  1. 다음 명령을 실행합니다.

    dotnet add StringLibraryTest/StringLibraryTest.csproj reference StringLibrary/StringLibrary.csproj
    

단위 테스트 메서드 추가 및 실행

Visual Studio는 단위 테스트를 호출할 때 TestClassAttribute 특성이 표시된 클래스에서 TestMethodAttribute 특성이 표시된 각 메서드를 실행합니다. 테스트 메서드는 첫 번째 오류가 발생하거나 메서드에 포함된 모든 테스트가 성공적으로 수행되면 종료됩니다.

가장 일반적인 테스트는 Assert 클래스의 멤버를 호출합니다. 많은 어설션 메서드에는 2개 이상의 매개 변수가 포함되며, 그 중 하나는 예상된 테스트 결과이고, 다른 하나는 실제 테스트 결과입니다. Assert 클래스에서 가장 자주 호출되는 일부 메서드는 다음 표에 나와 있습니다.

Assert 메서드 함수
Assert.AreEqual 두 개의 값이나 개체가 같은지를 확인합니다. 값이나 개체가 같지 않으면 어설션이 실패합니다.
Assert.AreSame 두 개의 개체 변수가 같은 개체를 참조하는지를 확인합니다. 변수가 서로 다른 개체를 참조하면 어설션이 실패합니다.
Assert.IsFalse 조건이 false인지 확인합니다. 조건이 true이면 어설션이 실패합니다.
Assert.IsNotNull 개체가 null이 아닌지를 확인합니다. 개체가 null이면 어설션이 실패합니다.

테스트 메서드에서 Assert.ThrowsException 메서드를 사용하여 throw될 것으로 예상되는 예외의 유형을 나타낼 수도 있습니다. 지정된 예외가 throw되지 않으면 테스트가 실패한 것입니다.

StringLibrary.StartsWithUpper 메서드를 테스트할 때 대문자로 시작하는 많은 문자열을 제공하려고 합니다. 이러한 경우에 메서드가 true를 반환할 것으로 기대하므로 Assert.IsTrue 메서드를 호출할 수 있습니다. 마찬가지로, 대문자 이외의 문자로 시작하는 많은 문자열을 제공하려고 합니다. 이러한 경우에 메서드가 false를 반환할 것으로 기대하므로 Assert.IsFalse 메서드를 호출할 수 있습니다.

라이브러리 메서드가 문자열을 처리하므로, 이 메서드에서 빈 문자열(String.Empty)null 문자열이 성공적으로 처리되는지도 확인해야 합니다. 빈 문자열은 문자가 없고 Length가 0인 문자열입니다. null 문자열은 초기화되지 않은 문자열입니다. StartsWithUpper를 직접 정적 메서드로 호출하고 단일 String 인수를 전달할 수 있습니다. 또는 null에 할당된 string 변수에 대한 확장 메서드로 StartsWithUpper를 호출할 수 있습니다.

각 메서드가 문자열 배열의 각 요소에 대해 해당 Assert 메서드를 호출하는 메서드 세 개를 정의해 보겠습니다. 테스트에 실패할 경우 표시될 오류 메시지를 지정할 수 있도록 하는 메서드 오버로드를 호출합니다. 메시지는 실패를 일으킨 문자열을 식별합니다.

테스트 메서드를 만들려면

  1. StringLibraryTest/UnitTest1.cs를 열고 모든 코드를 다음 코드로 바꿉니다.

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using UtilityLibraries;
    
    namespace StringLibraryTest;
    
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestStartsWithUpper()
        {
            // Tests that we expect to return true.
            string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва" };
            foreach (var word in words)
            {
                bool result = word.StartsWithUpper();
                Assert.IsTrue(result,
                       string.Format("Expected for '{0}': true; Actual: {1}",
                                     word, result));
            }
        }
    
        [TestMethod]
        public void TestDoesNotStartWithUpper()
        {
            // Tests that we expect to return false.
            string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                                   "1234", ".", ";", " " };
            foreach (var word in words)
            {
                bool result = word.StartsWithUpper();
                Assert.IsFalse(result,
                       string.Format("Expected for '{0}': false; Actual: {1}",
                                     word, result));
            }
        }
    
        [TestMethod]
        public void DirectCallWithNullOrEmpty()
        {
            // Tests that we expect to return false.
            string?[] words = { string.Empty, null };
            foreach (var word in words)
            {
                bool result = StringLibrary.StartsWithUpper(word);
                Assert.IsFalse(result,
                       string.Format("Expected for '{0}': false; Actual: {1}",
                                     word == null ? "<null>" : word, result));
            }
        }
    }
    

    TestStartsWithUpper 메서드의 대문자 테스트에는 그리스어 대문자 알파(U+0391) 및 키릴 자모 대문자 EM(U+041C)이 포함됩니다. TestDoesNotStartWithUpper 메서드의 소문자 테스트에는 그리스어 소문자 알파(U+03B1) 및 키릴 자모 소문자 Ghe(U+0433)가 포함됩니다.

  2. 변경 내용을 저장합니다.

  3. 테스트를 실행합니다.

    dotnet test StringLibraryTest/StringLibraryTest.csproj
    

    터미널 출력에 모든 테스트를 통과했음이 확인됩니다.

    Starting test execution, please wait...
    A total of 1 test files matched the specified pattern.
    
    Passed!  - Failed:     0, Passed:     3, Skipped:     0, Total:     3, Duration: 3 ms - StringLibraryTest.dll (net7.0)
    

테스트 실패 처리

TDD(테스트 기반 개발)를 수행하는 경우 먼저 테스트를 작성하고 첫 실행에서 실패합니다. 그런 다음, 테스트를 성공하게 만드는 코드를 앱에 추가합니다. 이 자습서에서는 유효성을 검사하는 앱 코드를 작성한 후에 테스트를 만들었으므로 테스트에 실패하지 않았습니다. 테스트가 실패할 것으로 예상되는 시점에 테스트가 실패하는지 확인하려면 테스트 입력에 잘못된 값을 추가하세요.

  1. TestDoesNotStartWithUpper 메서드의 words 배열이 "Error" 문자열을 포함하도록 수정합니다.

    string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                       "1234", ".", ";", " " };
    
  2. 테스트를 실행합니다.

    dotnet test StringLibraryTest/StringLibraryTest.csproj
    

    터미널 출력에는 하나의 테스트가 실패했음이 표시되고 실패한 테스트에 대한 오류 메시지인 "Assert.IsFalse 실패"가 표시됩니다. 'Error'에 필요한 값: false, 실제: True"가 표시됩니다. 이 오류 때문에 "Error" 다음에 나오는 배열의 문자열은 테스트되지 않았습니다.

    Starting test execution, please wait...
    A total of 1 test files matched the specified pattern.
      Failed TestDoesNotStartWithUpper [28 ms]
      Error Message:
       Assert.IsFalse failed. Expected for 'Error': false; Actual: True
      Stack Trace:
         at StringLibraryTest.UnitTest1.TestDoesNotStartWithUpper() in C:\ClassLibraryProjects\StringLibraryTest\UnitTest1.cs:line 33
    
    Failed!  - Failed:     1, Passed:     2, Skipped:     0, Total:     3, Duration: 31 ms - StringLibraryTest.dll (net5.0)
    
  3. 1단계에서 추가한 "Error" 문자열을 제거합니다. 테스트를 다시 실행하면 테스트를 통과합니다.

라이브러리의 릴리스 버전 테스트

라이브러리의 디버그 빌드를 실행할 때 테스트에 모두 통과했으므로 라이브러리의 릴리스 빌드에 대해 추가로 테스트를 실행합니다. 컴파일러 최적화를 비롯한 여러 가지 요인 때문에 디버그 및 릴리스 빌드 간에 서로 다른 동작이 발생할 수도 있습니다.

  1. 릴리스 빌드 구성을 사용하여 테스트를 실행합니다.

    dotnet test StringLibraryTest/StringLibraryTest.csproj --configuration Release
    

    테스트를 통과합니다.

테스트 디버그

Visual Studio Code를 IDE로 사용하는 경우 Visual Studio Code를 사용하여 .NET 콘솔 애플리케이션 디버그에 표시된 것과 동일한 프로세스를 사용하여 단위 테스트 프로젝트를 사용하는 코드를 디버그할 수 있습니다. ShowCase 앱 프로젝트를 시작하는 대신 StringLibraryTest/UnitTest1.cs를 열고 줄 7과 8 사이에서 Debug All Tests를 선택합니다. 이를 찾을 수 없는 경우 Ctrl+Shift+P를 눌러 명령 팔레트를 열고 Reload Window를 입력합니다.

Visual Studio Code가 디버거와 연결된 상태로 테스트 프로젝트를 시작합니다. 테스트 프로젝트에 추가한 중단점 또는 기본 라이브러리 코드에서 실행이 중지됩니다.

추가 리소스

다음 단계

이 자습서에서는 클래스 라이브러리의 단위 테스트를 실행했습니다. NuGet에 패키지로 라이브러리를 게시하면 다른 사용자가 사용할 수 있습니다. 방법을 알아보려면 NuGet 자습서를 따릅니다.

라이브러리를 NuGet 패키지로 게시하면 다른 사용자가 설치하고 사용할 수 있습니다. 방법을 알아보려면 NuGet 자습서를 따릅니다.

라이브러리는 패키지로 배포하지 않아도 됩니다. 라이브러리를 사용하는 콘솔 앱과 함께 제공할 수 있습니다. 콘솔 앱을 게시하는 방법을 알아보려면 이 시리즈의 이전 자습서를 참조하세요.

이 자습서에서는 솔루션에 테스트 프로젝트를 추가하여 단위 테스트를 자동화하는 방법을 보여 줍니다.

필수 조건

단위 테스트 프로젝트 만들기

단위 테스트는 개발 및 게시 동안 자동화된 소프트웨어 테스트를 제공합니다. 이 자습서에서 사용하는 테스트 프레임워크는 MSTest입니다. MSTest는 선택할 수 있는 세 가지 테스트 프레임워크 중 하나입니다. 다른 프레임워크는 xUnitnUnit입니다.

  1. Visual Studio Code 시작

  2. Visual Studio Code를 사용하여 .NET 클래스 라이브러리 만들기에서 만든 ClassLibraryProjects 솔루션을 엽니다.

  3. “StringLibraryTest”라는 단위 테스트 프로젝트를 만듭니다.

    dotnet new mstest -f net6.0 -o StringLibraryTest
    

    -f net6.0 명령은 기본 대상 프레임워크를 net6.0 버전으로 변경합니다.

    -o 또는 --output 명령은 생성된 출력을 저장할 위치를 지정합니다.

    프로젝트 템플릿에서 다음 코드를 사용하여 UnitTest1.cs 파일이 만들어집니다.

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestMethod1()
            {
            }
        }
    }
    

    단위 테스트 템플릿을 통해 만들어진 소스 코드는 다음을 수행합니다.

    [TestClass]로 태그가 지정된 테스트 클래스에서 [TestMethod]로 태그가 지정된 각 메서드는 단위 테스트가 호출될 때 자동으로 실행됩니다.

  4. 테스트 프로젝트를 솔루션에 추가합니다.

    dotnet sln add StringLibraryTest/StringLibraryTest.csproj
    

프로젝트 참조 추가

테스트 라이브러리가 StringLibrary 클래스에 대해 작동하도록 하기 위해 StringLibraryTest 프로젝트의 참조를 StringLibrary 프로젝트에 추가합니다.

  1. 다음 명령을 실행합니다.

    dotnet add StringLibraryTest/StringLibraryTest.csproj reference StringLibrary/StringLibrary.csproj
    

단위 테스트 메서드 추가 및 실행

Visual Studio는 단위 테스트를 호출할 때 TestClassAttribute 특성이 표시된 클래스에서 TestMethodAttribute 특성이 표시된 각 메서드를 실행합니다. 테스트 메서드는 첫 번째 오류가 발생하거나 메서드에 포함된 모든 테스트가 성공적으로 수행되면 종료됩니다.

가장 일반적인 테스트는 Assert 클래스의 멤버를 호출합니다. 많은 어설션 메서드에는 2개 이상의 매개 변수가 포함되며, 그 중 하나는 예상된 테스트 결과이고, 다른 하나는 실제 테스트 결과입니다. Assert 클래스에서 가장 자주 호출되는 일부 메서드는 다음 표에 나와 있습니다.

Assert 메서드 함수
Assert.AreEqual 두 개의 값이나 개체가 같은지를 확인합니다. 값이나 개체가 같지 않으면 어설션이 실패합니다.
Assert.AreSame 두 개의 개체 변수가 같은 개체를 참조하는지를 확인합니다. 변수가 서로 다른 개체를 참조하면 어설션이 실패합니다.
Assert.IsFalse 조건이 false인지 확인합니다. 조건이 true이면 어설션이 실패합니다.
Assert.IsNotNull 개체가 null이 아닌지를 확인합니다. 개체가 null이면 어설션이 실패합니다.

테스트 메서드에서 Assert.ThrowsException 메서드를 사용하여 throw될 것으로 예상되는 예외의 유형을 나타낼 수도 있습니다. 지정된 예외가 throw되지 않으면 테스트가 실패한 것입니다.

StringLibrary.StartsWithUpper 메서드를 테스트할 때 대문자로 시작하는 많은 문자열을 제공하려고 합니다. 이러한 경우에 메서드가 true를 반환할 것으로 기대하므로 Assert.IsTrue 메서드를 호출할 수 있습니다. 마찬가지로, 대문자 이외의 문자로 시작하는 많은 문자열을 제공하려고 합니다. 이러한 경우에 메서드가 false를 반환할 것으로 기대하므로 Assert.IsFalse 메서드를 호출할 수 있습니다.

라이브러리 메서드가 문자열을 처리하므로, 이 메서드에서 빈 문자열(String.Empty)null 문자열이 성공적으로 처리되는지도 확인해야 합니다. 빈 문자열은 문자가 없고 Length가 0인 문자열입니다. null 문자열은 초기화되지 않은 문자열입니다. StartsWithUpper를 직접 정적 메서드로 호출하고 단일 String 인수를 전달할 수 있습니다. 또는 null에 할당된 string 변수에 대한 확장 메서드로 StartsWithUpper를 호출할 수 있습니다.

각 메서드가 문자열 배열의 각 요소에 대해 해당 Assert 메서드를 호출하는 메서드 세 개를 정의해 보겠습니다. 테스트에 실패할 경우 표시될 오류 메시지를 지정할 수 있도록 하는 메서드 오버로드를 호출합니다. 메시지는 실패를 일으킨 문자열을 식별합니다.

테스트 메서드를 만들려면

  1. StringLibraryTest/UnitTest1.cs를 열고 모든 코드를 다음 코드로 바꿉니다.

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using UtilityLibraries;
    
    namespace StringLibraryTest;
    
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestStartsWithUpper()
        {
            // Tests that we expect to return true.
            string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва" };
            foreach (var word in words)
            {
                bool result = word.StartsWithUpper();
                Assert.IsTrue(result,
                       string.Format("Expected for '{0}': true; Actual: {1}",
                                     word, result));
            }
        }
    
        [TestMethod]
        public void TestDoesNotStartWithUpper()
        {
            // Tests that we expect to return false.
            string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                                   "1234", ".", ";", " " };
            foreach (var word in words)
            {
                bool result = word.StartsWithUpper();
                Assert.IsFalse(result,
                       string.Format("Expected for '{0}': false; Actual: {1}",
                                     word, result));
            }
        }
    
        [TestMethod]
        public void DirectCallWithNullOrEmpty()
        {
            // Tests that we expect to return false.
            string?[] words = { string.Empty, null };
            foreach (var word in words)
            {
                bool result = StringLibrary.StartsWithUpper(word);
                Assert.IsFalse(result,
                       string.Format("Expected for '{0}': false; Actual: {1}",
                                     word == null ? "<null>" : word, result));
            }
        }
    }
    

    TestStartsWithUpper 메서드의 대문자 테스트에는 그리스어 대문자 알파(U+0391) 및 키릴 자모 대문자 EM(U+041C)이 포함됩니다. TestDoesNotStartWithUpper 메서드의 소문자 테스트에는 그리스어 소문자 알파(U+03B1) 및 키릴 자모 소문자 Ghe(U+0433)가 포함됩니다.

  2. 변경 내용을 저장합니다.

  3. 테스트를 실행합니다.

    dotnet test StringLibraryTest/StringLibraryTest.csproj
    

    터미널 출력에 모든 테스트를 통과했음이 확인됩니다.

    Starting test execution, please wait...
    A total of 1 test files matched the specified pattern.
    
    Passed!  - Failed:     0, Passed:     3, Skipped:     0, Total:     3, Duration: 3 ms - StringLibraryTest.dll (net6.0)
    

테스트 실패 처리

TDD(테스트 기반 개발)를 수행하는 경우 먼저 테스트를 작성하고 첫 실행에서 실패합니다. 그런 다음, 테스트를 성공하게 만드는 코드를 앱에 추가합니다. 이 자습서에서는 유효성을 검사하는 앱 코드를 작성한 후에 테스트를 만들었으므로 테스트에 실패하지 않았습니다. 테스트가 실패할 것으로 예상되는 시점에 테스트가 실패하는지 확인하려면 테스트 입력에 잘못된 값을 추가하세요.

  1. TestDoesNotStartWithUpper 메서드의 words 배열이 "Error" 문자열을 포함하도록 수정합니다.

    string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                       "1234", ".", ";", " " };
    
  2. 테스트를 실행합니다.

    dotnet test StringLibraryTest/StringLibraryTest.csproj
    

    터미널 출력에는 하나의 테스트가 실패했음이 표시되고 실패한 테스트에 대한 오류 메시지인 "Assert.IsFalse 실패"가 표시됩니다. 'Error'에 필요한 값: false, 실제: True"가 표시됩니다. 이 오류 때문에 "Error" 다음에 나오는 배열의 문자열은 테스트되지 않았습니다.

    Starting test execution, please wait...
    A total of 1 test files matched the specified pattern.
      Failed TestDoesNotStartWithUpper [28 ms]
      Error Message:
       Assert.IsFalse failed. Expected for 'Error': false; Actual: True
      Stack Trace:
         at StringLibraryTest.UnitTest1.TestDoesNotStartWithUpper() in C:\ClassLibraryProjects\StringLibraryTest\UnitTest1.cs:line 33
    
    Failed!  - Failed:     1, Passed:     2, Skipped:     0, Total:     3, Duration: 31 ms - StringLibraryTest.dll (net5.0)
    
  3. 1단계에서 추가한 "Error" 문자열을 제거합니다. 테스트를 다시 실행하면 테스트를 통과합니다.

라이브러리의 릴리스 버전 테스트

라이브러리의 디버그 빌드를 실행할 때 테스트에 모두 통과했으므로 라이브러리의 릴리스 빌드에 대해 추가로 테스트를 실행합니다. 컴파일러 최적화를 비롯한 여러 가지 요인 때문에 디버그 및 릴리스 빌드 간에 서로 다른 동작이 발생할 수도 있습니다.

  1. 릴리스 빌드 구성을 사용하여 테스트를 실행합니다.

    dotnet test StringLibraryTest/StringLibraryTest.csproj --configuration Release
    

    테스트를 통과합니다.

테스트 디버그

Visual Studio Code를 IDE로 사용하는 경우 Visual Studio Code를 사용하여 .NET 콘솔 애플리케이션 디버그에 표시된 것과 동일한 프로세스를 사용하여 단위 테스트 프로젝트를 사용하는 코드를 디버그할 수 있습니다. ShowCase 앱 프로젝트를 시작하는 대신 StringLibraryTest/UnitTest1.cs를 열고 줄 7과 8 사이에서 Debug All Tests를 선택합니다. 이를 찾을 수 없는 경우 Ctrl+Shift+P를 눌러 명령 팔레트를 열고 Reload Window를 입력합니다.

Visual Studio Code가 디버거와 연결된 상태로 테스트 프로젝트를 시작합니다. 테스트 프로젝트에 추가한 중단점 또는 기본 라이브러리 코드에서 실행이 중지됩니다.

추가 리소스

다음 단계

이 자습서에서는 클래스 라이브러리의 단위 테스트를 실행했습니다. NuGet에 패키지로 라이브러리를 게시하면 다른 사용자가 사용할 수 있습니다. 방법을 알아보려면 NuGet 자습서를 따릅니다.

라이브러리를 NuGet 패키지로 게시하면 다른 사용자가 설치하고 사용할 수 있습니다. 방법을 알아보려면 NuGet 자습서를 따릅니다.

라이브러리는 패키지로 배포하지 않아도 됩니다. 라이브러리를 사용하는 콘솔 앱과 함께 제공할 수 있습니다. 콘솔 앱을 게시하는 방법을 알아보려면 이 시리즈의 이전 자습서를 참조하세요.