Тестване в .NET Core 2.0

Тестове за единици и интеграция с xUnit

Здрасти!

Ето нашата нова публикация за .NET Core.

В предишната научихме как да разгърнем нашето .NET Core приложение с помощта на Docker. Не забравяйте да го проверите!

В тази публикация ще обсъдим как да създадем автоматизирани тестове за нашето приложение. Автоматизираните тестове са много важна част от разработката на софтуер като цяло и тази концепция се отнася и за .NET Core. Опростява изпълнението на тестовете за интеграция и интеграция, спестявайки много време на разработчиците.

Тази публикация ще ви даде представа как да внедрите тестове във вашето .NET Core приложение.

Личен опит

В Wolox тестваме нашите .NET Core проекти с помощта на xUnit и тестовата команда, налична в .NET Core CLI. Това не е единственият начин за тестване на тази специфична рамка, но тя е доста бърза за настройка и обхваща основите за това как да започнете по пътя си към производителност.

Важно е изходният код на нашето приложение да е готов за тестване. В този пример ще използваме този проект, който е достъпен на GitHub.

За да запазим структурата чиста, ще разделим кода си в две папки:

  • Един за изходния код (src) и,
  • Един за тестовете (тест).

Трябва да създадем новия тестов проект в тестовата папка.

За всеки от секциите на тази публикация ще създаваме тестов проект, използвайки командата dotnet new, която генерира нов xUnit проект (dotnet new xunit). След като имаме тестовия проект, трябва да препратим изходния код на нашето приложение във файла на проекта. Можем да го направим, използвайки следната команда:

dotnet добавете референция ROUTE_TO_CSPROJ.csproj

Това ще ни позволи да използваме всички методи или класове, дефинирани в основния ни проект.

Единични тестове

Тестването на единицата е доста просто. Тя ни позволява да тестваме специфичните модули и компоненти на нашите приложения. Целта на тези видове тестове не включва функционалността на приложението като цяло, а специфичната работа на единиците, които съставляват нашата система.

Тези единици обикновено са специфични класове или функции, които се оценяват, за да се види дали очакваният резултат при използване на техните методи съответства на това, което всъщност получаваме.

За този пример ще създадем клас Helper (MathHelper.cs), който ще капсулира функциите, които ще тестваме. Това ще бъде статичен клас.

За да тестваме тези класове, ние ще създадем файл на нашия тестов проект, наречен UnitTestMathHelper.cs. Тук ще дефинираме клас със същото име като файла и метод, наречен TestSum.

Етикетите [Fact] уведомяват тестовия проект да знаем, че кодираме методите за тестване. За това приложение ще тестваме само два от методите, налични на нашия помощник. Един от начините да го направите е като използвате следния код:

Тук първо използваме етикета [Fact], така че този метод ще бъде идентифициран като тест.

  • След това използваме няколко променливи, за да установим нашите тестови данни (редове 4 и 5) и очаквания резултат (ред 6).
  • Следното нещо, което трябва да направим, е всъщност да извикаме метода, който ще тестваме (в случая методът Сума в ред 7).
  • И накрая, трябва да проверим дали полученият резултат е същият като този, който очаквахме (ред 8). След като тестовият ни случай е реализиран, трябва да използваме функцията „Assert.Equal“, за да позволим на приложението да определи резултата от теста.

Това ще върне стойност въз основа на условието, което поставихме като изискване тестът да е успешен. Класът Assert има различни методи, които се прилагат за различни ситуации.

Можем да използваме и етикета [Theory], заедно с [InlineData], ако искаме да тестваме метод с различни входове, както е показано в следващия код.

За да стартираме нашия тест на устройството, просто трябва да се насочим към основната папка с помощта на нашия терминал и да напишем командата за тестване на dotnet. Трябва да ни даде резултата от нашите тестове. Ето, ние правим 4 теста. Една за метода Sum и една за всяка от стойностите, тествани в метода на умножение.

Опитай! Опитайте да създадете тест за един от методите в OperationsController. Би трябвало да можем да го заложим директно във вашето приложение.

Тестов сървър

Тестов сървър ни позволява да тестваме функционалността на различни компоненти на нашето приложение, работещи заедно. Те са малко по-сложни от единичните тестове, главно защото изискват от нас да настроим сървър, за да работи нашето приложение.

В този пример ще тестваме нов клас и контролер: Hero. Кодът на този нов клас, неговия контролер и други файлове, които трябва да бъдат променени, можете да намерите тук.

След като сме готови, можем да започнем да пишем тестовия код.

