Udostępnij za pośrednictwem


Samouczek: testowanie biblioteki klas .NET

W tym samouczku pokazano, jak zautomatyzować testowanie jednostkowe przez dodanie projektu testowego do rozwiązania.

Wymagania wstępne

Ten samouczek współpracuje z rozwiązaniem utworzonym w Tworzenie biblioteki klas .NET.

Tworzenie projektu testów jednostkowych

Testy jednostkowe zapewniają zautomatyzowane testowanie oprogramowania podczas opracowywania i publikowania. MSTest jest jedną z trzech platform testowych, z których można wybrać. Pozostałe są xUnit i nUnit.

  1. Uruchom Visual Studio.

  2. Otwórz rozwiązanie ClassLibraryProjects utworzone w Utwórz bibliotekę klas .NET.

  3. Dodaj nowy projekt testu jednostkowego o nazwie "StringLibraryTest" do rozwiązania.

    1. Kliknij rozwiązanie prawym przyciskiem myszy w Solution Explorer i wybierz Dodaj>Nowy projekt.

    2. Na stronie Dodaj nowy projekt wprowadź mstest w polu wyszukiwania. Wybierz C# lub Visual Basic z listy Język, a następnie z listy Platforma wybierz pozycję Wszystkie platformy.

    3. Wybierz szablon MSTest Test Project, a następnie wybierz opcję Dalej.

    4. Na stronie Konfigurowanie nowego projektu wprowadź StringLibraryTest w polu Nazwa projektu. Następnie wybierz pozycję Dalej.

    5. Na stronie Additional information wybierz .NET 10 w polu Framework, wybierz Microsoft.Testing.PlatformTest runner, a następnie wybierz Utwórz.

    Wprowadź dodatkowe informacje dotyczące projektu testowego MSTest

  4. Visual Studio tworzy projekt i otwiera plik klasy w oknie kodu przy użyciu następującego kodu. Jeśli język, którego chcesz użyć, nie jest wyświetlany, zmień selektor języka w górnej części strony.

    namespace StringLibraryTest
    {
    
        [TestClass]
        public sealed class Test1
        {
            [TestMethod]
            public void TestMethod1()
            {
            }
        }
    }
    
    Imports Microsoft.VisualStudio.TestTools.UnitTesting
    
    Namespace StringLibraryTest
        <TestClass>
        Public Class Test1
            <TestMethod>
            Sub TestSub()
    
            End Sub
        End Class
    End Namespace
    

    Kod źródłowy utworzony przez szablon testu jednostkowego wykonuje następujące czynności:

    Każda metoda oznaczona tagiem [TestMethod] w klasie testowej oznaczonej tagiem [TestClass] jest wykonywana automatycznie po uruchomieniu testu jednostkowego.

  1. Uruchom Visual Studio Code.

  2. Otwórz rozwiązanie ClassLibraryProjects utworzone w Utwórz bibliotekę klas .NET.

  3. W Solution Explorer wybierz Nowy projekt lub z palety poleceń wybierz .NET: Nowy projekt.

  4. Wybierz pozycję Projekt testowy MSTest, nadaj mu nazwę "StringLibraryTest", wybierz katalog domyślny i wybierz pozycję Utwórz projekt.

    Szablon projektu tworzy StringLibraryTest/Test1.cs z następującym kodem:

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

    Kod źródłowy utworzony przez szablon testu jednostkowego wykonuje następujące czynności:

    Każda metoda oznaczona tagiem [TestMethod] w klasie testowej oznaczonej tagiem [TestClass] jest uruchamiana automatycznie po wywołaniu testu jednostkowego.

  1. Otwórz terminal i przejdź do folderu tutorials zawierającego projekty StringLibrary i ShowCase.

  2. Utwórz nowy projekt testowy MSTest:

    dotnet new mstest -n StringLibraryTest
    

    Szablon projektu tworzy StringLibraryTest/Test1.cs z następującym kodem:

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

    Kod źródłowy utworzony przez szablon testu jednostkowego wykonuje następujące czynności:

    Każda metoda oznaczona tagiem [TestMethod] w klasie testowej oznaczonej tagiem [TestClass] jest uruchamiana automatycznie po wywołaniu testu jednostkowego.

