Здравей, Хабр!
Казвам се Максим Пономаренко и съм разработчик в Спортмастера. Имам 10-годишен опит в IT сферата. Започнах кариерата си в областта на ръчното тестване, след което преминах към разработка на бази данни. През последните 4 години, натрупвайки знания от тестването и разработката, се занимавам с автоматизация на тестването на ниво СУБД.
В екипа на Спортмастера съм малко повече от година и в един от големите проекти се занимавам с разработка на автоматизирано тестване. През април аз и колегите от Sportmaster Lab участвахме в конференция в Краснодар, моята презентация беше на тема „Юнит тестове в СУБД“, и сега искам да я споделя с вас. Ще има много текст, затова реших да разделя презентацията на два поста. В първия ще говорим за автотестове и тестването като цяло, а във втория по-подробно ще разгледам нашата система за юнит тестване и резултатите от нейното прилагане.
Първоначално малко скучна теория. Какво е автоматизирано тестване? Това е тестване, което се извършва с помощта на софтуерни средства, и в съвременния IT то се използва все по-често при разработката на софтуер. Това е свързано с факта, че компаниите растат, техните информационни системи нарастват и съответно нараства и количеството функционалности, които трябва да се тестват. Провеждането на ръчно тестване става все по-трудно и трудно.
Работил съм в една голяма компания, чийто релизи излизат на всеки два месеца. При това цял месец се губи за десетина тестировчици да проверяват функционалността със собствените си ръце. Благодарение на внедряването на автоматизация с малка команда от разработчици успяхме за година и половина да съкратим времето за тестване до 2 седмици. Не само увеличихме скоростта на тестване, но и повишихме неговото качество. Автоматичните тестове се стартират редовно и винаги изпълняват целия набор от заложени проверки, тоест изключваме човешкия фактор.
За съвременния IT е характерно, че от разработчика може да се изисква не само да пише кода на продукта, но и да пише юнит тестове, които проверяват този код.
Но какво да направите, ако системата ви се основава предимно на сървърна логика? Няма универсално решение или практики, прилагани на пазара. Обикновено компаниите решават този проблем чрез създаване на собствена система за тестване. Тази система за автоматизирано тестване беше създадена в нашия проект и за нея ще разкажа в моя доклад.

