Panduan: Membuat dan menjalankan pengujian unit untuk kode terkelola

Artikel ini memandu Anda membuat, menjalankan, dan menyesuaikan serangkaian pengujian unit menggunakan kerangka kerja pengujian unit Microsoft untuk kode terkendali dan Test Explorer Visual Studio. Anda mulai dengan proyek C# yang sedang dalam pengembangan, membuat pengujian yang menjalankan kodenya, menjalankan pengujian, dan memeriksa hasilnya. Lalu Anda mengubah kode proyek dan menjalankan ulang pengujian. Jika Anda ingin ringkasan konseptual tugas-tugas ini sebelum melalui langkah-langkah ini, lihat Dasar-dasar pengujian unit.

Membuat proyek untuk diuji

  1. Buka Visual Studio.

  2. Dari jendela awal, pilih Buat proyek baru.

  3. Cari dan pilih templat proyek Aplikasi Konsol C# untuk .NET, lalu klik Berikutnya.

    Catatan

    Jika tidak melihat templat Aplikasi Konsol, Anda dapat menginstalnya dari jendela Buat proyek baru. Di pesan Tidak menemukan apa yang Anda cari?, pilih link Instal alat dan fitur lain. Kemudian, di Alat Penginstal Visual Studio, pilih beban kerja Pengembangan desktop .NET.

  4. Beri nama proyek Bank, lalu klik Berikutnya.

    Pilih kerangka kerja target yang direkomendasikan atau .NET 8, lalu pilih Buat.

    Proyek Bank dibuat dan ditampilkan dalam Penjelajah Solusi dengan file Program.cs terbuka di editor kode.

    Catatan

    Jika Program.cs tidak terbuka di editor, klik dua kali file Program.cs di Penjelajah Solusi untuk membukanya.

  5. Ganti isi Program.cs dengan kode C# berikut yang menentukan kelas, BankAccount:

    using System;
    
    namespace BankAccountNS
    {
        /// <summary>
        /// Bank account demo class.
        /// </summary>
        public class BankAccount
        {
            private readonly string m_customerName;
            private double m_balance;
    
            private BankAccount() { }
    
            public BankAccount(string customerName, double balance)
            {
                m_customerName = customerName;
                m_balance = balance;
            }
    
            public string CustomerName
            {
                get { return m_customerName; }
            }
    
            public double Balance
            {
                get { return m_balance; }
            }
    
            public void Debit(double amount)
            {
                if (amount > m_balance)
                {
                    throw new ArgumentOutOfRangeException("amount");
                }
    
                if (amount < 0)
                {
                    throw new ArgumentOutOfRangeException("amount");
                }
    
                m_balance += amount; // intentionally incorrect code
            }
    
            public void Credit(double amount)
            {
                if (amount < 0)
                {
                    throw new ArgumentOutOfRangeException("amount");
                }
    
                m_balance += amount;
            }
    
            public static void Main()
            {
                BankAccount ba = new BankAccount("Mr. Bryan Walton", 11.99);
    
                ba.Credit(5.77);
                ba.Debit(11.22);
                Console.WriteLine("Current balance is ${0}", ba.Balance);
            }
        }
    }
    
  6. Ubah nama file menjadi BankAccount.cs dengan mengeklik kanan dan memilih Ubah Nama di Penjelajah Solusi.

  7. Pada menu Build, klik Build Solusi (atau tekan Ctrl + SHIFT + B).

Anda sekarang memiliki proyek dengan metode yang dapat Anda uji. Dalam artikel ini, pengujian berfokus pada metode Debit. Metode Debit dipanggil saat uang ditarik dari akun.

Membuat proyek pengujian unit

  1. Pada menu File, pilih Tambahkan>Proyek Baru.

    Tip

    Anda juga dapat mengeklik kanan solusi di Penjelajah Solusi dan memilih Tambahkan>Proyek Baru.

  2. Ketik pengujian di kotak pencarian, pilih C# sebagai bahasa, lalu pilih C# MSTest Unit Test Project untuk templat .NET, lalu klik Berikutnya.

    Catatan

    Di Visual Studio 2019 versi 16.9, templat proyek MSTest adalah Proyek Uji Unit.

  3. Beri nama proyek BankTests dan klik Berikutnya.

  4. Pilih kerangka kerja target yang direkomendasikan atau .NET 8, lalu pilih Buat.

    Proyek BankTests ditambahkan ke solusi Bank.

  5. Dalam proyek BankTests, tambahkan referensi ke proyek Bank.

    Di Penjelajah Solusi, pilih Dependensi di bawah proyek BankTests lalu pilih Tambahkan Referensi (atau Tambahkan Referensi Proyek) dari menu klik kanan.

  6. Di kotak dialog Pengelola Referensi, luaskan Proyek, pilih Solusi, lalu centang item Bank.

  7. Pilih OK.

