Share via


Live Unit Testing 시작

Visual Studio 솔루션에서 Live Unit Testing을 사용하도록 설정하면 테스트 검사와 테스트 상태가 시각적으로 표시됩니다. 또한 Live Unit Testing은 코드를 수정할 때마다 동적으로 테스트를 실행하고, 변경 내용으로 인해 테스트가 실패하는 경우 즉시 알림을 표시합니다.

.NET Framework 또는 .NET Core를 대상으로 하는 솔루션을 테스트하는 데 Live Unit Testing을 사용할 수 있습니다. 이 자습서에서는 .NET Standard를 대상으로 하는 간단한 클래스 라이브러리를 생성하여 Live Unit Testing을 사용하는 방법을 알아보고 .NET Core를 대상으로 테스트하는 MSTest 프로젝트를 생성합니다.

전체 C# 솔루션은 GitHub의 MicrosoftDocs/visualstudio-docs 리포지토리에서 다운로드할 수 있습니다.

필수 조건

이 자습서를 사용하려면 .NET Core 플랫폼간 개발 워크로드가 있는 Visual Studio Enterprise Edition을 설치해야 합니다.

솔루션 및 클래스 라이브러리 프로젝트 생성

단일 .NET Standard 클래스 라이브러리 프로젝트 StringLibrary로 구성된 UtilityLibraries라는 Visual Studio 솔루션을 만들어 시작합니다.

솔루션은 하나 이상의 프로젝트에 대한 컨테이너일 뿐입니다. 빈 솔루션을 만들려면 Visual Studio를 열고 다음을 수행합니다.

  1. 최상위 Visual Studio 메뉴에서 파일>새로 만들기>프로젝트를 선택합니다.

  2. 솔루션을 템플릿 검색 상자에 입력한 다음, 빈 솔루션 템플릿을 선택합니다. 프로젝트 이름을 UtilityLibraries로 지정합니다.

  3. 솔루션 만들기를 완료합니다.

이제 솔루션을 만들었으므로 문자열 작업을 위한 여러 가지 확장 메서드가 포함된 StringLibrary라는 클래스 라이브러리를 만듭니다.

  1. 솔루션 탐색기에서 UtilityLibraries 솔루션을 마우스 오른쪽 단추로 클릭하고 추가>새 프로젝트를 선택합니다.

  2. 클래스 라이브러리를 템플릿 검색 상자에 입력하고 클래스 라이브러리(.NET Standard) 템플릿을 선택합니다. 다음을 클릭합니다.

  3. 프로젝트 이름을 StringLibrary로 지정합니다.

  4. 만들기를 클릭하여 프로젝트를 만듭니다.

  5. 코드 편집기에서 모든 기존 코드를 다음 코드로 바꿉니다.

    using System;
    
    namespace UtilityLibraries
    {
        public static class StringLibrary
        {
            public static bool StartsWithUpper(this string s)
            {
                if (String.IsNullOrWhiteSpace(s))
                    return false;
    
                return Char.IsUpper(s[0]);
            }
    
            public static bool StartsWithLower(this string s)
            {
                if (String.IsNullOrWhiteSpace(s))
                    return false;
    
                return Char.IsLower(s[0]);
            }
    
            public static bool HasEmbeddedSpaces(this string s)
            {
                foreach (var ch in s.Trim())
                {
                    if (ch == ' ')
                        return true;
                }
                return false;
            }
        }
    }
    

    StringLibrary에는 다음과 같은 세 가지 정적 메서드가 있습니다.

    • StartsWithUpper는 문자열이 대문자로 시작하는 경우 true를 반환하고 그렇지 않은 경우 false를 반환합니다.

    • StartsWithLower는 문자열이 소문자로 시작하는 경우 true를 반환하고 그렇지 않은 경우 false를 반환합니다.

    • HasEmbeddedSpaces는 문자열에 포함된 공백 문자가 있는 경우 true를 반환하고 그렇지 않은 경우 false를 반환합니다.

  6. 최상위 Visual Studio 메뉴에서 빌드>솔루션 빌드를 선택합니다. 빌드가 성공적으로 수행됩니다.

테스트 프로젝트 만들기

