Ühiktestide kirjutamine
Ühiktestide kirjutamine on suuresti meie endi töö, kuid me saame kasutada häid abivahendeid nagu testimisraamistikud. Selles aines kasutame xUnit testimisraamistikku, mis töötab hästi koos Visual Studioga. Loomulikult saab jooksutada teste ka käsurealt kui selleks vajadust on.
Ühiktestide jaoks lisame me rakendusse tavaliselt eraldi projekti. Teste ja rakenduse koodi ühes projektis koos hoida ei ole otstarbekas, sest käituskeskkondades teste ei jooksutada. Testide jooksutamine on arenduskeskkondade teema.
Pilt juurde, võiks src ja tests kaustadega olla, viide VS-i solution folderitele
Testide klassid
Igale klassile rakenduse koodis seame me vastavusse klassi testide projektis. See puudutab siis klasse, mida me kavatseme testidega katta. xUnit tunneb testide klassid ära selle järgi, et nendes klassides on testid ehk siis meetodid, millel on Fact
või Theory
atribuut lisatud.
Testide klassid on nagu kõik teisedki klassid. Me võime kasutada näiteks klassi skoobis muutujaid, et mõningaid objekte igas testis uuesti ei peaks looma. Eelmises peatükis tpoodud testide klassis saaksime klassi skoopi viia näiteks muutuja, kus hoiame Calculator objekti.
Testide nimed
public class CalculatorTests
{
private readonly Calculator _calculator;
public CalculatorTests()
{
_calculator = new Calculator();
}
[Fact]
public void Add_should_add_two_positive_numbers()
{
var x = 10;
var y = 22;
var expectedResult = 32;
var actualResult = _calculator.Add(x, y);
Assert.Equal(expectedResult, actualResult)
}
[Fact]
public void Add_should_add_two_negative_numbers()
{
var x = -11;
var y = -28;
var expectedResult = -39;
var actualResult = _calculator.Add(x, y);
Assert.Equal(expectedResult, actualResult)
}
}
Testide tulemuste osas see midagi ei mõjuta, sest iga testi jaoks tehakse testide klassi põhjal uus objekt. Meenutuseks olgu antud eelmises peatükis toodud näitekood.
CalculatorTests tests;
tests = new CalculatorTests();
tests.Add_should_add_two_positive_numbers();
tests = new CalculatorTests();
tests.Add_should_add_two_negative_numbers();
Selliselt jooksutab teste ka xUnit, mida me kasutame. Iga test algab uue testklassi objekti loomisega, et test kindlasti käivituks puhtast seisust. See tähendab seda, et testklassile eelmise testi tehtud muudatused järgmisi teste ei mõjuta.
Testmeetodid
Testklassid sisaldavad meetode, millest osad (tavaliselt enamus) on testid. Osad meetodid testklassides on abistava otstarbega. xUnit korral märgitakse testideks olevad meetodid kas Fact
või Theory
atribuudiga:
- Fact -
- Theory -
Näide theory kohta
Testide anatoomia
Testmeetoditel on oma kindel struktuur, mida piinliku täpsusega järgitakse. See võetakse kokku kolme A-ga (AAA):
- Arrange -
- Act -
- Assert -
[Fact]
public void Add_should_add_two_positive_numbers()
{
// Arrange
var calculator = new Calculator();
var x = 10;
var y = 22;
var expectedResult = 32;
// Act
var actualResult = calculator.Add(x, y);
// Assert
Assert.Equal(expectedResult, actualResult)
}
Arrange osas defineerime me muutujad, mida testis kasutame ja anname neile algväärtused. Eriline muutuja selles plokis on expectedResult
- selles muutujas hoitakse väärtust, mida test korrektsel juhul peaks tagastama. Me ei kirjuta selle muutuja väärtust lihtsalt Assert osasse sisse, sest sarnaselt rakenduse koodile väldime ka testide koodis maagiliste konstantide kasutamist.
Act osa on see, kus toimub testitava komponendi jooksutamine. Ülaltoodud näites lastakse käima kalkulaatori Add() meetod. Keerukamatel juhtudel võib Act osas olla ka mitu rida koodi.
Assert osas kontrollitakse kas test õnnestus. Selleks kasutatakse tavaliselt Assert klassi meetode. Üleltoodud test on lihtne ning seal oli vaja ainult ühte kontrolli veendumaks, et Add() meetod tagastas korrektse tulemuse. Keerukamatel juhtudel võib kontrolle olla rohkem.
Vigu püüdvad testid
Osad testid, mis me kirjutame, ei veendu selles, et kõik läks hästi, vaid vastupidi - testi õnnestumise eelduseks on see, et testitavas koodis tekkis viga.
Näide exceptionit ootavast testist
Asünkroonsed testid
Kuna .NET Core platvormil on asünkroonne kood muutumas ühe populaarsemaks, siis on toetatud ka asünkroonsete meetodie testimine. Testi jooksutamiseks asünkroonselt peame testi lihtsalt kirjutama kui iga teise asünkroonse meetodi.
public async Task GetById_returns_null_when_invoice_not_found()
{
// Arrange
var nonExistentId = -100;
IInvoiceService invoiceService = new InvoiceServiceStub();
// Act
var invoice = await invoiceService.GetById(nonExistentId);
// Assert
Asser.IsNull(invoice);
}