Membuat kelas pengujian

Buat kelas pengujian untuk memverifikasi kelas BankAccount. Anda dapat menggunakan file UnitTest1.cs yang dihasilkan oleh templat proyek, tetapi beri nama file dan kelas yang lebih deskriptif.

Mengubah nama file dan kelas

  1. Untuk mengubah nama file, di Penjelajah Solusi, pilih file UnitTest1.cs di proyek BankTests. Dari menu klik kanan, pilih Ubah nama (atau tekan F2), lalu ubah nama file menjadi BankAccountTests.cs.

  2. Untuk mengubah nama kelas, posisikan kursor pada UnitTest1 di editor kode, klik kanan, lalu pilih Ubah nama (atau tekan F2). Ketik BankAccountTests lalu tekan Enter.

File BankAccountTests.cs sekarang berisi kode berikut:

// The 'using' statement for Test Tools is in GlobalUsings.cs
// using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace BankTests
{
    [TestClass]
    public class BankAccountTests
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
}

Menambahkan pernyataan penggunaan

Tambahkan using pernyataan ke kelas pengujian agar dapat dipanggil ke proyek yang sedang diuji tanpa menggunakan nama yang sepenuhnya memenuhi syarat. Di bagian atas file kelas, tambahkan:

using BankAccountNS;

Persyaratan kelas pengujian

Persyaratan minimum untuk kelas pengujian adalah:

  • Atribut [TestClass] diperlukan pada setiap kelas yang berisi metode pengujian unit yang ingin Anda jalankan di Test Explorer.

  • Setiap metode pengujian yang ingin Anda kenali oleh Test Explorer harus memiliki atribut [TestMethod].

Anda dapat memiliki kelas lain dalam proyek pengujian unit yang tidak memiliki atribut [TestClass], dan Anda dapat memiliki metode lain di kelas pengujian yang tidak memiliki atribut [TestMethod]. Anda dapat memanggil kelas dan metode lain ini dari metode pengujian Anda.

Membuat metode pengujian pertama

Dalam prosedur ini, Anda menulis metode pengujian unit untuk memverifikasi perilaku Debit metode BankAccount kelas.

Setidaknya ada tiga perilaku yang perlu diperiksa:

Tip

Anda dapat menghapus metode TestMethod1 default, karena Anda tidak akan menggunakannya dalam panduan ini.

Untuk membuat metode pengujian

Pengujian pertama memverifikasi bahwa jumlah yang valid (yaitu, yang kurang dari saldo akun dan lebih besar dari nol) menarik jumlah yang benar dari akun. Tambahkan metode berikut ke kelas BankAccountTests itu:

[TestMethod]
public void Debit_WithValidAmount_UpdatesBalance()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = 4.55;
    double expected = 7.44;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act
    account.Debit(debitAmount);

    // Assert
    double actual = account.Balance;
    Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly");
}

Metodenya sederhana: metode ini menyiapkan objek BankAccount baru dengan saldo awal lalu menarik jumlah yang valid. Ini menggunakan metode Assert.AreEqual untuk memverifikasi bahwa saldo akhir seperti yang diharapkan. Metode seperti Assert.AreEqual, Assert.IsTrue, dan lainnya sering digunakan dalam pengujian unit. Untuk informasi konseptual selengkapnya tentang menulis pengujian unit, lihat Menulis pengujian Anda.

Persyaratan metode pengujian

Metode pengujian harus memenuhi persyaratan berikut:

  • Metode dilengkapi dengan atribut [TestMethod].

  • Hal ini mengembalikan void.

  • Metode tidak dapat memiliki parameter.

