Печалби:
- Способност да се попречи на изкуствения интелект да приеме погрешно поведение като „правилно“ чрез изчисляване на очакваната стойност в тестове на единица, независимо от правилото за приемане
- Възможност за отпечатване на бързи, независими и повторяеми тестове чрез прилагане на принципите AAA и FIRST и осмиване на външни зависимости
- Възможност за тестване на тестове с мутация (разбиване на код) и разпознаване на труден за тестване код като миризма на дизайн
Най-големият и най-бърз слой от пирамидата за тестване е тестването на единици - тестване, което проверява функция или малка част от кода изолирано от всичко останало. Хиляди модулни тестове се изпълняват за секунди и улавят грешка, докато кодът все още е на екрана на разработчика. Изкуственият интелект (AI) е може би най-умелият в създаването на единични тестове: вие му давате функция, AI произвежда десетки тестове. Но точно това удобство поражда най-големия капан: AI лесно създава тестове, които „светят в зелено, но не проверяват нищо“ или приемат текущото (може би погрешно) поведение на кода като „правилно“. В този модул ще научите как да пишете наистина защитни тестове на единица с AI и връзката между тестваем код и AI.
Качества на добър модулен тест: ПЪРВО
Добрите модулни тестове следват принципите FIRST: бързи, независими (тестовете не трябва да зависят един от друг), повторяеми (повтарящи се — един и същ резултат във всяка среда), самопроверяващи се (ясен успех/неуспех), навременни (навреме). Припомнете си тези принципи, когато карате AI да произвежда тестове; изрично поискайте тестът да не зависи от външния свят (реална база данни, мрежа, часовник), за да бъде "независим" и "повтарящ се".
AAA модел и изразително утвърждаване
Солиден единичен тест следва структурата на AAA: Подреждане (подготвяне — настройване на входове и зависимости), Действие (изпълнение — извикване на тестовата функция), Утвърждаване (валидиране — сравняване на резултата с очакваната стойност). Критичният е твърдят. Най-честата грешка, която изкуственият интелект прави е извличането на твърдението от изхода на тествания код – логиката „каквото кодът върне е вярно“. Това обезсмисля теста. Правилният начин е да се определи очакваната стойност независимо (от критериите за приемане, изчислете я ръчно).
Внимание: Ако кажете на AI "напишете тест за тази функция", AI може да изпълни функцията и да запише нейния изход като "очакван". Този тест преминава дори ако функцията е невярна. Вместо това кажете „вие изчислявате очакваните резултати съгласно тези правила, не препращайте към текущия изход на функцията“.
Подигравки, мъничета и зависимости
Единичното тестване изисква изолация. Ако вашата функция зависи от база данни или API, те се заменят с фалшиви обекти (mock/stub — контролиран, фиктивен заместител на истинската зависимост) при тестване. Това прави теста бърз, независим и възпроизводим. AI може да произведе фиктивна инсталация; Но внимавайте с прекомерното подиграване: ако се подигравате на всичко, тестът ще провери само „какво връща макетът“, а не действителната логика. Баланс: емулирайте външния свят, изпълнете реалната логика, която се тества.
Тестваемост и AI
Има интересна обратна връзка: код, който е труден за тестване, често е лошо проектиран код. Ако AI има проблеми с писането на тестове за функция (твърде много зависимости, скрито глобално състояние, странични ефекти), това е миризма на дизайн. Питането на AI "как бихте преработили този код, за да го направите тестваем" води както до по-добро тестване, така и до по-добър код.
Параметризирани тестове и разнообразие от данни
Писането на отделен тест всеки път за проверка на едно и също правило с различни входове е едновременно досадно и трудно за поддържане. Параметризирано тестване - структура, която многократно изпълнява една и съща тестова логика на списък от входове и очаквани резултати - елиминира това повторение: едно тестово тяло се захранва с десетки входни двойки. AI е много ефективен при изготвянето на тези таблици с очаквани резултати, когато му дадете вашите правила за приемане; По-специално, той систематично представя гранични стойности и класове на еквивалентност.
Но тук също има капан: AI има тенденция да извлича очакваните резултати в генерираната таблица от тествания код. Тази грешка е още по-опасна при параметризирано тестване, тъй като една единствена неправилна логика прави невалидни десетки редове. Затова винаги разполагайте с колоната с очаквани резултати, изчислена независимо според правилото за приемане и ръчно валидирайте поне няколко реда. Също така поискайте колона за описание „какво представлява всеки ред“; така че когато редът се счупи, веднага виждате кое състояние е счупено.
Съвет: Умишлено добавете „ред за прихващане“ към параметризираната тестова таблица — тоест, съзнателно погрешно въведете резултата. Ако тази линия не стане червена, когато стартирате теста, вашият тест всъщност не проверява тази ситуация. Това е бърза фиктивна проверка.
Слаба подкана / Силна подкана
Слаб: „Напишете модулен тест за тази функция.“
Силно: Напишете [език/рамка] единични тестове за функцията "taxCalculate(сума, ставка). Правило за приемане: резултат = сума * ставка, закръглена до 2 знака след десетичната запетая; отрицателна сума или ставка извежда грешка; връща 0, ако скоростта е 0. Използвайте AAA структура. Ръчно изчислете очакваните стойности според ТЕЗИ правила; не препращайте към текущия изход на функцията. Покрийте обвързани и отрицателни случаи (0, отрицателен, много големи, заоблени до десетични знаци). Нека името на всеки тест описва правилото, което проверява.
Мощна подсказка; Той дава правилото за приемане, независимо очакване на очакваната стойност, структура и крайни случаи. Така тестът се превръща в пазител на правилото, а не в огледалото на кода.
Таблица за качество на единичните тестове
симптом
Лош тест (фалшиво доверие)
добър тест
твърдят
Няма или „не е нула“
Очаквана конкретна стойност
Очакван източник на стойност
Изход на функцията
Правило за приемане / ръчно изчисление
пристрастяване
Действителен DB/мрежа/час
Изолиран с макет/пън
ръб случай
Само щастлив път
граница, отрицателна, грешка
Когато разбиете кода
остава зелено
става червен
Име
test1, testMethod
описва правилото, което потвърждава
Четири копируеми шаблона
1) Единично тестване, управлявано от правила:
Вашата роля: старши софтуерен тестов инженер. Напишете единичен тест на следната функция с [език/рамка]: [подпис]. Правила за приемане: [правила]. - Използвайте AAA структура. - Ръчно изчисляване на очакваните стойности според ТЕЗИ правила; НЕ препращайте към текущия изход на функцията. - Покрийте лимита, отрицателния, грешката и щастливия път с отделни тестове. - Нека всяко име на тест описва правилото, което проверява. - Макет на външни зависимости; Накарайте действителната логика да работи.
2) Контрол на устойчивостта на мутации:
Вижте тези единични тестове. Избройте 5 дребни корекции, които мога да направя в тествания код (a - вместо +, a >= вместо >, изместване на границата) и ми кажете за всяко от тях КОЙ от тези тестове ще стане червен? Ако нито един не бъде върнат, тестът е недостатъчен. Код + тестове: [поставяне]
3) Преглед на възможността за тестване:
Защо е трудно да се напише модулен тест за тази функция? Скрита зависимост, глобален статус, странични ефекти, има ли много отговорности? Предложете минимален рефакторинг, за да го направите тестваем; не променяйте поведението си. Код: [поставете]
4) Непълно завършване на сценария:
Дадени са следните функции и налични тестове. Избройте кое поведение/edgecase НИКОГА не е тестван (пропуск в обхвата) и добавете тест за всеки. Функционални+тестове: [поставяне]
три мини калъфа
Случай 1 — Тест за отразяване на кода. Разработчик накара AI да напише тест за функцията за закръгляване; 10 теста бяха зелени. Всъщност функцията беше закръглена в грешна посока, но AI беше взел очакваните стойности от изхода на функцията, така че тестовете счетоха грешката за „вярна“. Когато очакваните стойности бяха изчислени ръчно с шаблона, управляван от правила, 4 теста станаха червени и истинската грешка беше разкрита.
Случай 2 — Стойността на контрола на мутациите. Един екип разчита на 45 единици тестове. Опитах 20 незначителни корекции на кода с „проверка за устойчивост на мутации“; тестовете са уловили само 11 от тях. Останалите 9 смущения преминаха тихо. Екипът засили слаби тестове; Действителна грешка в изчислението беше уловена от тези подобрени тестове в следващото издание.
Случай 3 — Нетестваемостта е миризма на дизайн. AI не можеше да напише тестове за функция за подреждане, постоянно се нуждаеше от истинската база данни. Шаблонът „преглед на възможността за тестване“ показа, че функцията включва достъп до база данни. Когато инжектирането на зависимости беше премахнато, можеха да се пишат тестове и кодът стана по-чист.
Често срещани грешки
- Извличане на очакваната стойност от код. AI приема изхода на функцията като "правилен"; тест, който потвърждава грешен код.
- Тествайте без твърдение или с тривиално твърдение. "Той не издаде грешка, той премина" логика; Не потвърждава нищо.
- Изключителна подигравка. Осмиване на всичко и тестване само на това, което макетът връща; истинската логика не се тества.
- Само щастливия път. Заобикаляне на гранични, отрицателни и грешки състояния.
- Без тестване чрез разбиване на кода. Доверяване на зелено без проверка за мутация.
- Игнориране на нетестваемостта. Неразпознаване и коригиране на лош дизайн, вместо налагане на усилено тестване.
В обобщение
Единичните тестове са най-бързият и най-големият слой от тестовата пирамида; Хваща грешката в най-евтиния момент. AI е много способен да произвежда модулни тестове, но най-големият му капан е писането на тестове, които приемат неправилно поведение като „правилно“, като извличат очакваната стойност от самия код. Решение: дайте правилата за приемане, изчислете очакваните стойности ръчно, наложете принципите AAA и FIRST, подигравайте се на външния свят и стартирайте действителната логика и тествайте всеки тест чрез мутация (разбиване на кода). Кодът, който е труден за тестване, е знак за дизайн, който се нуждае от коригиране.
Задача за приложение
Изберете функция, която съдържа бизнес правило от вашия собствен проект. Напишете правила за приемане и направете тестове за писане на AI с шаблона „тестване на единици, управлявано от правила“; Изчислете очакваните стойности ръчно. След това приложете „проверката за устойчивост на мутациите“: направете поне 5 малки прекъсвания в кода и измерете колко теста стават червени. Добавете нов тест за неуловени повреди. Докладвайте колко смущения са били уловени (като резултат на мутация).
контролен списък
- [ ] Дадох правилата за приемане и изчислих ръчно очакваните стойности.
- [ ] Уверих се, че тестовете не извличат очакваната стойност от кода.
- [ ] Установих независимо тестване, следвайки указанията на AAA и FIRST.
- [ ] Подиграх се на външните зависимости и изпълних действителната логика.
- [ ] Покрих случаи на ограничение, отрицателни и грешки.
- [ ] Чрез разбиване на кода (мутация) доказах, че тестовете наистина защитават.