다음 단계는 StringLibrary 라이브러리를 테스트하기 위한 단위 테스트 프로젝트를 만드는 것입니다. 다음 단계를 수행하여 단위 테스트를 만듭니다.

  1. 솔루션 탐색기에서 UtilityLibraries 솔루션을 마우스 오른쪽 단추로 클릭하고 추가>새 프로젝트를 선택합니다.

  2. 템플릿 검색 상자에 unit test를 입력하고 C#을 언어로 선택한 다음, .NET Core 템플릿에 대한 단위 테스트 프로젝트를 선택합니다. 다음을 클릭합니다.

    참고 항목

    Visual Studio 2019 버전 16.9에서 MSTest 프로젝트 템플릿 이름은 단위 테스트 프로젝트입니다.

  3. 프로젝트 이름을 StringLibraryTests로 지정하고 다음을 클릭합니다.

  4. 권장되는 대상 프레임워크 또는 .NET 6을 선택한 다음, 만들기를 선택합니다.

    참고 항목

    이 시작 자습서는 MSTest 테스트 프레임워크와 함께 Live Unit Testing을 사용합니다. 또한 xUnit 및 NUnit 테스트 프레임워크도 사용할 수 있습니다.

  5. 단위 테스트 프로젝트는 테스트 중인 클래스 라이브러리에 자동으로 액세스할 수 없습니다. 클래스 라이브러리 프로젝트에 대한 참조를 추가하여 테스트 라이브러리 액세스를 제공합니다. StringLibraryTests>이렇게 하려면 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가, 참조를 클릭합니다. 참조 관리자 대화 상자에서 솔루션 탭이 선택되어 있는지 확인하고 다음 그림에 표시된 것처럼 StringLibrary 프로젝트를 선택합니다.

    The Reference Manager dialog

    The Reference Manager dialog

  6. 템플릿에서 제공하는 상용구 단위 테스트 코드를 다음 코드로 바꿉니다.

    using System;
    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,
                                  $"Expected for '{word}': true; Actual: {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,
                                   $"Expected for '{word}': false; Actual: {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,
                                   $"Expected for '{(word == null ? "<null>" : word)}': " +
                                   $"false; Actual: {result}");
                }
            }
        }
    }
    
  7. 도구 모음에서 저장 아이콘을 선택하여 프로젝트를 저장합니다.

    단위 테스트 코드는 비ASCII 문자를 포함하므로 다음과 같은 대화 상자에서 기본 ASCII 형식으로 파일을 저장한 경우 일부 문자가 손실될 수 있다는 경고가 표시됩니다.

  8. 다른 인코딩으로 저장 단추를 선택합니다.

    Choose a file encoding

    Choose a file encoding

  9. 고급 저장 옵션 대화 상자의 인코딩 드롭다운 목록에서 다음 그림과 같이 유니코드(시그니처 없는 UTF-8) - 코드 페이지 65001을 선택합니다.

    Choosing the UTF-8 encoding

  10. 최상위 Visual Studio 메뉴에서 빌드>솔루션 다시 빌드를 선택하여 단위 테스트 프로젝트를 컴파일합니다.

클래스 라이브러리와 이에 대한 단위 테스트를 만들었습니다. 이제 Live Unit Testing을 사용하는 데 필요한 준비 작업을 완료했습니다.

Live Unit Testing을 사용하도록 설정

지금까지 StringLibrary 클래스 라이브러리에 대한 테스트를 작성했지만 실행하지는 않았습니다. Live Unit Testing을 사용하도록 설정했으면 자동으로 실행됩니다. 이렇게 하려면 다음을 수행할 수 있습니다.

  1. 필요에 따라 StringLibrary에 대한 코드가 포함된 코드 편집기 창을 선택합니다. C# 프로젝트의 경우 Class1.cs이고, Visual Basic 프로젝트의 경우 Class1.vb입니다. (이 단계를 통해 Live Unit Testing을 사용하도록 설정한 후 테스트 결과와 코드 검사를 시각적으로 검사할 수 있습니다.)

  2. 최상위 Visual Studio 메뉴에서 테스트>Live Unit Testing>시작을 선택합니다.

  3. 리포지토리 루트에 유틸리티 프로젝트와 테스트 프로젝트 모두에 대한 원본 파일 경로가 포함되어 있는지 확인하여 Live Unit Testing에 대한 구성을 확인합니다. 다음, 마침을 차례로 선택합니다.

  1. Live Unit Testing 창에서 모든 테스트 포함 링크를 선택합니다(또는 재생 목록 단추 아이콘을 선택한 다음, 그 아래에 있는 모든 테스트를 선택하는 StringLibraryTest를 선택합니다. 그런 다음 재생 목록 단추를 선택 취소하여 편집 모드를 종료합니다.)

  2. Visual Studio는 프로젝트를 다시 빌드하고 모든 테스트를 자동으로 실행하는 Live Unit Test를 시작합니다.

  1. Visual Studio는 프로젝트를 다시 빌드하고 모든 테스트를 자동으로 실행하는 Live Unit Test를 시작합니다.