Mem-build dan menjalankan pengujian

  1. Pada menu Build, pilih Build Solusi (atau tekan Ctrl + SHIFT + B).

  2. Jika Test Explorer tidak terbuka, buka dengan memilih Test>Explorer (atau Uji>Windows>Test Explorer) dari bilah menu atas (atau tekan Ctrl + E, T).

  3. Pilih Jalankan Semua untuk menjalankan pengujian (atau tekan Ctrl + R, V).

    Saat pengujian berjalan, bilah status di bagian atas jendela Test Explorer dianimasikan. Di akhir uji coba, bilah berubah menjadi hijau jika semua metode pengujian lulus, atau merah jika salah satu pengujian gagal.

    Dalam hal ini, pengujian gagal.

  4. Pilih metode di Test Explorer untuk melihat detail di bagian bawah jendela.

Memperbaiki kode Anda dan menjalankan ulang pengujian Anda

Hasil pengujian berisi pesan yang menjelaskan kegagalan. Anda mungkin perlu menelusuri paling detail untuk melihat pesan ini. Untuk metode AreEqual, pesan menampilkan apa yang diharapkan dan apa yang sebenarnya diterima. Anda mengharapkan saldo berkurang, tetapi malah bertambah dengan jumlah penarikan.

Pengujian unit telah menemukan bug: jumlah penarikan ditambahkan ke saldo akun ketika harus dikurangi.

Memperbaiki bug

Untuk memperbaiki kesalahan, dalam file BankAccount.cs, ganti baris:

m_balance += amount;

dengan:

m_balance -= amount;

Menjalankan ulang pengujian

Di Test Explorer, pilih Jalankan Semua untuk menjalankan ulang pengujian (atau tekan Ctrl + R, V). Bilah merah/hijau berubah menjadi hijau untuk menunjukkan bahwa pengujian lulus.

Test Explorer in Visual Studio 2019 showing passed test

Test Explorer in Visual Studio 2019 showing passed test

Menggunakan pengujian unit untuk meningkatkan kode Anda

Bagian ini menjelaskan bagaimana proses analisis berulang, pengembangan pengujian unit, dan pemfaktoran ulang dapat membantu Anda membuat kode produksi lebih kuat dan efektif.

Analisis data

Anda telah membuat metode pengujian untuk mengonfirmasi bahwa jumlah yang valid telah dipotong dengan benar dalam metode Debit. Sekarang, verifikasi bahwa metode tersebut memunculkan ArgumentOutOfRangeException jika jumlah debitnya adalah:

  • lebih besar dari saldo, atau
  • kurang dari nol.

Membuat dan menjalankan metode pengujian baru

Buat metode pengujian untuk memverifikasi perilaku yang benar ketika jumlah debit kurang dari nol:

[TestMethod]
public void Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = -100.00;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act and assert
    Assert.ThrowsException<System.ArgumentOutOfRangeException>(() => account.Debit(debitAmount));
}

Gunakan metode ThrowsException untuk menegaskan bahwa pengecualian yang benar telah dimunculkan. Metode ini menyebabkan pengujian gagal kecuali jika ArgumentOutOfRangeException dimunculkan. Jika Anda memodifikasi sementara metode yang sedang diuji untuk memunculkan ApplicationException yang lebih umum saat jumlah debit kurang dari nol, pengujian akan berjalan dengan benar—yaitu, gagal.

Untuk menguji kasus ketika jumlah yang ditarik lebih besar dari saldo, lakukan langkah-langkah berikut:

  1. Buat metode pengujian baru bernama Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange.

  2. Salin isi metode dari Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange ke metode baru.

  3. Atur debitAmount ke angka yang lebih besar dari saldo.

Jalankan dua pengujian dan verifikasi bahwa pengujian tersebut lulus.

Melanjutkan analisis

Metode yang diuji dapat ditingkatkan lebih lanjut. Dengan implementasi saat ini, kita tidak memiliki cara untuk mengetahui kondisi mana (amount > m_balance atau amount < 0) yang menyebabkan pengecualian dimunculkan selama pengujian. Kita hanya tahu bahwa ArgumentOutOfRangeException dimunculkan ke suatu tempat dalam metode ini. Akan lebih baik jika kita dapat mengetahui kondisi mana dalam BankAccount.Debit yang menyebabkan pengecualian dimunculkan (amount > m_balance atau amount < 0) sehingga kita dapat yakin bahwa metode memeriksa argumennya dengan benar.

Lihat metode yang sedang diuji (BankAccount.Debit) lagi, dan perhatikan bahwa kedua pernyataan kondisional menggunakan konstruktor ArgumentOutOfRangeException yang hanya menggunakan nama argumen sebagai parameter:

