Boundary Value Analysis. Чи дійсно легко відразу перевірити всі границі, та наскільки ефективно з цим може допомогти AI

💡 Усі статті, обговорення, новини про тестування — в одному місці. Приєднуйтесь до QA спільноти!

Привіт, спільното! Мене звати Женя, наразі я Lead QA у GlobalLogic, і це моя друга стаття на DOU, але перша солов’їною. У тестуванні я вже 7 років і за цей час довелося попрацювати і з desktop, і з automotive, і з web, чим зараз частково і займаюся (чому частково? Бо проєкт пов’язаний із залізом, і не все чистий web).

У цій статті хочу більш детально поговорити про таку техніку тест-дизайну, як граничні значення (Boundary Value Analysis, BVA). Усі добре знають, що BVA часто (читайте «майже завжди») використовують разом із такою технікою, як класи еквівалентності (Equivalence Partitioning, EP). Утім, цього разу я хотів би зупинитися окремо на BVA: чи дійсно, побачивши якесь поле, достатньо просто перевірити [min-1, min, max, max + 1] значення і сказати, що я молодець, упорався і все гарно зробив? А для цікавості експерименту будемо задавати питання до ChatGPT паралельно з нашим дизайном, щоб порівняти результати.

Ця практична стаття буде корисна всім, хто хоче почати використовувати свої теоретичні знання на практиці, розширити свій кругозір на наче просту річ, але водночас таку, що містить у собі підводні камені, а також тим, хто хоче просто освіжити знання чи повторити.

Що таке BVA

Для початку — трошки теорії. За ISTQB Glossary, BVA — це black-box техніка для тест дизайну, при якій тестові випадки розробляються на основі граничних значень. Іншими словами — це техніка тестування ПЗ, яка фокусується на перевірці поведінки системи на межах допустимих діапазонів вхідних даних. Ідея полягає в тому, що помилки частіше виникають на кордонах цих діапазонів, ніж усередині них.

Як я вже згадував, ця техніка є доповненням до тестування за допомогою класів еквівалентності (Equivalence Partitioning), яка ділить вхідні дані на групи (класи) з очікуваною однаковою поведінкою системи. BVA натомість деталізує перевірку саме «біля» цих меж.

Фактично, ми можемо використати цю техніку для тих значень, які можемо представити в чисельному вигляді:

  • Числові атрибути нечислових змінних. Наприклад, у вас є застосунок, що дає змогу зберігати текст. Текст це число? Ні, але текст має якусь довжину (для прикладу «текст» містить 5 літер «т» «е» «к» «с» «т» — його довжина буде 5). І вже з цим можна щось робити:)
  • Розмір фізичних об’єктів, наприклад, пам’яті. Мабуть, ви колись стикалися з тим, що потрібно кудись завантажити файл, але система видає помилку — «файл занадто великий для цієї дії».
  • Тривалість дій. Наприклад, у застосунку, який ми зараз розробляємо, є обмеження за часом: після певного часу бездіяльності користувача поверне на початковий екран.
  • Інші числові параметри, такі як кількість повідомлень або циклів у коді — все залежить від того, як дивитись на речі.

Далі нам треба вибрати підхід, який ми хочемо використати: two-value boundary чи three-value boundary testing. Тут вже залежить від контексту вашого застосунку, ваших звичок і часу, який є на тестування.

Two-value boundary і three-value boundary testing

Особисто я в 99.9% випадків залишу свій вибір на three-value boundary testing, бо так мені спокійніше. Але, знову ж таки, тут у гру може вступити EP і сказати, що підхід вже буде exhaustive / overload. У цьому контексті мені подобається фраза з книги Lee Copland — A Practitioner’s Guide to Software Test Design: (далі те, як я це зрозумів) «У кожного з нас є свій досвід, теорія лише каже те, що треба перевірити обов’язково. А те, що виходить на практиці — вирішуєте ви самі».

Зазирнемо в ISTQB Syllabus, що він говорить про two-value та three-value: при тестуванні граничних значень за методом двох значень (two-value boundary testing) використовуються граничне значення (на межі) та значення, яке знаходиться безпосередньо за межею (з найменшим можливим приростом, виходячи з необхідної точності). Для тестування граничних значень за методом трьох значень (three-value boundary testing) використовуються значення перед границею, на границі та за границею.