테스트 실행이 완료되면 Live Unit Testing에 전반적인 결과와 개별 테스트 결과가 모두 표시됩니다. 또한 코드 편집기 창에는 테스트 코드 검사와 테스트 결과가 그래픽 방식으로 모두 표시됩니다. 다음 그림에서 볼 수 있듯이 세 테스트가 모두 성공적으로 실행됩니다. 또한 테스트가 StartsWithUpper 메서드의 모든 코드 경로를 포함하고 해당 테스트가 모두 성공적으로 실행되었음을 보여 줍니다(녹색 확인 표시 "✓"로 표시됨). 마지막으로 StringLibrary의 다른 메서드 중 어느 것도 코드 검사를 포함하지 않음을 보여 줍니다(파란색 선 "➖"로 표시됨).

The Live Test Explorer and code editor window after starting Live Unit testing

The Live Test Explorer and code editor window after starting Live Unit testing

코드 편집기 창에서 특정 코드 검사 아이콘을 선택하여 테스트 검사 및 테스트 결과에 대한 자세한 정보를 얻을 수도 있습니다. 이 세부 정보를 검사하려면 다음을 수행합니다.

  1. StartsWithUpper 메서드에서 if (String.IsNullOrWhiteSpace(s))라는 줄에서 녹색 확인 표시를 클릭합니다. 다음 그림처럼 Live Unit Testing은 코드 줄을 포함하는 세 가지 테스트를 나타내며 모두 성공적으로 실행되었습니다.

    Code coverage for the if conditional statement

    Code coverage for the if conditional statement

  2. StartsWithUpper 메서드에서 return Char.IsUpper(s[0])라는 줄에서 녹색 확인 표시를 클릭합니다. 다음 그림처럼 Live Unit Testing은 코드 줄을 포함하는 두 가지 테스트만 나타내며 모두 성공적으로 실행되었습니다.

    Code coverage for the return statement

    Code coverage for the return statement

Live Unit Testing에서 확인해야 할 주요 문제점은 불완전한 코드 검사입니다. 다음 섹션에서 이를 해결합니다.

테스트 검사 확장

이 섹션에서는 단위 테스트를 StartsWithLower 메서드로 확장합니다. 이렇게 하는 동안 Live Unit Testing은 계속해서 동적으로 코드를 테스트합니다.

코드 검사를 StartsWithLower 메서드로 확장하려면 다음을 수행합니다.

  1. 다음 TestStartsWithLowerTestDoesNotStartWithLower 메서드를 프로젝트의 테스트 소스 코드 파일로 추가합니다.

    // Code to add to UnitTest1.cs
    [TestMethod]
    public void TestStartsWithLower()
    {
        // Tests that we expect to return true.
        string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство" };
        foreach (var word in words)
        {
            bool result = word.StartsWithLower();
            Assert.IsTrue(result,
                          $"Expected for '{word}': true; Actual: {result}");
        }
    }
    
    [TestMethod]
    public void TestDoesNotStartWithLower()
    {
        // Tests that we expect to return false.
        string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва",
                           "1234", ".", ";", " "};
        foreach (var word in words)
        {
            bool result = word.StartsWithLower();
            Assert.IsFalse(result,
                           $"Expected for '{word}': false; Actual: {result}");
        }
    }
    
  2. Microsoft.VisualStudio.TestTools.UnitTesting.Assert.IsFalse 메서드 호출 바로 다음에 아래 코드를 추가하여 DirectCallWithNullOrEmpty 메서드를 수정합니다.

    // Code to add to UnitTest1.cs
    result = StringLibrary.StartsWithLower(word);
    Assert.IsFalse(result,
                   $"Expected for '{(word == null ? "<null>" : word)}': " +
                   $"false; Actual: {result}");
    
  3. 소스 코드를 수정하면 Live Unit Testing이 새 테스트와 수정된 테스트를 자동으로 실행합니다. 다음 그림처럼 추가한 테스트 2개와 수정한 테스트 1개가 모두 성공했습니다.

    The Live Test Explorer after expanding test coverage

    The Live Test Explorer after expanding test coverage

  4. StringLibrary 클래스에 대한 소스 코드가 포함된 창으로 전환합니다. 이제 Live Unit Testing은 코드 검사가 StartsWithLower 메서드로 확장되었음을 보여 줍니다.

    Code coverage for the StartsWithLower method

    Code coverage for the StartsWithLower method

경우에 따라 테스트 탐색기 에서 성공한 테스트가 회색으로 표시될 수 있습니다. 이는 테스트가 현재 실행 중이거나, 테스트가 마지막으로 실행된 이후 테스트에 영향을 줄 수 있는 코드 변경이 없었기 때문에 테스트가 다시 실행되지 않았음을 나타냅니다.

지금까지 테스트는 모두 성공했습니다. 다음 섹션에서는 테스트 실패를 처리하는 방법을 살펴봅니다.

테스트 실패 처리

