Aracılığıyla paylaş


Birim testi ekleme

ViewModel'leriniz ve hizmetleriniz ayrı bir sınıf kitaplığında olduğuna göre, birim testlerini kolayca oluşturabilirsiniz. Birim testi projeleri eklemek, ViewModel'lerinizin ve hizmetlerinizin kullanıcı arabirimi katmanına veya el ile teste bağlı kalmadan beklendiği gibi davrandığını doğrulamanıza olanak tanır. Birim testlerini geliştirme iş akışınızın bir parçası olarak otomatik olarak çalıştırarak kodunuzun güvenilir ve sürdürülebilir kalmasını sağlayabilirsiniz.

Birim testi projesi oluşturma

  1. Çözüm Gezgini'nde çözüme sağ tıklayın.
  2. Yeni Proje Ekle...'> seçin.
  3. WinUI Birim Testi Uygulaması şablonunu seçin ve İleri'yi seçin.
  4. Proje'yi WinUINotes.Tests adlandırın ve 'i seçerek'yi oluşturun.

Proje referansları ekleme

  1. WinUINotes.Tests projesine sağ tıklayın veProje Başvurusu Ekle...'> seçin.
  2. WinUINotes.Bus projesini denetleyin ve Tamam'ı seçin.

Test için sahte uygulamalar oluşturma

