Sdílet prostřednictvím


Unit Testing Enterprise Apps

Poznámka:

Tato elektronická kniha byla publikována na jaře roku 2017 a od té doby nebyla aktualizována. Existuje mnoho v knize, která zůstává cenná, ale některé materiály jsou zastaralé.

Mobilní aplikace mají jedinečné problémy, které se nemusí starat o desktopové a webové aplikace. Mobilní uživatelé se budou lišit podle zařízení, která používají, podle síťového připojení, dostupnosti služeb a řady dalších faktorů. Mobilní aplikace by proto měly být testovány tak, jak budou použity ve skutečném světě ke zlepšení jejich kvality, spolehlivosti a výkonu. Existuje mnoho typů testování, které by se mělo provádět v aplikaci, včetně testování částí, testování integrace a testování uživatelského rozhraní, přičemž testování částí je nejběžnější formou testování.

Test jednotek přijímá malou jednotku aplikace, obvykle metodu, izoluje ji od zbytku kódu a ověřuje, že se chová podle očekávání. Jejím cílem je zkontrolovat, že každá jednotka funkcí funguje podle očekávání, aby se chyby nešířily v celé aplikaci. Zjištění chyby, ve které k ní dochází, je efektivnější, když dochází k nepřímému výskytu chyby v sekundárním bodě selhání.

Testování částí má největší vliv na kvalitu kódu, pokud je nedílnou součástí pracovního postupu vývoje softwaru. Jakmile byla metoda zapsána, měly by být zapsány testy jednotek, které ověřují chování metody v reakci na standardní, hraniční a nesprávné případy vstupních dat a kontrolují explicitní nebo implicitní předpoklady provedené kódem. Alternativně při vývoji řízeném testem se testy jednotek zapisují před kódem. V tomto scénáři fungují testy jednotek jako dokumentace k návrhu i funkční specifikace.

Poznámka:

Testy jednotek jsou velmi efektivní proti regresi – to znamená funkce, které se používají k práci, ale byly narušeny chybnou aktualizací.

Testy jednotek obvykle používají model arrange-act-assert:

  • Oddíl uspořádání metody testu jednotek inicializuje objekty a nastaví hodnotu dat, která jsou předána metodě v rámci testu.
  • Oddíl act vyvolá metodu test s požadovanými argumenty.
  • Oddíl assert ověřuje, že akce metody v testu se chová podle očekávání.

Provedením tohoto modelu zajistíte, aby testy jednotek byly čitelné a konzistentní.

Injektáž závislostí a testování částí

Jednou z motivací k přijetí volně propojených architektur je, že usnadňuje testování jednotek. Jedním z typů registrovaných v autofacu OrderService je třída. Následující příklad kódu ukazuje osnovu této třídy:

public class OrderDetailViewModel : ViewModelBase  
{  
    private IOrderService _ordersService;  

    public OrderDetailViewModel(IOrderService ordersService)  
    {  
        _ordersService = ordersService;  
    }  
    ...  
}

Třída OrderDetailViewModel má závislost na IOrderService typu, který kontejner přeloží při vytvoření instance objektu OrderDetailViewModel . Místo vytvoření objektu OrderService pro testování OrderDetailViewModel třídy místo toho nahraďte OrderService objekt napodobenou pro účely testů. Tento vztah znázorňuje obrázek 10–1.

Třídy, které implementují rozhraní IOrderService

Obrázek 10-1: Třídy, které implementují rozhraní IOrderService

Tento přístup umožňuje OrderService předání objektu OrderDetailViewModel do třídy za běhu a v zájmu testovatelnosti umožňuje OrderMockService , aby třída byla předána OrderDetailViewModel do třídy v testovací době. Hlavní výhodou tohoto přístupu je, že umožňuje provádět testy jednotek, aniž by vyžadovaly nepraktné prostředky, jako jsou webové služby nebo databáze.

Testování aplikací MVVM