이 섹션에서는 Live Unit Testing을 사용하여 테스트 실패를 식별, 문제 해결 및 처리하는 방법을 알아봅니다. 테스트 검사를 HasEmbeddedSpaces 메서드로 확장하여 이 작업을 수행합니다.

  1. 다음 메서드를 테스트 파일에 추가합니다.

    [TestMethod]
    public void TestHasEmbeddedSpaces()
    {
        // Tests that we expect to return true.
        string[] phrases = { "one car", "Name\u0009Description",
                             "Line1\nLine2", "Line3\u000ALine4",
                             "Line5\u000BLine6", "Line7\u000CLine8",
                             "Line0009\u000DLine10", "word1\u00A0word2" };
        foreach (var phrase in phrases)
        {
            bool result = phrase.HasEmbeddedSpaces();
            Assert.IsTrue(result,
                          $"Expected for '{phrase}': true; Actual: {result}");
        }
    }
    
  2. 테스트를 실행하면 다음 그림과 같이 Live Unit Testing이 TestHasEmbeddedSpaces 메서드가 실패했음을 보여 줍니다.

    The Live Test Explorer reporting a failed test

    The Live Test Explorer reporting a failed test

  3. 라이브러리 코드를 표시하는 창을 선택합니다. Live Unit Testing에서 코드 검사를 HasEmbeddedSpaces 메서드로 확장했습니다. 또한 빨간색 ‘’를 실패한 테스트 범위 줄에 추가하여 테스트 실패를 보고합니다.

  4. HasEmbeddedSpaces 메서드 서명이 있는 줄 위로 마우스를 가리킵니다. Live Unit Testing은 다음 그림과 같이 메서드가 하나의 테스트에서 검사됨을 보고하는 도구 설명을 표시합니다.

    Live Unit Testing information on a failed test

    Live Unit Testing information on a failed test

  5. 실패한 TestHasEmbeddedSpaces 테스트를 선택합니다. Live Unit Testing은 다음 그림과 같이 모든 테스트를 실행하고 모든 테스트를 디버그하는 등의 몇 가지 옵션을 제공합니다.

    Live Unit Testing options for a failed test

    Live Unit Testing options for a failed test

  6. 모두 디버그를 선택하여 실패한 테스트를 디버그합니다.

  7. Visual Studio는 디버그 모드에서 테스트를 실행합니다.

    테스트에서는 배열의 각 문자열을 phrase라는 변수에 할당하고 이를 HasEmbeddedSpaces 메서드에 전달합니다. 어설션 문이 처음으로 false일 때 프로그램 실행이 일시 중지되고 디버거를 호출합니다. Microsoft.VisualStudio.TestTools.UnitTesting.Assert.IsTrue 메서드 호출의 예기치 않은 값으로 생성되는 예외 대화 상자가 다음 그림과 같이 표시됩니다.

    Live Unit Testing exception dialog

    Live Unit Testing exception dialog

    또한 다음 그림과 같이 Visual Studio에서 제공하는 모든 디버깅 도구를 실패한 테스트를 문제 해결하는 데 사용할 수 있습니다.

    Visual Studio debugging tools

    Visual Studio debugging tools

    Autos 창에서 phrase 변수 값이 배열의 두 번째 요소인 "Name\tDescription"임을 확인합니다. 테스트 메서드는 HasEmbeddedSpaces가 이 문자열을 전달할 때 true를 반환할 것으로 예상하지만 false를 반환합니다. 분명히, 탭 문자 "\t"를 포함된 공백으로 인식하지 않습니다.

  8. 디버그>계속을 선택하거나, F5 키를 누르거나 도구 모음에서 계속 단추를 클릭하여 테스트 프로그램 실행을 계속합니다. 처리되지 않은 예외가 발생했으므로 테스트를 종료합니다. 여기서는 버그의 예비 조사를 위한 충분한 정보를 제공합니다. 테스트 루틴 TestHasEmbeddedSpaces가 잘못된 가정을 했거나 HasEmbeddedSpaces가 포함된 모든 공백을 제대로 인식하지 못합니다.

  9. 문제를 진단하고 해결하려면 StringLibrary.HasEmbeddedSpaces 메서드를 시작합니다. HasEmbeddedSpaces 메서드에서 비교를 확인합니다. 포함된 공백을 U+0020으로 간주합니다. 그러나 유니코드 표준은 다른 공백 문자 수를 포함합니다. 이것은 라이브러리 코드가 공백 문자를 잘못 테스트했음을 나타냅니다.

  10. 같음 비교를 System.Char.IsWhiteSpace 메서드에 대한 호출로 바꿉니다.

    if (Char.IsWhiteSpace(ch))
    
  11. 실패한 테스트 메서드를 Live Unit Testing에서 자동으로 다시 수행합니다.

    Live Unit Testing은 업데이트된 결과를 표시하며, 이 결과는 코드 편집기 창에도 나타납니다.