Dodawanie odwołania do projektu

Aby projekt testowy mógł współpracować z klasą StringLibrary, dodaj odwołanie w projekcie StringLibraryTest do projektu StringLibrary.

  1. W Solution Explorer kliknij prawym przyciskiem myszy węzeł Dependencies projektu StringLibraryTest i wybierz Dodaj odwołanie do projektu z menu kontekstowego.

  2. W oknie dialogowym Menedżer odwołań wybierz pole obok StringLibrary.

    Dodaj StringLibrary jako referencję do projektu dla StringLibraryTest.

  3. Kliknij przycisk OK.

  1. W Solution Explorer kliknij prawym przyciskiem myszy projekt "StringLibraryTest" i wybierz pozycję Dodaj odwołanie do projektu.

  2. Wybierz pozycję "BibliotekaCiągów".

  1. Przejdź do folderu StringLibraryTest i dodaj odwołanie do projektu:

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

Dodawanie i uruchamianie metod testów jednostkowych

Po uruchomieniu testu jednostkowego każda metoda oznaczona atrybutem TestMethodAttribute w klasie oznaczonej atrybutem TestClassAttribute jest wykonywana automatycznie. Metoda testowa kończy się po znalezieniu pierwszego błędu lub pomyślnym zakończeniu wszystkich testów zawartych w metodzie.

Najbardziej typowe testy wywołują członków klasy Assert. Wiele metod asercyjnych obejmuje co najmniej dwa parametry, z których jeden jest oczekiwanym wynikiem testu, a drugi jest rzeczywistym wynikiem testu. Niektóre z najczęściej wywoływanych metod klasy Assert przedstawiono w poniższej tabeli:

Metody asercji Function
Assert.AreEqual Sprawdza, czy dwie wartości lub obiekty są równe. Asercja kończy się niepowodzeniem, jeśli wartości lub obiekty nie są równe.
Assert.AreSame Sprawdza, czy dwie zmienne obiektu odwołują się do tego samego obiektu. Asercja kończy się niepowodzeniem, jeśli zmienne odwołują się do różnych obiektów.
Assert.IsFalse Sprawdza, czy warunek jest false. Asercja kończy się niepowodzeniem, jeśli warunek ma wartość true.
Assert.IsNotNull Sprawdza, czy obiekt nie jest null. Asercja kończy się niepowodzeniem, jeśli obiekt jest null.

Możesz również użyć Assert.Throws w metodzie testowej, aby wskazać oczekiwany typ wyjątku. Test kończy się niepowodzeniem, jeśli określony wyjątek nie zostanie zgłoszony.

Podczas testowania metody StringLibrary.StartsWithUpper, chcesz podać wiele ciągów, które zaczynają się od wielkiej litery. Oczekujesz, że metoda zwróci true w tych przypadkach, aby można było wywołać metodę Assert.IsTrue. Podobnie chcesz podać wiele ciągów, które zaczynają się od innego znaku niż wielkie litery. Oczekujesz, że metoda zwróci false w tych przypadkach, aby można było wywołać metodę Assert.IsFalse.

Ponieważ metoda biblioteki obsługuje ciągi, należy również upewnić się, że pomyślnie obsługuje pusty ciąg (String.Empty) i null ciąg. Pusty ciąg to taki, który nie ma znaków i którego Length ma wartość 0. Ciąg null to ciąg, który nie został zainicjowany. Możesz wywołać StartsWithUpper metodę statyczną bezpośrednio i przekazać pojedynczy String argument. Możesz także wywołać StartsWithUpper jako metodę rozszerzenia dla zmiennej string przypisanej do null.

Zdefiniujesz trzy metody, z których każda wywołuje metodę Assert dla każdego elementu w tablicy ciągów. Wywołasz przeciążenie metody, które umożliwia określenie komunikatu o błędzie, który ma być wyświetlany w przypadku niepowodzenia testu. Komunikat identyfikuje ciąg, który spowodował błąd.

