Bagikan melalui


Pengujian Unit

Tip

Konten ini adalah kutipan dari eBook, Pola Aplikasi Perusahaan Menggunakan .NET MAUI, tersedia di .NET Docs atau sebagai PDF gratis yang dapat diunduh yang dapat dibaca secara offline.

Pola Aplikasi Perusahaan Menggunakan thumbnail sampul .NET MAUI eBook.

Aplikasi multi-platform mengalami masalah yang mirip dengan aplikasi desktop dan berbasis web. Pengguna seluler akan berbeda dengan perangkat mereka, konektivitas jaringan, ketersediaan layanan, dan berbagai faktor lainnya. Oleh karena itu, aplikasi multi-platform harus diuji karena akan digunakan di dunia nyata untuk meningkatkan kualitas, keandalan, dan performa mereka. Banyak jenis pengujian harus dilakukan pada aplikasi, termasuk pengujian unit, pengujian integrasi, dan pengujian antarmuka pengguna. Pengujian unit adalah bentuk yang paling umum dan penting untuk membangun aplikasi berkualitas tinggi.

Pengujian unit mengambil unit kecil aplikasi, biasanya metode, mengisolasinya dari sisa kode, dan memverifikasi bahwa itu bersifat seperti yang diharapkan. Tujuannya adalah untuk memeriksa bahwa setiap unit fungsionalitas berfungsi seperti yang diharapkan, sehingga kesalahan tidak menyebar ke seluruh aplikasi. Mendeteksi bug di mana itu terjadi lebih efisien daripada mengamati efek bug secara tidak langsung pada titik kegagalan sekunder.

Pengujian unit memiliki efek paling signifikan pada kualitas kode ketika merupakan bagian integral dari alur kerja pengembangan perangkat lunak. Pengujian unit dapat bertindak sebagai dokumentasi desain dan spesifikasi fungsi untuk aplikasi. Segera setelah metode ditulis, pengujian unit harus ditulis yang memverifikasi perilaku metode sebagai respons terhadap kasus data standar, batas, dan input yang salah dan memeriksa asumsi eksplisit atau implisit yang dibuat oleh kode. Atau, dengan pengembangan berbasis pengujian, pengujian unit ditulis sebelum kode. Untuk informasi selengkapnya tentang pengembangan berbasis pengujian dan cara menerapkannya, lihat Walkthrough: Pengembangan berbasis pengujian menggunakan Test Explorer..

Catatan

Pengujian unit sangat efektif terhadap regresi. Artinya, fungsionalitas yang digunakan untuk bekerja, tetapi telah terganggu oleh pembaruan yang rusak.

Pengujian unit biasanya menggunakan pola arrange-act-assert:

Langkah Deskripsi
Atur Menginisialisasi objek dan mengatur nilai data yang diteruskan ke metode di bawah pengujian.
Bertindak Memanggil metode di bawah pengujian dengan argumen yang diperlukan.
Assert Memverifikasi bahwa tindakan metode yang sedang diuji berulah seperti yang diharapkan.

Pola ini memastikan bahwa pengujian unit dapat dibaca, digambarkan sendiri, dan konsisten.

Injeksi dependensi dan pengujian unit

Salah satu motivasi untuk mengadopsi arsitektur yang digabungkan secara longgar adalah memfasilitasi pengujian unit. Salah satu jenis yang terdaftar dengan layanan injeksi dependensi adalah IAppEnvironmentService antarmuka. Contoh kode berikut menunjukkan kerangka kelas ini:

public class OrderDetailViewModel : ViewModelBase
{
    private IAppEnvironmentService _appEnvironmentService;

    public OrderDetailViewModel(
        IAppEnvironmentService appEnvironmentService,
        IDialogService dialogService, INavigationService navigationService, ISettingsService settingsService)
        : base(dialogService, navigationService, settingsService)
    {
        _appEnvironmentService = appEnvironmentService;
    }
}