Test etmek için, gerçekten diske yazmayan dosya hizmeti ve depolama sınıflarının sahte uygulamalarını oluşturun. Sahteler, test amacıyla gerçek bağımlılıkların davranışını simüle eden basit uygulamalardır.

  1. WinUINotes.Tests projesinde Fakes adlı yeni bir klasör oluşturun.

  2. Fakes klasörüne bir sınıf dosyası FakeFileService.cs ekleyin:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Windows.Storage;
    using WinUINotes.Services;
    
    namespace WinUINotes.Tests.Fakes
    {
        internal class FakeFileService : IFileService
        {
            private Dictionary<string, string> fileStorage = [];
    
            public async Task CreateOrUpdateFileAsync(string filename, string contents)
            {
                if (fileStorage.ContainsKey(filename))
                {
                    fileStorage[filename] = contents;
                }
                else
                {
                    fileStorage.Add(filename, contents);
                }
    
                await Task.Delay(10); // Simulate some async work
            }
    
            public async Task DeleteFileAsync(string filename)
            {
                if (fileStorage.ContainsKey(filename))
                {
                    fileStorage.Remove(filename);
                }
    
                await Task.Delay(10); // Simulate some async work
            }
    
            public bool FileExists(string filename)
            {
                if (string.IsNullOrEmpty(filename))
                {
                    throw new ArgumentException("Filename cannot be null or empty", nameof(filename));
                }
    
                if (fileStorage.ContainsKey(filename))
                {
                    return true;
                }
    
                return false;
            }
    
            public IStorageFolder GetLocalFolder()
            {
                return new FakeStorageFolder(fileStorage);
            }
    
            public async Task<IReadOnlyList<IStorageItem>> GetStorageItemsAsync()
            {
                await Task.Delay(10);
                return GetStorageItemsInternal();
            }
    
            public async Task<IReadOnlyList<IStorageItem>> GetStorageItemsAsync(IStorageFolder storageFolder)
            {
                await Task.Delay(10);
                return GetStorageItemsInternal();
            }
    
            private IReadOnlyList<IStorageItem> GetStorageItemsInternal()
            {
                return fileStorage.Keys.Select(filename => CreateFakeStorageItem(filename)).ToList();
            }
    
            private IStorageItem CreateFakeStorageItem(string filename)
            {
                return new FakeStorageFile(filename);
            }
    
            public async Task<string> GetTextFromFileAsync(IStorageFile file)
            {
                await Task.Delay(10);
    
                if (fileStorage.ContainsKey(file.Name))
                {
                    return fileStorage[file.Name];
                }
    
                return string.Empty;
            }
        }
    }
    

    , FakeFileService gerçek dosya sistemine dokunmadan dosya işlemlerinin benzetimini yapmak için bellek içi sözlüğü (fileStorage) kullanır. Önemli özellikler şunlardır:

    • Asenkron simülasyon: Gerçek asenkron dosya işlemlerini taklit etmek için Task.Delay(10) kullanılır.
    • Doğrulama: Gerçek uygulama gibi geçersiz girişler için özel durumlar oluşturur
    • Sahte depolama sınıfları ile tümleştirme: Windows Depolama API'sinin benzetimini yapmak için birlikte çalışan FakeStorageFolder ve FakeStorageFile örneklerini döndürür.
  3. Ekle FakeStorageFolder.cs:

    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices.WindowsRuntime;
    using Windows.Foundation;
    using Windows.Storage;
    using Windows.Storage.FileProperties;
    using Windows.Storage.Search;
    
    namespace WinUINotes.Tests.Fakes
    {
        internal class FakeStorageFolder : IStorageFolder
        {
            private string name;
            private Dictionary<string, string> fileStorage = [];
    
            public FakeStorageFolder(Dictionary<string, string> files)
            {
                fileStorage = files;
            }
    
            public FileAttributes Attributes => throw new NotImplementedException();
            public DateTimeOffset DateCreated => throw new NotImplementedException();
            public string Name => name;
            public string Path => throw new NotImplementedException();
    
            public IAsyncOperation<StorageFile> CreateFileAsync(string desiredName)
            {
                throw new NotImplementedException();
            }
    
            public IAsyncOperation<StorageFile> CreateFileAsync(string desiredName, CreationCollisionOption options)
            {
                throw new NotImplementedException();
            }
    
            public IAsyncOperation<StorageFolder> CreateFolderAsync(string desiredName)
            {
                throw new NotImplementedException();
            }
    
            // Only partial implementation shown for brevity
            ...
        }
    }
    

    Bu nesne, oluşturucusunda dosya depolama sözlüğü alır ve böylece FakeFileService ile aynı bellek içi dosya sistemiyle çalışabilmesini sağlar. Çoğu arabirim üyesi, yalnızca testler tarafından gerçekten kullanılan özelliklerin ve metotların uygulanması gerektiğinden NotImplementedException fırlatır.

    Uygulamasının tamamını FakeStorageFolder bu öğretici için GitHub kod deposunda görüntüleyebilirsiniz.

  4. Ekle FakeStorageFile.cs:

    using System;
    using System.IO;
    using System.Runtime.InteropServices.WindowsRuntime;
    using Windows.Foundation;
    using Windows.Storage;
    using Windows.Storage.FileProperties;
    using Windows.Storage.Streams;
    
    namespace WinUINotes.Tests.Fakes
    {
        public class FakeStorageFile : IStorageFile
        {
            private string name;
    
            public FakeStorageFile(string name)
            {
                this.name = name;
            }
    
            public string ContentType => throw new NotImplementedException();
            public string FileType => throw new NotImplementedException();
            public FileAttributes Attributes => throw new NotImplementedException();
            public DateTimeOffset DateCreated => throw new NotImplementedException();
            public string Name => name;
            public string Path => throw new NotImplementedException();
    
            public IAsyncOperation<StorageFile> CopyAsync(IStorageFolder destinationFolder)
            {
                throw new NotImplementedException();
            }
    
            public IAsyncOperation<StorageFile> CopyAsync(IStorageFolder destinationFolder, string desiredNewName)
            {
                throw new NotImplementedException();
            }
    
            public IAsyncOperation<StorageFile> CopyAsync(IStorageFolder destinationFolder, string desiredNewName, NameCollisionOption option)
            {
                throw new NotImplementedException();
            }
    
            public IAsyncAction CopyAndReplaceAsync(IStorageFile fileToReplace)
            {
                throw new NotImplementedException();
            }
    
            // Only partial implementation shown for brevity
            ...
        }
    }
    

    sahte FakeStorageFile depolama sistemindeki tek tek dosyaları temsil eder. Dosya adını depolar ve testler için gereken en düşük uygulamayı sağlar. FakeStorageFolder gibi, yalnızca test edilen kod tarafından gerçekten kullanılan üyeleri uygular.

    Uygulamasının tamamını FakeStorageFolder bu öğretici için GitHub kod deposunda görüntüleyebilirsiniz.

Belgelerde daha fazla bilgi edinin:

Basit bir birim testi yazma

  1. UnitTest1.cs şunu NoteTests.cs olarak yeniden adlandırın ve güncelleştirin.

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System;
    using WinUINotes.Tests.Fakes;
    
    namespace WinUINotes.Tests
    {
        [TestClass]
        public partial class NoteTests
        {
            [TestMethod]
            public void TestCreateUnsavedNote()
            {
                var noteVm = new ViewModels.NoteViewModel(new FakeFileService());
                Assert.IsNotNull(noteVm);
                Assert.IsTrue(noteVm.Date > DateTime.Now.AddHours(-1));
                Assert.IsTrue(noteVm.Filename.EndsWith(".txt"));
                Assert.IsTrue(noteVm.Filename.StartsWith("notes"));
                noteVm.Text = "Sample Note";
                Assert.AreEqual("Sample Note", noteVm.Text);
                noteVm.SaveCommand.Execute(null);
                Assert.AreEqual("Sample Note", noteVm.Text);
            }
        }
    }
    

    Bu test, FakeFileService kullanarak NoteViewModel birim testinin nasıl yapılacağını gösterir. Test yeni bir NoteViewModel oluşturur, ilk durumunu denetler (tarih yenidir, dosya adının beklenen desene uyup uymadığını kontrol eder), notta metni ayarlar, kaydetme komutunu çalıştırır ve metnin kaydedildiğini doğrular. Sahte dosya hizmeti gerçek uygulama yerine kullanıldığından, test herhangi bir gerçek dosya G/Ç olmadan hızlı bir şekilde çalışır ve yan etkileri olmadan tekrar tekrar çalıştırılabilir.