Aby utworzyć metody testowe:

  1. W oknie kodu Test1.cs lub Test1.vb zastąp kod następującym kodem:

    using UtilityLibraries;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public sealed class Test1
        {
            [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>"}': false; Actual: {result}");
                }
            }
        }
    }
    
    Imports Microsoft.VisualStudio.TestTools.UnitTesting
    Imports UtilityLibraries
    
    Namespace StringLibraryTest
        <TestClass>
        Public Class UnitTest1
            <TestMethod>
            Public Sub TestStartsWithUpper()
                ' Tests that we expect to return true.
                Dim words() As String = {"Alphabet", "Zebra", "ABC", "Αθήνα", "Москва"}
                For Each word In words
                    Dim result As Boolean = word.StartsWithUpper()
                    Assert.IsTrue(result,
                           $"Expected for '{word}': true; Actual: {result}")
                Next
            End Sub
    
            <TestMethod>
            Public Sub TestDoesNotStartWithUpper()
                ' Tests that we expect to return false.
                Dim words() As String = {"alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                                   "1234", ".", ";", " "}
                For Each word In words
                    Dim result As Boolean = word.StartsWithUpper()
                    Assert.IsFalse(result,
                           $"Expected for '{word}': false; Actual: {result}")
                Next
            End Sub
    
            <TestMethod>
            Public Sub DirectCallWithNullOrEmpty()
                ' Tests that we expect to return false.
                Dim words() As String = {String.Empty, Nothing}
                For Each word In words
                    Dim result As Boolean = StringLibrary.StartsWithUpper(word)
                    Assert.IsFalse(result,
                           $"Expected for '{If(word Is Nothing, "<null>", word)}': false; Actual: {result}")
                Next
            End Sub
        End Class
    End Namespace
    

    Test wielkich liter w metodzie TestStartsWithUpper zawiera wielką literę alfa z alfabetu greckiego (U+0391) i wielką literę EM z alfabetu cyrylickiego (U+041C). Test małych liter w metodzie TestDoesNotStartWithUpper zawiera grecką małą literę alfa (U+03B1) i cyrylicką małą literę gie (U+0433).

  2. Na pasku menu wybierz pozycję Plik>Zapisz Test1.cs jako lub Plik>Zapisz Test1.vb jako. W oknie dialogowym Zapisz plik jako wybierz strzałkę obok przycisku Zapisz, a następnie wybierz Zapisz z kodowaniem.

  3. W oknie dialogowym Potwierdź zapisanie jako wybierz przycisk Tak, aby zapisać plik.

  4. W oknie dialogowym Zaawansowane opcje zapisu zaznacz Unicode (UTF-8 z podpisem) — Kodowa strona 65001 z listy rozwijanej Kodowanie i wybierz OK.

    Jeśli nie uda ci się zapisać kodu źródłowego jako pliku zakodowanego w formacie UTF8, Visual Studio może zapisać go jako plik ASCII. W takim przypadku środowisko uruchomieniowe nie dekoduje dokładnie znaków UTF8 poza zakresem ASCII, a wyniki testu nie są poprawne.

  5. Na pasku menu wybierz pozycję Test>Uruchom wszystkie testy. Jeśli okno eksploratora testów nie jest otwarte, otwórz je, wybierając pozycję TestTest Explorer. Trzy testy są wymienione w sekcji 'Zaliczone Testy', a sekcja 'Podsumowanie' raportuje wynik uruchomienia testu.

    okno Eksploratora Testów z zaliczonymi testami

  1. Otwórz plik StringLibraryTest/Test1.cs i zastąp cały kod poniższym kodem.

    using UtilityLibraries;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public sealed class Test1
        {
            [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>"}': false; Actual: {result}");
                }
            }
        }
    }
    

    Test wielkich liter w metodzie TestStartsWithUpper zawiera wielką literę alfa z alfabetu greckiego (U+0391) i wielką literę EM z alfabetu cyrylickiego (U+041C). Test małych liter w metodzie TestDoesNotStartWithUpper zawiera grecką małą literę alfa (U+03B1) i cyrylicką małą literę gie (U+0433).

  2. Zapisz swoje zmiany.