Kelas OrderDetailViewModel memiliki dependensi pada IAppEnvironmentService jenis, yang diselesaikan kontainer injeksi dependensi saat membuat instans OrderDetailViewModel objek. Namun, daripada membuat IAppEnvironmentService objek yang menggunakan server, perangkat, dan konfigurasi nyata untuk menguji OrderDetailViewModel kelas secara unit, sebagai gantinya, ganti IAppEnvironmentService objek dengan objek tiruan untuk tujuan pengujian. Objek tiruan adalah objek yang memiliki tanda tangan objek atau antarmuka yang sama, tetapi dibuat dengan cara tertentu untuk membantu pengujian unit. Ini sering digunakan dengan injeksi dependensi untuk menyediakan implementasi antarmuka tertentu untuk menguji skenario data dan alur kerja yang berbeda.

Pendekatan ini memungkinkan IAppEnvironmentService objek untuk diteruskan ke OrderDetailViewModel kelas pada runtime, dan demi kepentingan uji coba, memungkinkan kelas tiruan untuk diteruskan ke kelas pada OrderDetailViewModel waktu pengujian. Keuntungan utama dari pendekatan ini adalah memungkinkan pengujian unit dijalankan tanpa memerlukan sumber daya yang berat seperti fitur platform runtime, layanan web, atau database.

Menguji aplikasi MVVM

Menguji model dan melihat model dari aplikasi MVVM identik dengan menguji kelas lain, dan menggunakan alat dan teknik yang sama; ini termasuk fitur seperti pengujian unit dan tiruan. Namun, beberapa pola yang khas untuk memodelkan dan melihat kelas model dapat memperoleh manfaat dari teknik pengujian unit tertentu.

Tip

Uji satu hal dengan setiap pengujian unit. Ketika kompleksitas pengujian meluas, itu membuat verifikasi pengujian itu lebih sulit. Dengan membatasi pengujian unit untuk satu kekhawatiran, kami dapat memastikan bahwa pengujian kami lebih berulang, terisolasi, dan memiliki waktu eksekusi yang lebih kecil. Lihat Praktik terbaik pengujian unit dengan .NET untuk praktik terbaik lainnya.

Jangan tergoda untuk membuat latihan pengujian unit lebih dari satu aspek perilaku unit. Melakukannya mengarah pada pengujian yang sulit dibaca dan diperbarui. Ini juga dapat menyebabkan kebingungan saat menafsirkan kegagalan.

Aplikasi multi-platform eShop menggunakan MSTest untuk melakukan pengujian unit, yang mendukung dua jenis pengujian unit yang berbeda:

Jenis Pengujian Atribut Deskripsi
TestMethod TestMethod Menentukan metode pengujian aktual yang akan dijalankan.
DataSource DataSource Pengujian yang hanya berlaku untuk sekumpulan data tertentu.

Pengujian unit yang disertakan dengan aplikasi multi-platform eShop adalah TestMethod, sehingga setiap metode pengujian unit dihiasi dengan TestMethod atribut . Selain MSTest ada beberapa kerangka kerja pengujian lain yang tersedia termasuk NUnit dan xUnit.

Menguji fungsionalitas asinkron

Saat menerapkan pola MVVM, lihat model biasanya memanggil operasi pada layanan, seringkali secara asinkron. Pengujian untuk kode yang memanggil operasi ini biasanya menggunakan tiruan sebagai pengganti layanan aktual. Contoh kode berikut menunjukkan pengujian fungsionalitas asinkron dengan meneruskan layanan tiruan ke dalam model tampilan:

[TestMethod]
public async Task OrderPropertyIsNotNullAfterViewModelInitializationTest()
{
    // Arrange
    var orderService = new OrderMockService();
    var orderViewModel = new OrderDetailViewModel(orderService);

    // Act
    var order = await orderService.GetOrderAsync(1, GlobalSetting.Instance.AuthToken);
    await orderViewModel.InitializeAsync(order);

    // Assert
    Assert.IsNotNull(orderViewModel.Order);
}

Pengujian unit ini memeriksa bahwa Order properti OrderDetailViewModel instans akan memiliki nilai setelah InitializeAsync metode dipanggil. Metode InitializeAsync ini dipanggil saat tampilan terkait model tampilan dinavigasi. Untuk informasi selengkapnya tentang navigasi, lihat Navigasi.