throw new ArgumentOutOfRangeException("amount");

Ada konstruktor yang dapat Anda gunakan yang melaporkan informasi yang jauh lebih kaya: ArgumentOutOfRangeException(String, Object, String) menyertakan nama argumen, nilai argumen, dan pesan yang ditentukan pengguna. Anda dapat merefaktor metode yang sedang diuji untuk menggunakan konstruktor ini. Lebih baik lagi, Anda dapat menggunakan anggota jenis yang tersedia untuk umum untuk menentukan kesalahan.

Refaktor kode yang sedang diuji

Pertama, tentukan dua konstanta untuk pesan kesalahan di cakupan kelas. Tempatkan definisi di kelas di bawah pengujian, BankAccount:

public const string DebitAmountExceedsBalanceMessage = "Debit amount exceeds balance";
public const string DebitAmountLessThanZeroMessage = "Debit amount is less than zero";

Lalu, ubah dua pernyataan kondisional dalam metode Debit:

if (amount > m_balance)
{
    throw new System.ArgumentOutOfRangeException("amount", amount, DebitAmountExceedsBalanceMessage);
}

if (amount < 0)
{
    throw new System.ArgumentOutOfRangeException("amount", amount, DebitAmountLessThanZeroMessage);
}

Refaktor metode pengujian

Refaktor metode pengujian dengan menghapus panggilan ke Assert.ThrowsException. Tutup panggilan ke Debit() dalam blok try/catch, temukan pengecualian spesifik yang diharapkan, dan verifikasi pesan terkaitnya. Metode Microsoft.VisualStudio.TestTools.UnitTesting.StringAssert.Contains menyediakan kemampuan untuk membandingkan dua string.

Sekarang, Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange mungkin terlihat seperti ini:

[TestMethod]
public void Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = 20.0;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act
    try
    {
        account.Debit(debitAmount);
    }
    catch (System.ArgumentOutOfRangeException e)
    {
        // Assert
        StringAssert.Contains(e.Message, BankAccount.DebitAmountExceedsBalanceMessage);
    }
}

Coba lagi, tulis ulang, dan analisis ulang

Saat ini, metode pengujian tidak menangani semua kasus yang seharusnya. Jika metode yang diuji, metode Debit, gagal memunculkan ArgumentOutOfRangeException ketika debitAmount lebih besar dari saldo (atau kurang dari nol), metode pengujian akan lulus. Skenario ini tidak baik karena Anda ingin metode pengujian gagal jika tidak ada pengecualian yang dilemparkan.

Hasil ini adalah bug dalam metode pengujian. Untuk mengatasi masalah ini, tambahkan pernyataan Assert.Fail di akhir metode pengujian untuk menangani kasus di mana tidak ada pengecualian yang dimunculkan.

Menjalankan ulang pengujian menunjukkan bahwa pengujian sekarang gagal jika pengecualian yang benar ditemukan. Blok catch menangkap pengecualian, tetapi metode terus dijalankan dan gagal pada pernyataan Assert.Fail baru. Untuk mengatasi masalah ini, tambahkan pernyataan return setelah StringAssert di blok catch. Menjalankan ulang pengujian mengonfirmasi bahwa Anda telah memperbaiki masalah ini. Versi akhir dari Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange terlihat seperti ini:

[TestMethod]
public void Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = 20.0;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act
    try
    {
        account.Debit(debitAmount);
    }
    catch (System.ArgumentOutOfRangeException e)
    {
        // Assert
        StringAssert.Contains(e.Message, BankAccount.DebitAmountExceedsBalanceMessage);
        return;
    }

    Assert.Fail("The expected exception was not thrown.");
}

Kesimpulan

Perbaikan pada kode pengujian menghasilkan metode pengujian yang lebih kuat dan informatif. Tetapi yang lebih penting, metode pengujian juga memperbaiki kode yang sedang diuji.

Tip

Panduan ini menggunakan kerangka kerja pengujian unit Microsoft untuk kode terkendali. Test Explorer juga dapat menjalankan pengujian dari kerangka kerja pengujian unit pihak ketiga yang memiliki adapter untuk Test Explorer. Untuk informasi selengkapnya, lihat Menginstal kerangka kerja pengujian unit pihak ketiga.

Untuk informasi tentang cara menjalankan pengujian dari baris perintah, lihat Opsi baris perintah VSTest.Console.exe.