Kompilowanie i uruchamianie testów

  1. W Solution Explorer kliknij rozwiązanie prawym przyciskiem myszy i wybierz pozycję Build lub z palety poleceń wybierz pozycję .NET: Build.

  2. Wybierz okno Testowanie , wybierz pozycję Uruchom testy lub z palety poleceń wybierz pozycję Testuj: Uruchom wszystkie testy.

    Visual Studio Code Eksplorator testów

  1. Otwórz plik StringLibraryTest/Test1.cs i zastąp cały kod następującym kodem:

    using UtilityLibraries;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public sealed class Test1
        {
            [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>"}': false; Actual: {result}");
                }
            }
        }
    }
    

    Test wielkich liter w metodzie TestStartsWithUpper zawiera wielką literę alfa z alfabetu greckiego (U+0391) i wielką literę EM z alfabetu cyrylickiego (U+041C). Test małych liter w metodzie TestDoesNotStartWithUpper zawiera grecką małą literę alfa (U+03B1) i cyrylicką małą literę gie (U+0433).

  2. Zapisz zmiany i uruchom testy:

    dotnet test
    

    Testy powinny zostać wykonane pomyślnie.

Obsługa niepowodzeń testów

Jeśli wykonujesz programowanie oparte na testach (TDD), najpierw piszesz testy i kończą się one niepowodzeniem przy pierwszym uruchomieniu. Następnie dodasz kod do aplikacji, który sprawia, że test zakończy się pomyślnie. Na potrzeby tego samouczka utworzono test po napisaniu kodu aplikacji, który ma weryfikować. Dlatego nie mieliście okazji zaobserwować niepowodzenia testu. Aby sprawdzić, czy test zakończy się niepowodzeniem, gdy oczekujesz, że zakończy się niepowodzeniem, dodaj nieprawidłową wartość do danych wejściowych testu.

  1. Zmodyfikuj tablicę words w metodzie TestDoesNotStartWithUpper, aby uwzględnić ciąg "Błąd".

    string[] words = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                       "1234", ".", ";", " " };
    
    Dim words() As String = { "alphabet", "Error", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                       "1234", ".", ";", " " }
    
    
  1. Uruchom test, wybierając pozycję Test>Uruchom wszystkie testy na pasku menu. Okno Eksploratora testów wskazuje, że dwa testy zakończyły się pomyślnie i jeden zakończył się niepowodzeniem.

    okno eksploratora testów z testami zakończonymi niepowodzeniem

  2. Wybierz test, który zakończył się niepowodzeniem, TestDoesNotStartWith.

    W oknie Eksploratora testów wyświetlany jest komunikat wygenerowany przez asercję: "Assert.IsFalse nie powiodło się." Oczekiwano wartości "Błąd": false; rzeczywista: prawda". Ze względu na błąd ciągi w tablicy po błędzie nie zostały przetestowane.

    okno Eksploratora testów pokazujące niepowodzenie asercji IsFalse

  1. Uruchom testy, klikając zielony przycisk obok testu w edytorze.

    Dane wyjściowe pokazują, że test kończy się niepowodzeniem i zawiera komunikat o błędzie dla testu, który zakończył się niepowodzeniem: "Assert.IsFalse failed. Oczekiwana wartość dla 'Błąd': false; rzeczywista: true. Ze względu na błąd, żadne ciągi w tablicy znajdujące się po "Error" nie zostały przetestowane.

    Nieudany Test Visual Studio Code

  1. Uruchom testy:

    dotnet test
    

    Dane wyjściowe pokazują, że test kończy się niepowodzeniem i zawiera komunikat o błędzie dla testu, który zakończył się niepowodzeniem: "Assert.IsFalse failed. Oczekiwana wartość dla 'Błąd': false; rzeczywista: true. Ze względu na błąd, żadne ciągi w tablicy znajdujące się po "Error" nie zostały przetestowane.

  1. Usuń dodany ciąg "Błąd".

  2. Uruchom ponownie test, aby testy przeszły.

Testowanie wersji biblioteki