OrderDetailViewModel Saat instans dibuat, instans IOrderService akan ditentukan sebagai argumen. Namun, mengambil OrderService data dari layanan web. Oleh karena itu, OrderMockService instans, versi tiruan kelas OrderService , ditentukan sebagai argumen ke OrderDetailViewModel konstruktor. Kemudian, data tiruan diambil daripada berkomunikasi dengan layanan web ketika metode model InitializeAsync tampilan dipanggil, yang menggunakan IOrderService operasi.

Menguji implementasi INotifyPropertyChanged

INotifyPropertyChanged Menerapkan antarmuka memungkinkan tampilan bereaksi terhadap perubahan yang berasal dari model tampilan dan model. Perubahan ini tidak terbatas pada data yang ditampilkan dalam kontrol -- perubahan tersebut juga digunakan untuk mengontrol tampilan, seperti melihat status model yang menyebabkan animasi dimulai atau kontrol dinonaktifkan.

Properti yang dapat diperbarui langsung oleh pengujian unit dapat diuji dengan melampirkan penanganan aktivitas ke PropertyChanged peristiwa dan memeriksa apakah peristiwa dinaikkan setelah menetapkan nilai baru untuk properti. Contoh kode berikut menunjukkan pengujian seperti itu:

[TestMethod]
public async Task SettingOrderPropertyShouldRaisePropertyChanged()
{
    var invoked = false;
    var orderService = new OrderMockService();
    var orderViewModel = new OrderDetailViewModel(orderService);

    orderViewModel.PropertyChanged += (sender, e) =>
    {
        if (e.PropertyName.Equals("Order"))
            invoked = true;
    };
    var order = await orderService.GetOrderAsync(1, GlobalSetting.Instance.AuthToken);
    await orderViewModel.InitializeAsync(order);

    Assert.IsTrue(invoked);
}

Pengujian unit ini memanggil InitializeAsync metode OrderViewModel kelas, yang menyebabkan propertinya Order diperbarui. Pengujian unit akan lulus, asalkan PropertyChanged peristiwa dinaikkan untuk Order properti.

Menguji komunikasi berbasis pesan

Lihat model yang menggunakan MessagingCenter kelas untuk berkomunikasi antara kelas yang digabungkan secara longgar dapat diuji unit dengan berlangganan pesan yang dikirim oleh kode di bawah pengujian, seperti yang ditunjukkan dalam contoh kode berikut:

[TestMethod]
public void AddCatalogItemCommandSendsAddProductMessageTest()
{
    var messageReceived = false;
    var catalogService = new CatalogMockService();
    var catalogViewModel = new CatalogViewModel(catalogService);

    MessagingCenter.Subscribe<CatalogViewModel, CatalogItem>(
        this, MessageKeys.AddProduct, (sender, arg) =>
    {
        messageReceived = true;
    });
    catalogViewModel.AddCatalogItemCommand.Execute(null);

    Assert.IsTrue(messageReceived);
}

Pengujian unit ini memeriksa bahwa CatalogViewModel menerbitkan AddProduct pesan sebagai respons terhadap pesan AddCatalogItemCommand yang dijalankan. MessagingCenter Karena kelas mendukung langganan pesan multicast, pengujian unit dapat berlangganan AddProduct pesan dan menjalankan delegasi panggilan balik sebagai respons untuk menerimanya. Delegasi panggilan balik ini, yang ditentukan sebagai ekspresi lambda, menetapkan bidang boolean yang digunakan oleh Assert pernyataan untuk memverifikasi perilaku pengujian.

Menguji penanganan pengecualian

Pengujian unit juga dapat ditulis bahwa periksa apakah pengecualian tertentu dilemparkan untuk tindakan atau input yang tidak valid, seperti yang ditunjukkan dalam contoh kode berikut:

[TestMethod]
public void InvalidEventNameShouldThrowArgumentExceptionText()
{
    var behavior = new MockEventToCommandBehavior
    {
        EventName = "OnItemTapped"
    };
    var listView = new ListView();

    Assert.Throws<ArgumentException>(() => listView.Behaviors.Add(behavior));
}

