Въведение
Със сигурност сте чували за тестване на регресия и приемане. Но знаете ли колко действително се изразходват за тестване за приемане в даден проект?
Можем бързо да получим отговор на това с помощта на система за проследяване на времето като TMetric.
В нашия проект тестване за приемане настолно приложение от около 100 сборки отне повече от 2 човекоседмици. Новите QA специалисти, които не познаваха добре приложението, изпитваха най-големи затруднения. В сравнение с по-опитните QA специалисти, те отделиха много повече време на всеки тестов случай.
Според мен обаче най-неприятната част беше това – ако се открият критични грешки преди пускането, тестването за приемане трябва да се извърши отново след като тези грешки бъдат отстранени.
Писмените модулни тестове помогнаха малко, но все пак до голяма степен намалиха времето, прекарано в регресионно тестване. С това, когато количеството ръчно тестване достигна критично ниво, ние започнахме да вървим към автоматизация.
ROI
Преди да напишем автоматизирани UI тестове, трябваше да преценим колко печеливши са нашите инвестиции. Направихме това с помощта на ROI (Return On Investment https://en.wikipedia.org/wiki/Return_on_investment)
Изчисляването на ROI на тестването на потребителския интерфейс също стана интересна задача с множество неизвестни променливи:
ROI =Печалба / Разходи
или
ROI =(Печалба – Разходи) / Разходи
На този етап ни трябваше малък прототип, който да ни помогне да изчислим всички необходими разходи. Той показа много особени резултати:извършването на тестване за приемане отнема приблизително същото време като автоматизирането на този процес. Първоначално тази информация изглеждаше съмнителна, но когато проучихме допълнително, причините станаха ясни:
- Новите QA специалисти може да имат ограничено разбиране за стъпките, описани в тестови случаи. Когато това се случи, няколко души ще участват в тестване за приемане, за да помогнат за разбирането на ситуацията по-добре. Тук също трябва да имаме предвид въпроса доколко уместна е информацията, която разполагаме за настройките и изискванията на средата.
- Понякога хората, участващи в тестовете за приемане, прекарват време в изучаване на техническа документация.
- Самото приложение взаимодейства с конкретен набор от услуги. Ако един от тях не е наличен, по-малко опитните QA специалисти ще отделят време да описват грешки, които разработчиците от своя страна ще проучат. В резултат на това време се губи, защото необходимата услуга просто не работи правилно след прекъсване на работата/актуализация на хардуера/рестартиране на компютъра.
- Компютрите на QA тестери не са много мощни. Ако няма SSD, вече ще го забележите по време на инсталацията. Освен това, ако приложението работи при голямо натоварване, е възможно да се използва бавен файл за пейджинг.
- Честно казано, ние се увлечехме и забравихме, че работим с автоматизация. Между другото, затворихте ли раздела Youtube в браузъра си?
Сега да се върнем към ROI. За да опростим нещата, изчисленията бяха извършени от времето. Нека изчислим печалбата като спестявания от ръчни тестове, а периодът от време, който ще разгледаме, е една година:
Печалба =(X – Y) * N =(60 – 1) * 8 =472 дни
X – времето, прекарано за ръчно тестване (60 дни)
Y – времето, прекарано за извършване на автоматизирани тестове (1 ден)
N – времето, през което е извършено приемането
След това ще разгледаме разходите:
Разходи =A + B + C + D + E + F =0 + 10 + 5 + 50 + 7 + 8 =80
A – Цената на лиценза за инструмент за автоматизация. В нашия случай беше използван безплатен инструмент.
B – Обучение на QA специалист (10 дни)
C – Подготовка на инфраструктурата (5 дни)
D – Разработване на тестове (50 дни)
E – Извършване на тестове и описване на грешки, открити в процеса (7 дни)
F – Тестова поддръжка (8 дни)
Общо:
ROI =Печалба / Разходи =472 / 80 =5,9
Разбира се, някои от аспектите тук са оценени. За да оценим собствените си изчисления, прекарахме известно време в проучване на възможностите, предлагани от платените решения и различни калкулатори на ROI. С това изчислихме средната стойност на ROI от 2 или 3, което е страхотен резултат.
Съществуващи рамки
След като разгледахме организационните въпроси, нека се съсредоточим върху въпроси от технически вид. Най-важният от тях беше изборът на рамка за автоматизиране на тестването на нашето настолно приложение. Имахме следните изисквания въз основа на характеристиките на нашия проект:
- Тестовете ще бъдат разработени и изпълнявани на машини с Windows
- Рамката трябва да бъде адаптирана за тестване на настолни приложения
- Тестването на потребителския интерфейс може да бъде интегрирано в процеса на CI. Вече използвахме Дженкинс, така че тук беше за предпочитане
- Възможността за писане на тестове в удобна за потребителя IDE – тя трябва да има подчертаване на синтаксиса, навигация в тестов скрипт и завършване на код в стил IntelliSense
- Минимални разходи за QA обучение. По определени причини нашите QA специалисти не искаха да пишат тестове в Brainfuck
- За предпочитане е общността на Stack Overflow, MSDN и т.н.
Тестът е завършен
Първоначално тази платформа ни хареса поради своята зрялост, което даде надежди по отношение на техническите аспекти.
Първото нещо, на което се сблъскахме, беше нестабилна и доста остаряла IDE. Средата се справяше с подчертаването на синтаксиса повече или по-малко прилично, но имаше значителни проблеми с навигацията (Отиди към дефиниция), търсенето и автоматичното довършване на кода:тази функционалност изобщо не работеше приблизително в 60% от времето. Вграденият рекордер и аналогов Inspect работиха добре. В крайна сметка IDE ни поднесе неприятна изненада, когато започна да предава аргументи на приложението. Това, очаквано, причини грешки в работата на приложението:
--no-sandbox program files (x86)\smartbear\testcomplete12\x64\bin\Extensions\tcCrExtension\tcCEFHost.dll;application/x-testcomplete12-0-chrome-browser-agent
На този етап включихме поддръжката на TestComplete в ситуацията, за да се опитаме да спестим време и да оценим качеството на техническата поддръжка, преди потенциално да закупим лиценз. След като бяха изпратени няколко писма до техническата поддръжка, получихме отговор – трябва да игнорираме аргументите, предадени на приложението. Странно, нали? Проучвайки допълнително, установихме, че тези аргументи са необходими за тестване на приложения, които използват CEF. В следващото ни писмо заявихме, че използваме CEF, и ни казаха от специалистите по поддръжката да не пренебрегваме аргументите. Когато попитахме как точно да ги използваме, отговорът се промени обратно на „Игнорирайте аргументите“.
Излизайки от разговора с техническата поддръжка, се обърнахме към документацията на IDE (без много надежда). Имаше повече информация, но не открихме нищо, свързано с въпросния случай. Също така, според същата тази документация, IDE трябваше да се държи различно от самото начало.
Предполага се, че тестовете в TestComplete ще бъдат написани с помощта на VBScript.
Ако го гледате достатъчно дълго, можете да чуете това. Microsoft предлага да конвертирате това „чудо“ в скриптове на PowerShell. Като алтернатива могат да се използват JavaScript и Python, което помага на ситуацията.
Като безплатен инструмент TestComplete би бил поносим, но техният сайт има страница с ценообразуване и цените са на потребител. В резултат на това ще получим след закупуване на инструмента:
- IDE, който искате да затворите
- Съвместимост със скриптове от 1996 г.
- Рекордер, така че да не записваме всичко ръчно
- Още една проверка, но със звънци и свирки
- 2 вида отговори за техническа поддръжка
- Документация, която не отразява реалността
Най-лошата търговска сделка, да продължим напред.
Кодиран потребителски интерфейс
Тактическо отстъпление, прегрупиране и флангираме проблема. От една страна, научихме как да използваме Visual Studio като IDE. От друга страна, нашият подход се основаваше на компонентите на потребителския интерфейс на DevExpress, които използваме. В резултат на това открихме интересна информация за Coded UI framework, която официално се използва в DevExpress за автоматизиране на тестването на потребителския интерфейс. Тази рамка е интегрирана във вътрешния процес на тестване толкова много, че има дори разширение на Visual Studio за нея.
Имаше обширна общност, Microsoft популяризира инструмента на своя уебсайт и този продукт също беше споменат в „Microsoft Visual Studio” канал. Накратко, всичко изглеждаше обещаващо и започнахме да подготвяме рамката.
Първото изискване, с което се сблъскахме, беше Visual Studio Enterprise. Освен това тази версия на Visual Studio беше необходима не само за писане на тестове, но и за тяхното изпълнение. Това означава, че mstest, чрез който ще се извършва стартирането в случай на CI, също трябва да бъде част от изданието Enterprise.
Всички необходими инструменти за кодиран потребителски интерфейс могат да бъдат инсталирани чрез активиране на съответните квадратчета за отметка, когато VS е инсталиран или модифициран.
Подходът към писането на тестове беше доста приятен:командите, интегрирани в обвивката, позволяваха бързо стартиране на рекордер, който генерира единичен тест и клас „карта“, описващ потребителския интерфейс. Допълнителните инструменти, интегрирани във VS, предоставяха възможността за създаване на отделни тестови класове без извикване на кода.
Единствената особеност, която забелязахме, беше частичен клас, който имаше описанието на контролата и беше разделен на две части. Заедно с много други неща, това е описано в документацията. Тази документация е достатъчна за удобен работен процес:примерите за код и екранните снимки правят цялата техническа информация лесно достъпна и лесна за разбиране. Казано по-просто, когато рекордерът описва потребителския интерфейс, се генерира файл „Designer.cs“. Този файл е отговорен за повторното използване на кода, който описва потребителския интерфейс. Всичко, с което рекордерът не може да се справи, трябва да бъде написано ръчно и запазено някъде извън автоматично генерираната част на класа. Това е много подобно на частичните класове, написани от VS deigners при създаване на контроли. Приоритетът на операциите, извършвани върху контролите и на техните проверки на състоянието, е описан в метод, към който рекордерът услужливо добавя стандартен атрибут TestMethod.
Облаците започнаха да се събират над рамката, когато започнахме да разглеждаме нещата, генерирани от рекордера . На първо място, това прикри някои от проблемите на приложението:свойството Name на някои контроли не беше посочено и записващият счете, че нарича този нелеп случай на нарушение на правилото приемлив и претърси контроли в текста. Освен това се справяше със сложни контроли много неефективно. Например възлите TreeView бяха търсени по индекс на възли, което направи създадения клас „карта“ неизползваем в случай на разширение на интерфейса. И стойността на рекордера падна значително в нашите очи – какъв е смисълът от автоматично генериране на кода, ако трябва да го проверите след това?
Можехме да се примирим с всички тези неща и да намерим похвално решение, но изведнъж гръм удари:Microsoft заяви, че тази технология вече е остаряла. С това VS 2019 стана последната версия на Visual Studio, която поддържа кодиран потребителски интерфейс. Възможността да сме зависими от VS 2019 сега и няколко години предварително не изглеждаше толкова страшно, но нашият проект е доста голям, така че трудностите могат да започнат някъде надолу (2025 г., например).
Нека обобщим. С кодиран потребителски интерфейс ще имаме:
- Мощна платена IDE
- Цялата инфраструктура вече е създадена за тестове:както от страната на IDE, така и от нашата CI
- Възможността да помолим всеки разработчик от нашия проект за помощ, защото пишем тестове на C# в същата IDE
- Огромно количество документация с добро качество
- Няколко тъжни QA специалисти, които поставиха кода си в автоматично генерираната част на класа и след това го загубиха по време на процеса на автоматично генериране
- Много генериран код, който работи и който трябва да подложите на строг преглед
- Невероятно прозрачен подход към CI:можете да пишете код за стартиране на тестове чрез mstest със затворени очи.
- Бавно умиращ червен гигант на автоматизацията, който непрекъснато нараства от нови тестове и е опасно близо до превръщането или в избледняващо бяло джудже, представено от абсолютно изолирана машина с необратимо остарял софтуер, или в взрив на свръхнова, когато проектът гръмне под натиск от нови актуализации.
Всичко звучеше добре с изключение на последната точка. Ето защо трябваше да продължим търсенето си.
TestStack.White
Работихме върху тестове за създаване на прототипи с помощта на White успоредно с изследването на функционалността на Coded UI.
Сами по себе си White е обвивка около библиотеките „Microsoft.Automation“, които изглеждаха много обещаващи, а White също е подобен на Coded потребителски интерфейс. При по-внимателно разглеждане обаче открихме, че е много по-строг и можете да го забележите навсякъде – от факта, че нямаше рекордер до действителната тестова структура. Например стартирането на приложението, търсенето на прозорец и натискането на бутона „Изпълни“ изглежда така:
var appPath = @"C:\Program files\UiAutomatedTestApplication\TestApplication.exe"; var app = TestStack.White.Application.Launch(appPath); var windowSearchCriteria = SearchCriteria.ByAutomationId("MainForm"); var window = app.GetWindow(windowSearchCriteria, InitializeOption.NoCache); var execute = window.GetElement(SearchCriteria.ByText("Execute")); var invokePattern = (InvokePattern)execute.GetCurrentPattern(InvokePattern.Pattern); invokePattern.Invoke(); app.WaitWhileBusy();
Дори и да няма оплаквания, когато става въпрос за стартиране на приложението, необходимостта от работа с класа InvokePattern е много съмнителна. Класът InitializeOption също изглежда странно, защото има достъп до статичния член WithCache, но се предполага, че се използва строго вътрешно:
public class InitializeOption { // // Summary: // This option should not be used as this is only for internal white purposes public static InitializeOption WithCache { get; } public static InitializeOption NoCache { get; } public virtual bool Cached { get; } public virtual string Identifier { get; } public virtual bool NoIdentification { get; } // // Summary: // Specify the unique identification for your window. White remembers the location // of UIItems inside a window as you find them. Next time when items inside the // same window is found they are located first based on position which is faster. // // Parameters: // identifier: public virtual InitializeOption AndIdentifiedBy(string identifier); public virtual void NonCached(); public override string ToString(); }
Странни решения като това са навсякъде и рамката се оказва твърде абстрактна за QA.
Документацията е с прилично качество и е оставила добро общо впечатление. Изходният код на проекта беше хостван в github, но последният ангажимент беше от 8 януари 2016 г.
Обобщавайки информацията за White, ще имаме:
- Достойна документация
- Достъп до изходния код
- Малка общност
- Необходимостта да се обясни на всички QA специалисти, че поведението на контрола се реализира чрез класа Pattern
- Старо хранилище, от което определено ще трябва да се разделим
Най-неприятната част беше необходимостта да разработим собствена рамка, която бихме искали да избегнем. Така че трябваше да продължим напред.
Appium
Срещахме Appium в нашето търсене и преди, но започнахме да го обмисляме сериозно, след като Microsoft спря да използва кодиран потребителски интерфейс.
На пръв поглед тестването с помощта на Appium изглежда като слот машина с три барабана. Първият показва езика, за който има API, който позволява взаимодействие с драйвера. Това предоставя възможност за писане на тестове на всеки познат език:Python, C#, Java и т.н. Втората лента показва приложението на драйвера, което служи като междинен слой между тестовете и продукта, който тестваме. Както е описано в документацията, взаимодействието с тестове се извършва с помощта на JSON Wire Protocol – това всъщност ни дава възможността да пишем тестове на всеки език. И третият барабан показва обекта, който тестваме. Всъщност няма значение дали е уебсайт, мобилно приложение или настолно приложение, стига съответният драйвер да работи. Както можете да видите, компонентите са елегантно взаимозаменяеми .
Оценката на уместността на пакета беше задоволителна – на страницата на Github можехме да видим, че хранилището има нови комити. Докато разглеждахме хранилището на WinAppDriver, разбрахме, че дори има рекордер в него.
Започнахме да забелязваме някои проблеми, докато пишехме прототип. Например, тъй като рамката е твърде многофункционална, WindowsElement, отговорен за контрола на работния плот, има метод FindElementByCssSelector, който хвърля следното изключение при изпълнение:„Неочаквана грешка. Нереализирана команда:стратегията за локатор на css селектор не се поддържа”. В следващата статия ще говорим за проблемите, които срещнахме, докато работихме с тази рамка, по-подробно, но засега бих искал да кажа, че успяхме да се справим с всички тях.
Като обобщение, ето какво ще имаме, докато използваме Appium:
- Възможността за тестване на функционалност на приложението, която изисква взаимодействие с браузър (отваряне на страницата за обратна връзка, онлайн активиране, проверка на доставката на имейл) в обхвата на една инфраструктура и един тест
- Възможност за работа с всяко издание на Visual Studio
- Възможността за тестване на настолно приложение, което използва браузър за изобразяване на потребителския интерфейс. Добър пример за това е Azure Data Studio
- Всички предимства, които получаваме с кодирания потребителски интерфейс
- Безплатна рамка, която Microsoft препоръчва да използвате
- Инфраструктура, позната на QA специалистите, които са работили със Selenium
- Хранилище, актуализирано с нови ангажименти
- Прилично голяма общност, която обаче не е толкова голяма, колкото общността на Coded UI
- Рекордер с ограничена функционалност
- Необходимостта от стартиране на приложение на драйвер за тестване. Не е много удобно, но има собствена функция за регистриране
- Много възможности да се простреляте в крака поради злополучното наследство на WindowsElement от AppiumWebElement
Преминавайки през всички точки с изискванията за рамки и сравнявайки всички проблеми, открити във всяка от тези рамки, накрая избрахме Appium.
Заключение
Беше интересно да се работи с всички тези рамки, защото всяка една от тях се основаваше на уникална философия за подход към автоматизирано тестване. Част от тях едва започнаха своя път, докато други достигаха своето затъмнение или вече са избледнели. Можете да избегнете загубата в множеството налични решения, като създадете списък със специфични изисквания за инструмента и имате отговорен екип с добре установено взаимодействие между членовете му. И не забравяйте, че бъдещите тестове са толкова голям проект, колкото и обикновеният код, с изоставане, платки, CI, рефакторинг и всичко останало.