Belgelerde daha fazla bilgi edinin:

Testleri çalıştırma

  1. Visual Studio'da Test Gezgini penceresini açın (Test>Test Gezgini).
  2. Birim testinizi yürütmek için Tüm Testleri Çalıştır'ı seçin.
  3. Testin geçtiğini doğrulayın.

Artık ViewModel'lerinizi ve hizmetlerinizi kullanıcı arabiriminden bağımsız olarak test edebilirsiniz!

Özet

Bu öğretici serisinde şunların nasıl yapılacağını öğrendiniz:

  • ViewModel'lerinizi ve hizmetlerinizi tutmak için ayrı bir sınıf kitaplığı projesi (Bus projesi) oluşturun ve birim testini kullanıcı arabirimi katmanından ayrı olarak etkinleştirin.
  • MVVM Araç Seti'ni kullanarak, özniteliklerinden (ObservableObject, [ObservableProperty]) ve [RelayCommand] yararlanarak boş kodu azaltmak için MVVM modelini uygulayın.
  • Özellik değişikliği bildirimlerini ve komut uygulamalarını otomatik olarak oluşturmak için kaynak oluşturucuları kullanın.
  • Özellik değerleri değiştiğinde komut kullanılabilirliğini otomatik olarak güncelleştirmek için kullanın [NotifyCanExecuteChangedFor] .
  • Microsoft.Extensions.DependencyInjection kullanarak bağımlılık enjeksiyonunu entegre edin ve ViewModel'lerin ve hizmetlerin yaşam döngüsünü yönetin.
  • Dosya işlemlerini test edilebilir bir şekilde işlemek için bir IFileService arabirim ve uygulama oluşturun.
  • Sayfalarınızda, App.xaml.cs'de DI kapsayıcısını yapılandırın ve hizmet sağlayıcısından ViewModel'leri alın.
  • Bileşenler arasında gevşek bağlantı sağlamak için WeakReferenceMessenger öğesini uygulayın, böylece sayfalar doğrudan referanslar olmaksızın ViewModel olaylarına yanıt verebilir.
  • Bileşenler arasında veri taşımak için ValueChangedMessage<T> sınıfından devralan ileti sınıfları oluşturun.
  • Gerçek dosya sistemine dokunmadan test için sahte bağımlılık uygulamaları oluşturun.
  • ViewModel davranışını kullanıcı arabirimi katmanından bağımsız olarak doğrulamak için MSTest kullanarak birim testleri yazın.

Bu mimari, kullanıcı arabirimi, iş mantığı ve veri erişim katmanları arasındaki endişelerin net ayrımı ile sürdürülebilir, test edilebilir WinUI uygulamaları oluşturmak için sağlam bir temel sağlar. Bu öğreticinin kodunu GitHub deposundan indirebilir veya görüntüleyebilirsiniz.

Sonraki Adımlar

MVVM Araç Seti ve bağımlılık ekleme ile MVVM'yi nasıl uygulayabileceğinizi anladığınıza göre, daha gelişmiş konuları keşfedebilirsiniz:

  • Gelişmiş Mesajlaşma: Seçmeli ileti işleme için istek/yanıt iletileri ve ileti belirteçleri de dahil olmak üzere ek mesajlaşma düzenlerini keşfedin.
  • Doğrulama: Veri ek açıklamalarını ve MVVM Araç Seti'nin doğrulama özelliklerini kullanarak ViewModel'lerinize giriş doğrulaması ekleyin.
  • Zaman Uyumsuz Komutlar: ile AsyncRelayCommandzaman uyumsuz komut yürütme, iptal desteği ve ilerleme durumu raporlaması hakkında daha fazla bilgi edinin.
  • Gelişmiş Test: İleti işleme, zaman uyumsuz komut yürütme ve özellik değişikliği bildirimlerini test etme gibi daha gelişmiş test senaryolarını keşfedin.
  • Gözlemlenebilir Koleksiyonlar: Toplu işlemler için ObservableRangeCollection<T> keşfedin ve ObservableCollection<T>'i etkili bir şekilde kullanın.