Първата стъпка е да добавите пакета Microsoft.AspNetCore.TestHost NuGet към нашия тестов конфигурационен файл. Нашият файл на проекта трябва да изглежда така:

Това ще ни предостави необходимите библиотеки за създаване на тестов сървър за нашето приложение.

Нека създадем нова папка в нашата тестова папка и да я наречем Интеграция, както и нов файл, за да започне самия сървър. Следният код показва един начин за това:

За този тест ще използваме база данни в паметта, така че трябва да променим начина, по който настройваме базата данни. За целта трябва да добавим няколко реда в метода ConfigureServices, разположен във файла Startup.cs на нашето приложение. Ето как трябва да изглежда новият код:

С този набор ще можем да използваме тестовия сървър, сякаш той е редовният. Сървърът трябва да работи по същия начин като нашето приложение, но той ни позволява да извършваме нашите тестове с тестови данни, за да избегнем компрометиране на информацията, използвана в нашите производствени сървъри. Функциите Assert, които използвахме по-рано, работят по същия начин, както те при извършване на единични тестове.

За тези тестове първо ще направим някои тестови данни, които нашите тестове да използват. В този случай ние ще създадем някои „Heroes“ и ще ги съхраним в списък, както е показано в следния код:

Този списък ще бъде използван и в двата ни теста, макар и не по един и същи начин. Нека да разгледаме първия тест:

И така, какво правим тук?

  • Първо, използваме етикета [Теория], който показва, че ще извършваме едни и същи тестове няколко пъти с различни входни тестове. След това имаме етикет [MemberData]. Това може да се използва за извличане на данни за [Theory] от статично свойство. Този атрибут има много приложения, в този случай ние просто го използваме за информацията от собствеността Heroes, която предварително дефинирахме.
  • Следващото нещо, което правим, е да дадем на нашия метод име и параметри. Както може би се досещате, вмъкнатите параметри съвпадат с параметрите на класа Hero, които по-късно ще бъдем инсталирани (ред 7) и добавени към нашата база данни в паметта (редове 9 и 10).
  • Останалото е доста ясно. Ние отправяме заявка към нашето приложение, използвайки номера на идентификационния номер на героя като параметър (ред 12) и проверяваме дали кодът на състоянието на отговора е ОК (ред 14).
  • На следващо място, ние получаваме 'Hero' от отговора като JSON низ (ред 16) и го преобразуваме в герой обект (ред 18).
  • И накрая, можем да проверим дали свойствата на поставения герой (идентификатор и име) съответстват на тези на героя на отговора (редове 20 и 21).

Този тест ще се изпълни за всеки от героите, определени в свойството Heroes.

Нека да разгледаме следващия тест:

Ето, ние приемаме различен подход към нашите Герои:

  • Както можете да видите, първо използваме етикета [Fact], вместо [MemberData]. Това е така, защото този път ние ще използваме свойството „Heroes“ като цяло, вместо да тестваме вмъкването на всеки герой поотделно.
  • С помощта на Linq можем да конвертираме този списък на обекти [] в списък с герои (редове 5 до 10) и да вмъкнем цялото нещо в нашата база данни (редове 12 до 13).
  • Следващата стъпка е да се определи очакваната стойност на отговора (в този случай героят с най-малка височина, вижте ред 15).
  • Още веднъж ще направим заявка към нашето приложение (ред 17), ще проверим кода на състоянието на отговора (ред 19), ще извадим JSON от отговора (ред 21) и ще го преобразуваме в обект Hero (ред 23).
  • Окончателното сравнение се извършва по същия начин, като се проверява дали свойствата на героя, който получихме от отговора, са същите като тези, които очакваме (редове 25 и 26).

Сега можем да стартираме нашия тестов дотнет тест за команда и да видим резултата от нашите тестове. Ако всичко е наред, ще получим съобщение „Тестване успешно. Ако някой от нашите тестове се провали, ще получим съобщение „Тест неуспешно“, заедно с информация за случилото се.

Това е!

Можем да комбинираме както тестове за единици, така и интеграция за нашия проект и да ги настроим, колкото искаме. Важно е да се отбележи, че обикновено се препоръчва използването на тестова база данни, за да се избегне компрометиране на информация, която може да не бъде възстановена, ако е повредена / презаписана. Тук създаваме база данни в паметта, но ако е необходимо, можете да настроите база данни да работи по същия начин като нормалната, за да избегнете компрометиране на информация, която може да не бъде възстановена, ако е повредена / презаписана.

Сега можете да разработите автоматични тестове за вашите .NET Core приложения. Опитай! Ако искате да играете наоколо, винаги можете да опитате примерното приложение.

Следете за следващата публикация.

Честито тестване!