Як на мене, найцікавіше тут починається з фразою «з найменшим можливим приростом, виходячи з необхідної точності». На практиці мені інколи доводиться проводити співбесіди на проєкт. І більшість людей перед тим, як дізнатися, який таки дозволений мінімальний крок, просто беруть +/- 1 від границі. Тобто якщо у мене границя 0 — відразу кажуть тест [-1, 0, 1], не поцікавившись, який тут потрібен крок. Можливо, такий підхід пропустить якісь дефекти, бо треба було перевірити [-0.9, 0, 1.1]? Тому моя порада, як для співбесід, так і на проєктах: завжди треба тримати в голові питання про «можливий» та «дозволений» крок.

І на завершення, щоби ми повністю налаштованими приступили до практики, пропоную зупинится на понятті sub-boundaries. Цю тему, як на мене, гарно зачепив Ron Patton у своїй роботі Software Testing. Книжка трошки стара і не думаю, що зараз є багато проєктів, де аж так сильно занурюються у порівняння даних, але дуже раджу ознайомитись. Тож, що для нас означає це поняття? У будь-якій границі значень можуть бути ще якісь свої власні границі. Візьмемо той самий приклад: для значень [-1, 0, 1] числа —1 та 1 взагалі можуть бути частинами інших границь. Тому раджу завжди пам’ятати, що видимі границі можуть приховувати додаткові, менш очевидні «підграниці», які потребують окремої уваги при тестуванні.

Від теорії до практики. Розбір BVA та Sub-boundaries на прикладі інтернет-магазину

Розглянемо, як користуватися технікою BVA на прикладі класичного інтернет-магазину, де, додавши до кошика товар, можна змінювати його кількість. Тож параметри в нас такі:

  • мінімальне замовлення — це 1 шт. товару;
  • максимальне — 100 шт;
  • можна додавати або віднімати товари натискаючи кнопку + або -;
  • кількість товару — це поле вводу, в яке ми можемо самі ввести те значення, яке нас цікавить. Поле може містити лише числові значення.

Для прикладу візьму скріншот з популярного маркетплейсу (на якому карма тестувальника працює проти мене і часто робити замовлення просто боляче):

Тепер маємо визначити:

  1. Який у нас тут крок? Товар можна додавати по 1 шт., тобто крок — 1.
  2. Які у нас границі? Поле може приймати лише числові значення від 1 до 100 включно. Тобто min = 1, max = 100 — це наші границі.

Відповідно, набір тестів для:

  • two-value boundary буде [min — step, min , max, max + step] = [0, 1, 100, 101]
  • three -value boundary буде [min — step, min , min + step, max — step, max, max + step] = [0, 1, 2, 99, 100, 101]

Давайте тепер подивимось, що для цієї задачі нам скаже ChatGPT.

P.S. пам’ятаємо про sub-boundaries, просто зараз збудуємо наш каркас.

P.S.S. тут я погрався, задаючи різні параметри вхідних значень штучному інтелекту: як тестувальник, і як просто людина, яка хоче перевірити функціонал.

Чат почав тестувати кнопки +, - шукати не валідні значення і підбирати різні комбінації для вводу, але відповіді його трошки відрізнялися. Додаю скріни, в більшості для boundary value analysis:

1. Для людини, якій треба було перевірити поле вводу кількості товарів:

2. Для тестувальника, якому потрібно протестувати поле вводу кількості товарів:

3. Додатково для тестувальника — декілька кейсів про некоректні дані:

* Скріни, як тестувати кнопки «+» та «-» — пропускаю.

Як бачимо, ChatGPT нас не попереджає про жодні підводні камені у вигляді sub-boundaries. Звісно, його відповідь залежить від того, що ми йому задаємо — саме для цього і розбираємо цю задачку :)

Давайте разом пригадаємо: чи було у вас таке, що ви вже сформували або формуєте замовлення і хочете купити, наприклад, 50 одиниць товару? І в якийсь момент у вас вилазить помилка «out of stock». Знайомо?)

Це і буде нашою першою sub-boundary. Вона якраз знаходиться в межах нашого діапазону. Тобто тепер у нас границі не 1-100 а, відповідно, від 1 до 100 або до кількості товару, що лишилась на складі, якщо залишку менше, ніж 100 одиниць. І тепер до границь додалась ще одна — in stock, яка може бути у таких межах: від 0 (відповідно, ми не можемо сформувати замовлення) до будь-якого значення більше ніж 100, що не вплине на наші границі.