Тествайте лоялността
Първо, да поговорим за проекта, в който внедрихме системата за автоматизирано тестване. Нашият проект е система за лоялност на Спортмастера (между другото, вече писахме за него в ).
Ако компанията ви е достатъчно голяма, системата за лоялност ще разполага с три стандартни свойства:
- Вашата система ще бъде с високо натоварване
- Вашата система ще включва сложни изчислителни процеси
- Вашата система ще бъде активно подобрявана.
Да продължим по ред... В обобщение, ако разгледаме всички марки на Спортмастера, в Русия, Украйна, Китай, Казахстан и Беларус имаме над 1000 магазина. В тези магазини ежедневно се извършват около 300 000 покупки. Тоест всяка секунда в нашата система постъпват по 3-4 касови бележки. Естествено, системата за лоялност е с високо натоварване. А тъй като тя се използва активно, ние трябва да предоставяме най-високите стандарти за качество, тъй като всяка грешка в софтуера води до големи финансови, репутационни и други загуби.
В същото време в Спортмастера работят над сто различни промоции. Промоциите са разнообразни: има продуктови, има свързани с деня от седмицата, има привързани към конкретен магазин, има промоции, свързани с размера на покупката, и на брой стоки. В общи линии, предизвикателствата са значителни. Клиентите имат бонуси, имат промо кодове, които се използват при покупки. Всичко това води до факта, че изчисляването на всяка поръчка е доста нетривиална задача.
Алгоритъмът, реализиращ обработката на поръчки, е наистина ужасен и сложен. И всяка промяна в този алгоритъм е доста рисковано начинание. Дори най-външно незначителни промени могат да доведат до доста непредсказуеми ефекти. А точно такива сложни изчислителни процеси, особено реализиращи критична функционалност, са най-добрите кандидати за автоматизация. Проверяването на десетки еднотипни случаи ръчно е много времеемко. И тъй като точката на вход в процеса остава непроменена, описвайки я веднъж, можем доста бързо да генерираме автоматични тестове и да сме уверени в работата на функционала.
Тъй като нашата система се използва активно, бизнесът ще очаква от вас нещо ново, да е в крак с времето и да е ориентиран към клиента. В нашата система за лоялност версиите излизат на всеки два месеца. Това означава, че на всеки два месеца трябва да провеждаме пълен регрес на цялата система. При това, естествено, както и в всяка съвременна ИТ среда, разработката не попада веднага от разработчика в продукция. Тя се ражда на контур на разработчика, след което последователно минава през тестов стенд, релизната и приемната фаза, и едва тогава попада в продукция. Най-малко на тестовия и на релизната контури трябва да провеждаме пълен регрес на цялата система.
Описание на свойствата е стандартно за практически всяка система за лоялност. Нека поговорим за особеностите на нашия проект.
Технологично на 90% логиката на нашата система за лоялност е сървърна и реализирана на Oracle. Има клиент, разработен на Delphi, който изпълнява функцията на АРМ-администратор. Има предоставени уеб услуги за външни приложения (например уебсайт). Следователно е съвсем логично, че ако развиваме система за автоматизирано тестване, ще я направим на Oracle.
Системата за лоялност в Спортмастера съществува повече от 7 години и беше създадена от единствени разработчици… Средното количество разработчици в нашия проект през тези 7 години е било 3-4 души. Но през последната година нашият екип значително нарасна и сега по проекта работят 10 души. Тоест в проекта идват хора, които не са запознати с типичните задачи, процеси и архитектура. И съществува повишен риск, че ще пропускаме грешки.
За проекта е характерно отсъствието на выделени тестери като щатни единици. Тестиране, безусловно, има, но тестрането се извършва от аналитиците, освен другите им основни задължения: в комуникацията с бизнес поръчителите, потребителите, работата по изискванията към системата и т.н. и т.н… Въпреки че тестиране се провежда много качествено (особено е уместно да се спомена, тъй като някой от аналитиците може да види този доклад), ефективността на специализацията и концентрацията върху нещо конкретно не може да бъде отменена.
С оглед на всичко казано по-горе, за повишаване на качеството на продукта и намаляване на сроковете за разработка, идеята за автоматизация на тестиране в проекта изглежда много логична. И на различни етапи от съществуването на системата за лоялност, отделни разработчици полагаха усилия да покрият своя код с юнит тестове. Това като цяло беше доста разпръснат процес, в който всеки използваше своя архитектура и методи. Общото за юнит тестовете бяха крайни резултати: тестовете бяха разработвани, известен период се използваха, съхраняваха се в версионно хранилище на файлове, но в даден момент спираха да се изпълняват и бяха забравяни. На първо място, това се случваше поради факта, че тестовете бяха свързани по-скоро с конкретния изпълнител, а не с проекта.
На помощ идва utPLSQL.

Знаете ли нещо за Стивън Фейерштейн?
Това е интелигентен човек, който е посветил значителна част от кариерата си на работа с Oracle и PL/SQL, написвайки в тази област доста трудове. Една от известните му книги се нарича: „Oracle PL/SQL. За професионалисти“. Именно Стивън е създателят на решението utPLSQL, или, каквато е неговата разшифровка, Unit Testing framework for Oracle PL/SQL. Решението utPLSQL беше създадено през 2016 година, но активно се работи по него и се издават нови версии. Към момента на доклада последната версия е от 24 март 2019 година.
Какво е всъщност това? Това е отделен опенсорс проект. Тегли два мегабайта, включително примери и документация. Физически представлява отделна схема в базата данни ORACLE с набор от пакети и таблици за организация на юнит-тестове. Инсталацията отнема само няколко секунди. Отличителна черта на utPLSQL е простотата на експлоатация.
Глобално, utPLSQL представлява механизъм за стартиране на юнит-тестове, където под юнит-тест разбираме обикновени Oracle пакетни процедури, организацията на които съответства на определени правила. Освен стартиране, в utPLSQL се съхранява лог на всички ваши тестови стартирания, както и вътрешна система за отчитане.
Нека да разгледаме пример как изглежда кодът на юнит-тест, реализиран по тази методика.

