Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Tipp.
Ez a tartalom a 'Enterprise Application Patterns Using .NET' e-könyvből vett részlet, amely elérhető a MAUI oldalon, vagy ingyenesen letölthető PDF-ként, amit offline is lehet olvasni.
MAUI eBook cover thumbnail.
A többplatformos alkalmazások az asztali és a webes alkalmazásokhoz hasonló problémákat tapasztalnak. A mobilfelhasználók az eszközüktől, a hálózati kapcsolattól, a szolgáltatások elérhetőségétől és más tényezőktől függően eltérőek lesznek. Ezért a többplatformos alkalmazásokat úgy kell tesztelni, ahogy a való világban használnák a minőség, a megbízhatóság és a teljesítmény javítása érdekében. Számos tesztelési típust kell elvégezni egy alkalmazáson, beleértve az egységtesztelést, az integrációs tesztelést és a felhasználói felület tesztelését. Az egységtesztelés a leggyakoribb forma, és elengedhetetlen a kiváló minőségű alkalmazások létrehozásához.
Az egységteszt az alkalmazás egy kis egységét, általában egy metódust vesz igénybe, elkülöníti a kód többi részétől, és ellenőrzi, hogy a várt módon viselkedik-e. A cél annak ellenőrzése, hogy minden egyes funkcióegység a várt módon működik-e, így a hibák nem propagálásra kerülnek az alkalmazás egészében. A hibák észlelése, ahol előfordul, hatékonyabb, mint egy hiba közvetett hatásának megfigyelése másodlagos meghibásodási ponton.
Az egységtesztelés a kódminőségre a legfontosabb hatással van, ha ez a szoftverfejlesztési munkafolyamat szerves része. Az egységtesztek egy alkalmazás tervezési dokumentációjaként és funkcionális specifikációjaként is működhetnek. Amint megírtak egy metódust, olyan egységteszteket kell írni, amelyek ellenőrzik a metódus viselkedését a standard, a határ- és a helytelen bemeneti adatesetekre reagálva, és ellenőrzik a kód által tett explicit vagy implicit feltételezéseket. Másik lehetőségként a tesztalapú fejlesztéssel az egységtesztek a kód előtt lesznek megírva. A tesztalapú fejlesztéssel és annak implementálásával kapcsolatos további információkért lásd útmutatót: Tesztalapú fejlesztés a Test Explorer használatával..
Megjegyzés
Az egységtesztek nagyon hatékonyak a regresszió ellen. Ez azt a funkciót tartalmazza, amely korábban működött, de egy hibás frissítés megzavarta.
Az egységtesztek általában az előkészítés-végrehajtás-ellenőrzés mintát használják.
Lépés | Leírás |
---|---|
Elrendezés | Inicializálja az objektumokat, és beállítja a vizsgált metódusnak átadott adatok értékét. |
Felvonás | Meghívja a vizsgált metódust a szükséges argumentumokkal. |
Állít | Ellenőrzi, hogy a vizsgált módszer működése a várt módon működik-e. |
Ez a minta biztosítja, hogy az egységtesztek olvashatók, önleírók és konzisztensek legyenek.
Függőséginjektálás és egységtesztelés
A lazán összekapcsolt architektúra bevezetésének egyik motivációja az, hogy megkönnyíti az egységtesztelést. A függőséginjektálási szolgáltatásban regisztrált egyik típus az IAppEnvironmentService
interfész. Az alábbi példakód az osztály vázlatát mutatja be:
public class OrderDetailViewModel : ViewModelBase
{
private IAppEnvironmentService _appEnvironmentService;
public OrderDetailViewModel(
IAppEnvironmentService appEnvironmentService,
IDialogService dialogService, INavigationService navigationService, ISettingsService settingsService)
: base(dialogService, navigationService, settingsService)
{
_appEnvironmentService = appEnvironmentService;
}
}
Az OrderDetailViewModel
osztály függ a típustól IAppEnvironmentService
, amelyet a függőséginjektálási tároló felold, amikor létrehoz egy OrderDetailViewModel
objektumot. Azonban ahelyett, hogy valódi kiszolgálókat, eszközöket és konfigurációkat használó objektumot hoz létre IAppEnvironmentService
az OrderDetailViewModel
osztály teszteléséhez, ehelyett cserélje le az IAppEnvironmentService
objektumot egy szimulált objektumra a tesztek céljára. A makettobjektum olyan objektum, amely azonos aláírással rendelkezik egy objektumhoz vagy felülethez, de meghatározott módon jön létre az egységteszteléshez. A függőséginjektálással gyakran használják a különböző adatok és munkafolyamat-forgatókönyvek teszteléséhez szükséges interfészek konkrét implementációinak biztosítására.
Ez a megközelítés lehetővé teszi, hogy az IAppEnvironmentService
objektum futásidőben átkerüljön az OrderDetailViewModel
osztályba, és a tesztelhetőség érdekében lehetővé teszi, hogy a próbaosztályt a tesztelési időpontban átadják az OrderDetailViewModel
osztálynak. Ennek a megközelítésnek a fő előnye, hogy lehetővé teszi az egységtesztek végrehajtását anélkül, hogy nem megfelelő erőforrásokat, például futtatókörnyezeti platformfunkciókat, webszolgáltatásokat vagy adatbázisokat kellene igényelnie.
MVVM-alkalmazások tesztelése
A modellek tesztelése és az MVVM-alkalmazásokból származó modellek megtekintése megegyezik bármely más osztály tesztelésével, és ugyanazokat az eszközöket és technikákat használja; Ez olyan funkciókat is tartalmaz, mint az egységtesztelés és a gúnyolás. A modellosztályok modellezésére és megtekintésére jellemző minták némelyike azonban kihasználhatja az egyes egységtesztelési technikákat.
Tipp.
Minden egységteszttel egy dolgot tesztelhet. A teszt összetettsége egyre összetettebbé válik, ami megnehezíti a teszt ellenőrzését. Az egységtesztek egyetlen problémára való korlátozásával biztosíthatjuk, hogy a tesztjeink ismételhetőbbek, elszigeteltebbek legyenek, és kisebb végrehajtási idő legyen. További ajánlott eljárásokért tekintse meg a .NET ajánlott tesztelési eljárásait.
Ne legyen kísértés arra, hogy az egységtesztelés az egység viselkedésének egynél több aspektusát is gyakorolja. Ez olyan tesztekhez vezet, amelyek nehezen olvashatók és frissíthetők. A hiba értelmezése során zavart is okozhat.
Az eShop többplatformos alkalmazás MSTest használatával végzi el az egységtesztelést, amely két különböző egységtesztet támogat:
Tesztelési típus | Attribútum | Leírás |
---|---|---|
TesztMódszer | TestMethod |
Meghatározza a futtatandó tényleges tesztmetódust. |
Adatforrás | DataSource |
Olyan tesztek, amelyek csak egy adott adatkészletre igazak. |
Az eShop többplatformos alkalmazáshoz tartozó egységtesztek TestMethod-ek, így minden egységteszt metódust az TestMethod
attribútummal van ellátva. Az MSTest mellett számos más tesztelési keretrendszer is elérhető, köztük az NUnit és az xUnit.
Aszinkron funkciók tesztelése
Az MVVM-minta megvalósításakor a nézetmodellek általában szolgáltatásokon hajtanak végre műveleteket, gyakran aszinkron módon. Az ezeket a műveleteket meghívó kódtesztek általában a tényleges szolgáltatások utánzatait használják. Az alábbi példakód bemutatja az aszinkron funkciók tesztelését, ha egy modellszolgáltatást egy nézetmodellbe ad át:
[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);
}
Ez az egységteszt ellenőrzi, hogy a Order
OrderDetailViewModel
példány tulajdonsága rendelkezik-e értékkel a InitializeAsync
metódus meghívása után. A InitializeAsync
metódus akkor lesz meghívva, ha a nézetmodell megfelelő nézetére navigál. A navigációval kapcsolatos további információkért lásd : Navigáció.
OrderDetailViewModel
A példány létrehozásakor elvárja, hogy egy IOrderService
példány argumentumként legyen megadva. A OrderService
lekéri az adatokat egy webszolgáltatásból. Ezért egy OrderMockService
osztály modellezett verziója, azaz egy OrderService
példány, van megadva az OrderDetailViewModel
konstruktor argumentumaként. Ebben az esetben tesztadatok kerülnek lekérésre, ahelyett hogy a nézetmodell metódusának InitializeAsync
meghívásakor a webszolgáltatással kommunikálnának, amely IOrderService
műveleteket használ.
INotifyPropertyChanged implementációk tesztelése
Az interfész implementálása lehetővé teszi, hogy a INotifyPropertyChanged
nézetek reagáljanak a nézetmodellekből és modellekből származó változásokra. Ezek a módosítások nem korlátozódnak a vezérlőkben megjelenített adatokra – a nézet vezérlésére is használhatók, például az animációkat kiváltó nézetmodell-állapotok vagy a vezérlők letiltására.
Az egységteszt által közvetlenül frissíthető tulajdonságokat úgy lehet tesztelni, hogy egy eseménykezelőt csatol az PropertyChanged
eseményhez, és ellenőrzi, hogy az esemény létrejön-e a tulajdonság új értékének beállítása után. Az alábbi példakód egy ilyen tesztet mutat be:
[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);
}
Ez az egységteszt meghívja a(z) InitializeAsync
osztály OrderViewModel
metódusát, amely a Order
tulajdonságának frissítését eredményezi. Az egységteszt sikeres lesz, feltéve, hogy az PropertyChanged
esemény a Order
tulajdonsághoz kapcsolódik.
Üzenetalapú kommunikáció tesztelése
Az osztályt MessagingCenter
lazán összekapcsolt osztályok közötti kommunikációra használó modelleket a tesztelt kód által küldött üzenetre való feliratkozással lehet tesztelni, ahogyan az a következő kód példájában is látható:
[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);
}
Ez az egységteszt ellenőrzi, hogy a rendszer a CatalogViewModel
végrehajtásra AddProduct
válaszul közzéteszi-e az AddCatalogItemCommand
üzenetet. Mivel az osztály támogatja a MessagingCenter
csoportos küldésű üzenet-előfizetéseket, az egységteszt előfizethet az AddProduct
üzenetre, és válaszul végrehajthat egy visszahívási függvényt. Ez a lambda kifejezésként megadott visszahívási delegált beállít egy logikai mezőt, amelyet az Assert
utasítás a teszt viselkedésének ellenőrzésére használ.
Kivételkezelés tesztelése
Az egységtesztek azt is megírhatják, hogy a rendszer bizonyos kivételeket ad-e érvénytelen műveletekhez vagy bemenetekhez, ahogy az a következő kód példájában is látható:
[TestMethod]
public void InvalidEventNameShouldThrowArgumentExceptionText()
{
var behavior = new MockEventToCommandBehavior
{
EventName = "OnItemTapped"
};
var listView = new ListView();
Assert.Throws<ArgumentException>(() => listView.Behaviors.Add(behavior));
}
Ez az egységteszt kivételt fog dobni, mert a ListView
vezérlőnek nincs olyan eseménye, amelynek neve OnItemTapped
. A Assert.Throws<T>
metódus egy általános metódus, amely T
a várt kivétel típusát adja meg. A metódusnak Assert.Throws<T>
átadott argumentum egy lambda kifejezés, amely kivételt eredményez. Ezért az egységteszt sikeres lesz, ha a lambda kifejezés egy ArgumentException
dob.
Tipp.
Kerülje a kivételüzenet-sztringeket vizsgáló egységtesztek írását. A kivételüzenetek szövegei idővel változhatnak, ezért azok az egységtesztek, amelyek a jelenlétükre támaszkodnak, törékenynek tekinthetők.
Tesztelési validálás
Az érvényesítési implementáció tesztelésének két aspektusa van: annak tesztelése, hogy az ellenőrzési szabályok megfelelően vannak-e implementálva, és hogy az osztály a ValidatableObject<T>
várt módon végez-e tesztelést.
Az érvényesítési logika tesztelése általában egyszerű, mivel általában egy önálló folyamat, amelyben a kimenet a bemenettől függ. Tesztelni kell a metódus meghívásának Validate
eredményeit minden olyan tulajdonságon, amely rendelkezik legalább egy társított érvényesítési szabvással, ahogy az a következő kód példájában is látható:
[TestMethod]
public void CheckValidationPassesWhenBothPropertiesHaveDataTest()
{
var mockViewModel = new MockViewModel();
mockViewModel.Forename.Value = "John";
mockViewModel.Surname.Value = "Smith";
var isValid = mockViewModel.Validate();
Assert.IsTrue(isValid);
}
Ez az egységteszt ellenőrzi, hogy az ellenőrzés sikeres-e, amikor a ValidatableObject<T>
példányban lévő két MockViewModel
tulajdonság mindkettő rendelkezik adatokkal.
Az ellenőrzés sikerességének igazolása mellett az érvényesítési egységteszteknek a Value
, IsValid
és Errors
tulajdonságok értékeit is ellenőrizniük kell az egyes ValidatableObject<T>
példányok esetében, hogy igazolják, az osztály a várt módon működik. Az alábbi példakód egy egységtesztet mutat be, amely ezt teszi:
[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);
}
Ez az egységteszt ellenőrzi, hogy az ellenőrzés sikertelen-e, ha a Surname
tulajdonságnál a MockViewModel
nem rendelkezik adatokkal, és az egyes Value
példányoknál a IsValid
, Errors
és ValidatableObject<T>
tulajdonságok helyesen vannak beállítva.
Összegzés
Az egységteszt az alkalmazás egy kis egységét, általában egy metódust vesz igénybe, elkülöníti a kód többi részétől, és ellenőrzi, hogy a várt módon viselkedik-e. A cél annak ellenőrzése, hogy minden egyes funkcióegység a várt módon működik-e, így a hibák nem propagálásra kerülnek az alkalmazás egészében.
A vizsgált objektumok viselkedése elkülöníthető úgy, hogy a függő objektumokat a függő objektumok viselkedését szimuláló modellobjektumokra cseréli. Ez lehetővé teszi az egységtesztek végrehajtását anélkül, hogy nem megfelelő erőforrásokat, például futtatókörnyezeti platformfunkciókat, webszolgáltatásokat vagy adatbázisokat kellene megkövetelni
A modellek tesztelése és az MVVM-alkalmazásokból származó modellek megtekintése megegyezik a többi osztály tesztelésével, és ugyanazokat az eszközöket és technikákat használhatja.