Testování modelů a zobrazení modelů z aplikací MVVM je stejné jako testování jiných tříd a stejné nástroje a techniky , jako je testování jednotek a napodobování, je možné použít. Existují však některé vzory, které jsou typické pro model a zobrazení tříd modelu, které mohou těžit z konkrétních technik testování jednotek.

Tip

Otestujte jednu věc s každým testem jednotek. Nenechte se pokoušet, aby cvičení testu jednotek bylo více než jeden aspekt chování jednotky. To vede k testům, které se obtížně čtou a aktualizují. Může také vést k nejasnostem při interpretaci selhání.

Mobilní aplikace eShopOnContainers provádí testování jednotek, která podporuje dva různé typy testů jednotek:

  • Fakta jsou testy, které jsou vždy pravdivé, což testuje neutrální podmínky.
  • Teorie jsou testy, které platí pouze pro konkrétní sadu dat.

Testy jednotek, které jsou součástí mobilní aplikace eShopOnContainers, jsou testy faktů, takže každá metoda testování jednotek je zdobena atributem [Fact] .

Poznámka:

Testy xUnit provádí spouštěč testů. Pokud chcete spustit spouštěč testů, spusťte projekt eShopOnContainers.TestRunner pro požadovanou platformu.

Testování asynchronních funkcí

Při implementaci modelu MVVM modely zobrazení obvykle vyvolávají operace ve službách, často asynchronně. Testy kódu, který tyto operace vyvolá, obvykle používají napodobení jako nahrazení skutečných služeb. Následující příklad kódu ukazuje testování asynchronní funkce předáním napodobené služby do modelu zobrazení:

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

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

    Assert.NotNull(orderViewModel.Order);  
}

Tento test jednotek zkontroluje, že Order vlastnost OrderDetailViewModel instance bude mít hodnotu po InitializeAsync vyvolání metody. Metoda InitializeAsync je vyvolána při přechodu na odpovídající zobrazení modelu zobrazení. Další informace o navigaci naleznete v tématu Navigace.

OrderDetailViewModel Když je instance vytvořena, očekáváOrderService, že instance bude zadána jako argument. Načítá OrderService ale data z webové služby. OrderMockService Proto je instance, která je napodobenou verzí OrderService třídy, určena jako argument konstruktoruOrderDetailViewModel. Když se pak vyvolá metoda modelu InitializeAsync zobrazení, která vyvolá IOrderService operace, načte se napodobení dat místo komunikace s webovou službou.

Testování implementace INotifyPropertyChanged

INotifyPropertyChanged Implementace rozhraní umožňuje zobrazení reagovat na změny, které pocházejí ze zobrazení modelů a modelů. Tyto změny nejsou omezeny na data zobrazená v ovládacích prvcích – slouží také k řízení zobrazení, jako jsou stavy modelu zobrazení, které způsobují spuštění animací nebo zakázání ovládacích prvků.

Vlastnosti, které lze aktualizovat přímo testem jednotek, lze testovat připojením obslužné rutiny události k PropertyChanged události a kontrolou, zda je událost vyvolána po nastavení nové hodnoty vlastnosti. Následující příklad kódu ukazuje takový test:

[Fact]  
public async Task SettingOrderPropertyShouldRaisePropertyChanged()  
{  
    bool 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.True(invoked);  
}

Tento test jednotek vyvolá InitializeAsync metodu OrderViewModel třídy, která způsobí aktualizaci jeho Order vlastnosti. Test jednotek projde za předpokladu PropertyChanged , že je událost vyvolána Order pro vlastnost.

Testování komunikace založené na zprávách

Prohlédněte si modely, které používají MessagingCenter třídu ke komunikaci mezi volně propojenými třídami, lze testovat tak, že se přihlásíte k odběru zprávy, kterou odešle testovaný kód, jak je znázorněno v následujícím příkladu kódu:

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

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

    Assert.True(messageReceived);  
}