И така, на екрана е представен кодът на типова спецификация на пакет с юнит-тестове. Какви са задължителните изисквания? Пакетът трябва да има префикс „utp_“. Същият префикс трябва да имат всички процедури с тестовете. В пакета задължително трябва да присъстват две стандартни процедури: „utp_setup“ и „utp_teardown“. Първата процедура се извиква преди всеки юнит-тест, втората — след изпълнението.
„utp_setup“ обикновено подготвя нашата система за стартиране на юнит-теста, например, създавайки тестови данни. „utp_teardown“ — обратно, всичко връща към първоначалните настройки и нулира резултатите от стартирането.
Ето пример на най-простия unit тест, който проверява нормализирането на въведения телефонен номер на клиента до стандартния за нашата система за лоялност формат. Няма задължителни стандарти как да се пишат процедури с unit тестове. Обикновено се извиква някакъв метод на тестваната система и резултатът, върнат от този метод, се сравнява с еталонния. Важно е сравняването на еталонния резултат и получения да става чрез стандартните утPLSQL методи.
В юнит теста може да има неограничен брой проверки. Както се вижда от примера, правим четири последователни извиквания на тествания метод за нормализиране на телефонния номер и след всяко извикване оценяваме резултата. При разработването на юнит теста трябва да се вземе под внимание, че има проверки, които не влияят на системата, а след някои от тях трябва да се възстанови първоначалното състояние на системата.
Например, в представения юнит тест просто форматираме входния телефонен номер, което не оказва влияние на системата за лоялност.
Ако пишем юнит тестове за метода за създаване на нов клиент, след всяка проверка в системата ще бъде създаден нов клиент, което може да повлияе на последващото изпълнение на теста.

Така стартират юнит тестовете. Допустими са два варианта на стартиране: стартиране на всички юнит тестове от конкретен пакет или стартиране на конкретен юнит тест в конкретен пакет.

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

- Автоматичните тестове трябва да бъдат ефективни и да носят полза. Имаме чудесни разработчици, за които определено трябва да споменем, тъй като някой от тях вероятно ще види този доклад, и те пишат великолепен код. Но дори и техният страхотен код не е идеален и е съдържал, съдържа и ще съдържа грешки. Автоматичните тестове трябва да откриват тези грешки. Ако не е така, то или пишем лоши автоматични тестове, или сме попаднали в мъртва зона, която по принцип не се доразвива. В двата случая правим нещо неправилно и подходът ни е просто безсмислен.
- Автоматичните тестове трябва да се използват. Безсмислено е да се губи много време и усилия за написването на софтуерен продукт, да се сглоби неговото хранилище и да се забрави за него. Тестовете трябва да бъдат задействани и да се стартират колкото се може по-редовно.
- Автоматичните тестове трябва да работят стабилно. Независимо от времето на деня, тестовата среда и други системни настройки, изпълнението на тестовете трябва да води до един и същ резултат. Обикновено това се осигурява чрез работа с конкретни тестови данни с фиксирани системни настройки.
- Автоматичните тестове трябва да работят с приемлива скорост за вашия проект. Това време е индивидуално за всяка система. Някои могат да си позволят да работят цял ден, докато за други е критично да се впишат в секунди. Какви скорости сме постигнали в нашия проект, ще разкажа по-късно.
- Разработването на автоматични тестове трябва да бъде гъвкаво. Не е желателно да се отказваме от проверката на някаква функционалност просто защото не сме го правили преди или поради други убеждения. utPLSQL не поставя ограничения върху разработката, а Oracle по принцип позволява реализирането на най-различни неща. Повечето задачи имат решение, въпросът е само във времето и вложените усилия.
- Разгръщаемост. Имаме няколко тестови среда, където е необходимо да се стартират тестове. На всяка от средите в който и да е момент може да бъде обновен дамп с данни. Трябва да управляваме проекта с автоматичните тестове така, че да имаме възможност безболезнено да извършваме пълна или частична инсталация.
А в следващия пост след няколко дни ще разкажа какво сме направили и какви резултати сме постигнали.
Източник: habr.com