Виходячи з цього, які наші можливі сценарії для тестування:

  • In stock < min value (1) — цей кейс у нас наче і покритий в початковій таблиці, але на нього хотілось би окрему помилку. Не про те, що ми вводимо щось не валідне, а про те, що товар закінчився.
  • Min <=In stock <= max — в даному випадку у нас In stock змінна може виступити як значення max.
  • In stock > max value (100) — фактично, цей кейс у нас покритий в початковій таблиці, але буде залежати, яка у вас валідація на полях.

Який набір тестів для наших нових границь:

CASE 1 In Stock < min value (1):

У такому випадку ми взагалі не повинні мати можливість додати товар у кошик.

CASE 2: Min <= In Stock <= max (уявимо, що залишок на складі — 50 одиниць)

two-value boundary буде [min — step, min , stock, stock + 1 , max, max + step] = [0, 1, 50, 51, 100, 101]

three -value boundary буде [min — step, min , min + step, stock-1, stock, stock + 1, max — step, max, max + step] = [0, 1, 2, 49, 50, 51, 99, 100, 101]

Бачимо, що тут залишились значення більші за 50. Логічно, що ми їх не зможемо ввести або будемо бачити якийсь еррор. Але питання тут — а який еррор показати для значення 101? «Немає товару на складі» чи «ввели значення, більше за допустиме»? Або ж ми вирішимо повернути значення на допустиме — тоді яке в цьому випадку буде допустиме, 100 чи 50? Тобто, фактично, розширена границя лишається [0, 1, 2, 49, 50, 51, 99, 100, 101], але які значення ми можемо скоротити з цього списку — вже буде залежати від реалізації вашого застосунку (які валідації існують, щоб, використавши EP, зменшити кількість кейсів).

CASE 3: Stock > max value (100) наші початкові тести залишаються незмінними:

two-value boundary буде [min — step, min , max, max + step] = [0, 1, 100, 101]

three -value boundary буде [min — step, min , min + step, max — step, max, max + step] = [0, 1, 2, 99, 100, 101]

P.S. Але з цим кейсом будьте пильні. Якщо ваша реалізація застосунку буде дозволяти вводити великі значення — можливо, треба буде перевіряти [stock-1, stock, stock + 1].

А що на це відповів чат:

Здається, майже розібралися. Але є ще декілька моментів, від яких будуть залежити наші sub-boundaries (до речі, GPT щось схоже хотів перевірити у TC17):

  1. Яка у нас валідація UI: якщо я ввожу значення 101, мені видає помилку чи змінює значення на 100?
  2. Очевидно, якщо ви тестуєте застосунок, у вас є змога взаємодіяти з вашим API, що, своєю чергою, дає змогу напряму працювати з беком, оминаючи валідації фронта.

З цього виходить, що в нас є ще як мінімум 1 sub-boundary — це максимальне значення, яке може приймати це поле. Але постає питання — як його дізнатися? Тут можливі декілька варіантів:

  • Запитати когось на проєкті, хто володіє цією інформацією (в основному — це деви).
  • Якщо маєте доступ до бази даних, можете написати такий запит, щоб дізнатися: Select column_name, data_type, character_maximum_length FROM information_shema.columns WHERE table_name = ‘your_table_name’. У цьому випадку в колонці character_maximum_length у вас буде максимальне значення, яке може бути збережено в базі даних. Звертаю увагу, що дане поле може бути null — це буде означати, що технічно довжина не обмежена.
  • Переглянути документацію API (так, у когось буває документація на все). Виглядати це може так:

Тут нас буде цікавити саме шматочок, де є значення min і max — відповідно, мінімальне і максимальне значення, яке система може прийняти. А також формати, з яких можна буде вибрати ще 1 sub-boundarie (кому цікаво тестування веб API, я б порекомендував почати з читання цієї книги):

Логічним буде питання: а нащо взагалі це тестувати, якщо більше 100 одиниць товару в замовленні не можна буде сформувати? На своїй практиці я вже декілька разів стикався з такою проблемою, що поле, яке логічно не повинно містити більше ніж n символів, може приймати у себе набагато більше значення — і тестування n+1 не покаже цю помилку. Але, якщо дивитись на ту границю як максимально допустиме значення для поля, то там частенько бувають креші, що дуже неприємно і може відлякати вашого користувача. І не кажіть, що у вас ніколи не було кейсу, що ви хотіли щось копіпастнути та вставляли великі дані не туди, куди треба.