Tento test jednotek zkontroluje, že CatalogViewModel publikuje AddProduct zprávu v reakci na spuštění AddCatalogItemCommand . Vzhledem k tomu, že MessagingCenter třída podporuje odběry zpráv vícesměrového vysílání, test jednotek se může přihlásit k odběru AddProduct zprávy a spustit delegáta zpětného volání v reakci na jeho přijetí. Tento delegát zpětného volání zadaný jako výraz lambda nastaví boolean pole, které používá Assert příkaz k ověření chování testu.

Testování zpracování výjimek

Testy jednotek lze také zapsat, které kontrolují, že konkrétní výjimky jsou vyvolány pro neplatné akce nebo vstupy, jak je znázorněno v následujícím příkladu kódu:

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

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

Tento test jednotek vyvolá výjimku, protože ListView ovládací prvek nemá událost s názvem OnItemTapped. Metoda Assert.Throws<T> je obecná metoda, kde T je typ očekávané výjimky. Argument předaný Assert.Throws<T> metodě je výraz lambda, který vyvolá výjimku. Proto bude test jednotek úspěšný za předpokladu, že výraz lambda vyvolá ArgumentException.

Tip

Vyhněte se psaní testů jednotek, které prověřují řetězce zpráv o výjimce. Řetězce zpráv o výjimkách se můžou v průběhu času měnit, takže testy jednotek, které spoléhají na jejich přítomnost, se považují za křehké.

Testování ověřování

Existují dva aspekty testování implementace ověřování: testování, že jsou správně implementována všechna ověřovací pravidla, a testování, že ValidatableObject<T> třída funguje podle očekávání.

Logika ověřování je obvykle jednoduchá k testování, protože se obvykle jedná o samostatný proces, ve kterém výstup závisí na vstupu. Měly by existovat testy na výsledcích vyvolání Validate metody pro každou vlastnost, která má alespoň jedno přidružené ověřovací pravidlo, jak je znázorněno v následujícím příkladu kódu:

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

    bool isValid = mockViewModel.Validate();  

    Assert.True(isValid);  
}

Tento test jednotek zkontroluje, že ověření proběhne úspěšně, pokud obě ValidatableObject<T> vlastnosti v MockViewModel instanci mají data.

Kromě kontroly úspěšného ověření by testy ověřovacích jednotek měly také zkontrolovat hodnoty Value, IsValida Errors vlastnost každé ValidatableObject<T> instance, a ověřit, že třída funguje podle očekávání. Následující příklad kódu ukazuje test jednotek, který to dělá:

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

    bool isValid = mockViewModel.Validate();  

    Assert.False(isValid);  
    Assert.NotNull(mockViewModel.Forename.Value);  
    Assert.Null(mockViewModel.Surname.Value);  
    Assert.True(mockViewModel.Forename.IsValid);  
    Assert.False(mockViewModel.Surname.IsValid);  
    Assert.Empty(mockViewModel.Forename.Errors);  
    Assert.NotEmpty(mockViewModel.Surname.Errors);  
}

Tento test jednotek zkontroluje, že ověření selže, pokud Surname vlastnost neobsahuje žádná data, a IsValidValue, a vlastnost každé Errors ValidatableObject<T> instance jsou správně nastavenyMockViewModel.

Shrnutí

Test jednotek přijímá malou jednotku aplikace, obvykle metodu, izoluje ji od zbytku kódu a ověřuje, že se chová podle očekávání. Jejím cílem je zkontrolovat, že každá jednotka funkcí funguje podle očekávání, aby se chyby nešířily v celé aplikaci.

Chování objektu v testu lze izolovat nahrazením závislých objektů napodobením objektů, které simulují chování závislých objektů. To umožňuje provádět testy jednotek, aniž by vyžadovaly nepraktné prostředky, jako jsou webové služby nebo databáze.

Testování modelů a zobrazení modelů z aplikací MVVM je stejné jako testování všech ostatních tříd a stejné nástroje a techniky lze použít.