Pengujian unit ini akan melemparkan pengecualian karena ListView kontrol tidak memiliki peristiwa bernama OnItemTapped. Metode Assert.Throws<T> ini adalah metode generik di mana T adalah jenis pengecualian yang diharapkan. Argumen yang diteruskan ke Assert.Throws<T> metode adalah ekspresi lambda yang akan melemparkan pengecualian. Oleh karena itu, pengujian unit akan lulus asalkan ekspresi lambda melempar ArgumentException.

Tip

Hindari menulis pengujian unit yang memeriksa string pesan pengecualian. String pesan pengecualian mungkin berubah dari waktu ke waktu, sehingga pengujian unit yang mengandalkan kehadirannya dianggap rapuh.

Validasi pengujian

Ada dua aspek untuk menguji implementasi validasi: menguji bahwa aturan validasi apa pun diimplementasikan dengan benar dan pengujian yang dilakukan kelas seperti yang ValidatableObject<T> diharapkan.

Logika validasi biasanya mudah diuji, karena biasanya merupakan proses mandiri di mana output tergantung pada input. Harus ada pengujian pada hasil pemanggilan Validate metode pada setiap properti yang memiliki setidaknya satu aturan validasi terkait, seperti yang ditunjukkan dalam contoh kode berikut:

[TestMethod]
public void CheckValidationPassesWhenBothPropertiesHaveDataTest()
{
    var mockViewModel = new MockViewModel();
    mockViewModel.Forename.Value = "John";
    mockViewModel.Surname.Value = "Smith";

    var isValid = mockViewModel.Validate();

    Assert.IsTrue(isValid);
}

Pengujian unit ini memeriksa bahwa validasi berhasil ketika dua ValidatableObject<T> properti dalam MockViewModel instans keduanya memiliki data.

Selain memeriksa bahwa validasi berhasil, pengujian unit validasi juga harus memeriksa nilai Valueproperti , , IsValiddan Errors dari setiap ValidatableObject<T> instans, untuk memverifikasi bahwa kelas berfungsi seperti yang diharapkan. Contoh kode berikut menunjukkan pengujian unit yang melakukan ini:

[TestMethod]
public void CheckValidationFailsWhenOnlyForenameHasDataTest()
{
    var mockViewModel = new MockViewModel();
    mockViewModel.Forename.Value = "John";

    bool isValid = mockViewModel.Validate();

    Assert.IsFalse(isValid);
    Assert.IsNotNull(mockViewModel.Forename.Value);
    Assert.IsNull(mockViewModel.Surname.Value);
    Assert.IsTrue(mockViewModel.Forename.IsValid);
    Assert.IsFalse(mockViewModel.Surname.IsValid);
    Assert.AreEqual(mockViewModel.Forename.Errors.Count(), 0);
    Assert.AreNotEqual(mockViewModel.Surname.Errors.Count(), 0);
}

Pengujian unit ini memeriksa bahwa validasi gagal ketika Surname properti MockViewModel tidak memiliki data apa pun, dan Valueproperti , , IsValiddan Errors dari setiap ValidatableObject<T> instans diatur dengan benar.

Ringkasan

Pengujian unit mengambil unit kecil aplikasi, biasanya metode, mengisolasinya dari sisa kode, dan memverifikasi bahwa itu bersifat seperti yang diharapkan. Tujuannya adalah untuk memeriksa bahwa setiap unit fungsionalitas berfungsi seperti yang diharapkan, sehingga kesalahan tidak menyebar ke seluruh aplikasi.

Perilaku objek yang sedang diuji dapat diisolasi dengan mengganti objek dependen dengan objek tiruan yang mensimulasikan perilaku objek dependen. Ini memungkinkan pengujian unit dijalankan tanpa memerlukan sumber daya yang tidak berat seperti fitur platform runtime, layanan web, atau database

Menguji model dan melihat model dari aplikasi MVVM identik dengan menguji kelas lain, dan alat dan teknik yang sama dapat digunakan.