Давайте зараз обмежимось максимальною довжиною, що може містити поле: нехай це буде 4 символи. Тобто максимальне значення — це 9999. Візьмемо найбільший наш випадок і доповнимо його ще 1 границями, відповідно до того, що може містити поле:

two-value boundary буде [min — step, min , stock, stock + 1 , max, max + step, field_limit, field_limit + 1] = [0, 1, 50, 51, 100, 101, 9999, 10000]

three -value boundary буде [min — step, min , min + step, stock-1, stock, stock + 1, max — step, max, max + step, field_limit — 1, field_limit, field_limit + 1] = [0, 1, 2, 49, 50, 51, 99, 100, 101, 9998, 9999, 10000]

Ось що на це каже чат:

Тепер порівняємо, що виходить в нас, а що у чата:

three -value boundary буде [min — step, min , min + step, stock-1, stock, stock + 1, max — step, max, max + step, field_limit — 1, field_limit, field_limit + 1] = [0, 1, 2, 49, 50, 51, 99, 100, 101, 9998, 9999, 10000] = 12 кейсів

Так, ми тут не перевіряли функціонал кнопок +/- (бо в нас і не було цієї задачі, ми дивились саме на граничні значення). І так, цей список можна скоротити до two-value boundary, який має менше кейсів, а потім з нього видалити значення, які знаходяться в одній EP (equivalence partition). Але тут все залежить від вас і вимог, які вам ставлять.

P.S. Звертаю увагу, що мета — саме розібрати границі та можливі підграниці. Якщо б довелося тестувати, то треба було б перевірити на ввід і текст, і символи, і null, і 1e+2 формат тощо.

Ось відповідно результат чату:

P.S. Цю задачу декілька разів проходив з чатом. Як писав вище — все залежить від умов, які ми початково задамо. З цікавого: лише 1 раз чат додав підграницю у вигляді максимально допустимого значення для поля, але нічого про залишок на складі. Втім, коли попросити його написати сторю на це, то тут він вже додає про залишок на складі. Довіряй, але перевіряй :)

Висновки

Тож у цій статті ми детально розібралися, що таке Boundary Value Analysis (BVA), чому важливо виходити за межі звичних значень [min-1, min, max, max+1] та враховувати «підграниці» (sub-boundaries) для повноцінного тестування. Цей підхід до тестування граничних значень допоможе вам покращити якість вашого застосунку. Його можна застосовувати для тих значень, які можемо представити у чисельному вигляді (вікового обмеження у соціальних мережах, лімітів кредитних карток у банківських системах, температурних діапазонів у медичних приладах, допустимого рівня шуму у застосунках для звукозапису або ж кількості гравців у онлайн-іграх та багатьох інших варіацій). А які будуть підграниці — залежатиме вже від вашого застосунку.

Ми також побачили, як AI, зокрема ChatGPT, може бути гарним помічником, але не замінює глибинного розуміння контексту та критичного мислення тестувальника. Чату треба правильно ставити вимоги залежно від до того, що хочете отримати в результаті. АІ не звільняє тих же trainee, що зараз линуть думати про те, що можна закинути все в чат і отримати відразу правильний результат.

Світ дійсно змінюється і, на мою думку, тепер людей, які детально розуміють, що вони роблять і чому саме так — повинні почати цінувати ще більше, бо рев’ю проробленої роботи ніхто не відміняв. І, все ж таки, поки що ми рухаємось від підходу «створення речей людиною для людини» до «від людини та АІ для людини», а не «від АІ для АІ».

В багатьох книжках завжди кажуть, що важливо, який фундамент ви закладете, і вже від цієї бази відштовхуватись. Ніколи не пізно повернутись до бази, освіжити знання і, можливо, десь доповнити та відточити їх. Головне пам’ятати, що тестування залежить від контексту і ні один шаблон не можна натягувати на все.

А з якими sub-boundaries ви стикалися на своїй практиці? Чи, можливо, ви зараз пішли і протестували те, на що ще не дивились? Знайшли щось цікаве?

👍ПодобаєтьсяСподобалось12
До обраногоВ обраному4
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Дякую за статтю! Дуже детальний приклад, я думаю багато кому корисно буде. Але я не зрозуміла sub-boundaries, для мене всі приклади з sub-boundaries виглядають як просто окрема вимога, яка має свої окремі BVA. І вони накладаються бо працюють з одним полем, але нащо називати це sub-boundaries?

Дякую за ваш коментар.

Так, ви праві — ви можете розглядати це все як окремі вимоги, які можуть перекривати одна одну, і просто покривати кожен окремий випадок відповідними кейсами. Але чи дійсно у вас будуть окремі сторі про все це? Чи, швидше за все, буде лише одна, в якій у кращому випадку згадають про кількість товару та ліміт на складі, а про решту вам, як інженеру, треба буде «здогадатися»?

Якщо йти по задукоментованій термінології ( glossary.istqb.org/...​&exact_matches_first=true ) то терміну sub-boundaries ви не знайдете, але для цього було посилання на книгу Software Testing де зачіпають цю тему.

Для чого це так називати? Давайте спробуємо подивитись на це під іншим кутом.Наприклад кастомер щось захотів — під цю потребу створюється «epic». Так, саме його ми згодом віддамо в реліз, але — це лише загальне уявлення про те, що хоче замовник. Далі цей «epic» розбивається на умовні «feature» — тут вже більш детально описано, що саме потрібно реалізувати, але це все ще досить високорівневий опис. Тому у нас є «user story». У user story вже достатньо конкретики, і зрозуміло, що саме треба реалізувати, але й на цьому рівні залишаються технічні деталі, які вже описуються в задачах для інженерів. По факту «epic», «feature», «user story», «task» — це окремі задачі але «task» це підзадача для «user story» яка в свою є чергою є підзадачею для «feature», яка в свою чергу до «epic» — тобто кожен має свою якрему назву, але є підзадачею для чогось більшого. Чи можемо ми кожну підзадачу розцінювати як окрему — так, звісно, можемо, але чи побачимо при цьому загальну картину? Те саме і з границями тут у нас є 1 границя це тип поля і далі ми цю границю обмежуємо під задачами. Сподіваюсь мені вдалося донесту свою логіку.

Благодарю за статью. Но уж очень растекаясь * мыслью по древу*.

Женя, дякую за корисну статтю!

Дякую. Гарна стаття. Про instock value треба пам’ятати — це дуже гарний кейс.
Якщо дозволите трохи понудіти, бо я трохи не зрозумів: якщо в нас є поле price на бекенді, яке може прийняти макс 9999.99, то чи ми маємо додати ще перевірку на випадок якщо у нас і кількість 1-100 і в instock value попадає, але сумарно коштує більше 9999.99 (ну там 2 штуки по 5000, чи 100 по 100, або взагалі одна 10001 — але це вже, мабуть зовсім аут, бо тоді як воно проєктувалося не зрозуміло)? І ще, якщо в нас бекенд може обробити тільки quantity до 100 од, а ми на фронтенді вважаємо, що 4 символи у полі вводу — це ок, то знову ж таки трохи не зрозуміло, що покупець побачить, коли введе чотирьохзначне число і за нашою логікою фронтенд його пропустить, а бекенд ні?

Дякую за ваш коментар.
Значення максимальної ціни 9999.99 було наведено просто як приклад, щоб показати, як може виглядати документація API.
Якщо відповідати на ваше питання, маючи дві границі, які треба враховувати:
— кількість товару,
— максимальна дозволена ціна товарів у кошику,
то у такому випадку треба додавати тестові кейси залежно від значень обох границь. При цьому використовувати лише BVA (Boundary Value Analysis) вже не так зручно для комбінування обмежень. У цьому випадку краще розглядати комбінацію різних технік тест-дизайну. Той же domain analysis був би більш наглядніший у такому кейсі і зручніший для використання.
Щодо валідацій у нас можливі різні сценарії:
1) валідація лише на фронтенді — якщо при введенні значення, більшого ніж дозволено, користувачу показується відповідна помилка для прикладу
2) валідація на бекенді — вводимо що хочемо, але при відправці запиту сервер перевіряє коректність у відповідному полі і, якщо щось не так видаємо помилку
3) валідація і на бекенді, і на фронтенді
І вже від того, що у вас в системі реалізовано залежать і перевірки, які ви будете закладати. Те, що саме побачить покупець при спробі ввести щось не валідне, залежить від реалізації: це може бути і модальне вікно яке скаже ай-ай-ай, якась підсвітка поля +хінт, що покажуть, щось тут не так, можливо просто не дасть ввести не коректні значення, або при вводі некортного юуде автоматичне виправлення на якесь коректне значення, все залежить від того що закладуть в систему

Дякую за змістовне і розлоге пояснення

Підписатись на коментарі