Teraz, gdy wszystkie testy pomyślnie przeszły podczas uruchamiania kompilacji Debug biblioteki, uruchom testy ponownie dla kompilacji Release biblioteki. Wiele czynników, w tym optymalizacje kompilatora, może czasami generować różne zachowanie między buildami Debug i Release.

Aby przetestować kompilację wydania:

  1. Na pasku narzędzi Visual Studio zmień konfigurację kompilacji z Debug na Release.

  2. W Solution Explorer kliknij prawym przyciskiem myszy StringLibrary projekt i wybierz Build z menu kontekstowego, aby ponownie skompilować bibliotekę.

  3. Uruchom testy jednostkowe, wybierając pozycję Test>Uruchom wszystkie testy na pasku menu. Testy zakończone pomyślnie.

Uruchom testy z konfiguracją kompilacji typu Release.

dotnet test StringLibraryTest/StringLibraryTest.csproj --configuration Release

Testy zakończone pomyślnie.

Uruchom testy z konfiguracją kompilacji typu Release.

dotnet test --configuration Release

Testy zakończone pomyślnie.

Debugowanie testów

Jeśli używasz Visual Studio jako środowiska IDE, możesz użyć tego samego procesu pokazanego w Tutorial: Debugowanie aplikacji konsolowej .NET do debugowania kodu przy użyciu projektu testu jednostkowego. Zamiast uruchamiać projekt aplikacji ShowCase, kliknij prawym przyciskiem myszy na projekcie StringLibraryTests, a następnie wybierz Debuguj testy z menu kontekstowego.

Visual Studio uruchamia projekt testowy z dołączonym debugerem. Wykonanie zatrzymuje się w dowolnym punkcie przerwania dodanym do projektu testowego lub kodu bazowej biblioteki.

Jeśli używasz Visual Studio Code jako środowiska IDE, możesz użyć tego samego procesu pokazanego w Debug aplikacji konsolowej .NET do debugowania kodu przy użyciu projektu testów jednostkowych. Zamiast uruchamiać projekt aplikacji ShowCase , otwórz plik StringLibraryTest/Test1.cs i wybierz pozycję Debuguj testy w bieżącym pliku między wierszami 7 i 8. Jeśli nie możesz go znaleźć, naciśnij klawisze Ctrl+Shift+P , aby otworzyć paletę poleceń i wprowadzić polecenie Załaduj ponownie okno.

Visual Studio Code uruchamia projekt testowy z dołączonym debugerem. Wykonanie zostanie zatrzymane w dowolnym punkcie przerwania dodanym do projektu testowego lub kodu bazowej biblioteki.

Dodatkowe zasoby

Oczyszczanie zasobów

GitHub automatycznie usuwa przestrzeń Codespace po upływie 30 dni braku aktywności. Jeśli planujesz zapoznać się z więcej samouczków w tej serii, możesz pozostawić aprowizowaną usługę Codespace. Jeśli chcesz odwiedzić witrynę .NET aby pobrać zestaw SDK .NET, możesz usunąć środowisko Codespace. Aby usunąć swój Codespace, otwórz okno przeglądarki i przejdź do Twoich Codespaces. W oknie wyświetlana jest lista twoich codespaces. Wybierz trzy kropki (...) we wpisie dotyczącym codespace samouczka learn. Następnie wybierz pozycję "Usuń".

Dalsze kroki

W tym samouczku przeprowadzono testy jednostkowe biblioteki klas. Bibliotekę można udostępnić innym osobom, publikując ją w pakiecie NuGet . Aby dowiedzieć się, jak to zrobić, postępuj zgodnie z samouczkiem NuGet:

Jeśli publikujesz bibliotekę jako pakiet NuGet, inne osoby mogą je instalować i używać. Aby dowiedzieć się, jak to zrobić, postępuj zgodnie z samouczkiem NuGet:

Biblioteka nie musi być dystrybuowana jako pakiet. Może być on powiązany z aplikacją konsolową, która z niej korzysta. Aby dowiedzieć się, jak opublikować aplikację konsolową, zobacz wcześniejszy samouczek z tej serii: