×

Що не так із застосуванням техніки «Аналіз класів еквівалентності»

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

Привіт, шановні колеги. Мене звати Володимир Поздняков. Я QA-інженер з майже 6-річним стажем роботи в аутсорсі. Починав з ручного тестування, виріс в QA Lead, а зараз більшу частину часу займаюсь автоматизованим тестуванням.

Отже, якщо з формальною, не дуже цікавою частиною покінчено, перейдімо до теми розмови, а саме: «Техніки тест-дизайну».

Попри те, що я займаюсь автоматизацією, маю для вас не дуже втішну новину: успіх якості та достатності автоматизованого тестування залежить в більшості випадків не від кількості та якості коду, який ви пишете, а саме від адекватного та грамотного тест-дизайну, аналізу та планування.

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

Своєю статтею я хотів би разом з вами дійти до розуміння того, що не так, і чому техніки тест-дизайну використовують невірно або розуміють їх не до кінця. І щоб не бути безапеляційно правим, моїм опонентом в цій дискусії буде всім відомий експерт Легковайті Тестущенко.

Приклади тест-дизайну, в яких щось пішло не так

Я: Пропоную розглянути три найбільш розповсюджені техніки тест дизайну: класи еквівалентності, аналіз граничних значень та попарне тестування.

Легковайті Тестущенко: Пфф. Легко! Це саме зрозуміле і легке, що може бути. Це ж основа основ, яку всі розуміють.

Я: То може ти розповіси нам, що ж воно таке? Почнімо з аналізу класів еквівалентності.

Легковайті Тестущенко: Тю, я ж не ботан якийсь, зараз загуглю... Отже, ось що нам кажуть деякі ресурси з всемогутнього інтернету:

Клас еквівалентності (equivalence class) — набір даних, обробка яких призводить до одного й того ж результату.

Клас еквівалентності — це набір значень змінної, який вважається еквівалентним.

Суть дуже проста — всі вхідні тестові дані розбиваються на групи (класи), що викликають однакову поведінку програмного забезпечення.

Ну, думаю, цього досить, і так все зрозуміло.

Я: Маєш рацію, визначення доволі зрозумілі — якщо будь-яке значення з діапазону призводить до одного і того ж результату, то ми вважаємо цей діапазон класом еквівалентності. Але давай все ж розглянемо на деяких прикладах.

Розглянемо простеньку функціональність:

Передумови: вік користувача — позитивне цілочисельне значення від 0 до 100, і валідується іншою функціональністю.

Функціонал: якщо вік користувача менший за 18 років — не дозволяти доступ до сайту. Якщо 18 і більше, то дозволяти користуватися сайтом.

Що ми тут маємо?

Легковайті Тестущенко: Очевидно, що два класи еквівалентності:

  1. від 0 до 17 включно;
  2. від 18 до 100 включно.

При будь-якому значенні від 0 до 17 включно система не повинна пропускати користувача, а отже будь-яке значення з першого класу повинно призводити до одного й того ж результату — не пропускати користувача. Те ж саме справедливо і для другого класу. То ж все вірно в інтернеті з визначеннями.

Я: Так, згоден. Це класичний метод використання цієї техніки в якості black-box підходу. І реалізація такої умови, скоріше за все, буде доволі стандартною, щось на кшталт:

const isAccessAllowed = (age: number): boolean => {
    return age > 17;
}

І що ж в результаті? Скільки нам буде потрібно тестів, щоб перевірити функціонал за цією технікою тестування?

Легковайті Тестущенко: Ну, мінімум, два тести, по одному значенню з кожного класу, наприклад 8 та 50 років.

Я: Ти кажеш «мінімум два тести». Отже, може бути і максимум? Що ти маєш на увазі?

Легковайті Тестущенко: Ну... Я кажу, що нам точно треба перевірити хоча б по одному значенню, але якщо у нас є час і можливість, то можна взяти не по одному тесту з класу, а, скажімо, по 3-5.

Я: Он як! То ж якщо будемо мати час — будемо тестити скільки влізе, як ні — обмежимось двома?

Легковайті Тестущенко: Ну, якость так...

Я: От що я тобі скажу, а ти запам’ятай раз і на завжди. Це повна дурня! Будь-яка техніка тест-дизайну покликана зменшити зусилля на тестування, і при цьому гарантувати належну якість. Тому, якщо ми вірно виділили класи еквівалентності, немає жодної причини витрачати час на проходження більшої кількості тестів ніж один на кожний клас еквівалентності — бо це буде марна трата часу.

Легковайті Тестущенко: Ага, має сенс... Зрозумів.

Я: А давай тоді ще один приклад:

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

Функціонал: оскільки модель взуття лише одна, то базова ціна взуття одна, але в залежності від розміру застосовується націнка: немає націнки на взуття від 38 до 41 розміру, 10% — на взуття від 42 до 45 розміру, 20% — на взуття від 46 до 50 розміру.

Легковайті Тестущенко: Та все те ж саме! Не мороч мені голову! Буде три класи:

  1. 38 — 41;
  2. 42 — 45;
  3. 46 — 50.

Я: Тобто, за умов техніки еквівалентного розділення, ти б взяв лише три значення для перевірки, і виконав лише три тести?

Легковайті Тестущенко: Так, я пам’ятаю, що більше і не треба. Бо саме цього ж нас вчить ця техніка, що не потрібно перевіряти всі значення, а достатньо взяти лише по одному з класу еквівалентності.

Я: А якщо я тобі скажу, що можливий такий варіант, що обов’язкових перевірок треба буде зробити не 3, а 13 — тобто, по одній для кожного розміру.

Легковайті Тестущенко: Що за чухня! Навіщо? У вимогах же чітко сказано, що кожні з діапазонів розмірів повинні призводити до свого результату, що повністю відповідає визначенню класів еквівалентності.

Я: В тому і проблема... Визначення техніки і опис вимог повністю вказують на приналежність до цієї техніки. І підхід тестування лише з позиції black-box може і часто призводить до таких втрат необхідних перевірок. Бо реалізація в цьому випадку може бути на рівні, наприклад, баз даних. Тобто коефіцієнт націнки буде визначатись для кожного з розмірів, і теоретично можливо допустити помилку у будь-якому з розмірів при оновленні значень в таблицях. А отже, в цьому випадку ми не можемо стверджувати, що маємо чітку множину значень, які призводять до одного і того ж результату, бо з такою реалізацією кожен розмір — це самостійний клас еквівалентності, хоч і складається з одного значення.

Легковайті Тестущенко: Ох, йой...

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

Замість висновку

Щоб правильно аналізувати і використовувати техніки тест-дизайну, потрібно знати і розуміти, на якому підґрунті стоїть основа реалізації, а у випадку розробки ПО — це код або архітектурні рішення. А також, якщо ви вже точно і правильно вирахували класи еквівалентності, то не треба перевантажувати свої перевірки додатковими непотрібними тестами, просто аби «про всяк випадок».

Дякую за увагу. В наступній статті поговоримо про «проблеми» з аналізом граничних значень.

👍ПодобаєтьсяСподобалось23
До обраногоВ обраному13
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
бо з такою реалізацією кожен розмір — це самостійний клас еквівалентності, хоч і складається з одного значення.

Це системна похибка, тому з вами майже всі сперечаються)
Треба або реалізацію міняти, або додавати юніт тести, або поспілкуватися тест-ліду і техліду про архітектуру, тощо.
Тестувальник не повинен робити повне тестування кожного елемента бази даних, бо це не ефективно і втрачається сенс класів еквівалентності взагалі.
( Якшо це не справжній рокет сайенс, но там використовується найчастіше waterfall model розробки, це інше)

Ну, навскидку, в 1-й задаче классов эквивалентности немножко побольше:
От минус бесконечности до 0 не включая (в отличие от реакции на следующий класс, тут система должна выдать ошибку ввода данных);
От 0 включая до 17 включая;
От 18 включая до плюс бесконечности.

Ну и, как уже много раз повторяли, техника классов эквивалентности — это техника black-box, она как раз и рассчитана на то, что использующий её не имеет знаний / доступа к имплементации. Иначе используем другие техники.

Було зазначено, що «вік користувача — позитивне цілочисельне значення від 0 до 100, і валідується іншою функціональністю.» тому і не перевіряємо ±безкінечність.

Тем более. Если ещё и 100 есть (провтычил дочитать, мой бок) — то добавляем класс «от 100 от плюс бесконечности». То, что система обязана обрабатывать значения от 0 до 100, ничего не говорит о том, какие значения она может принимать.
Тесты на ввод значений, выходящих за пределы разрешённого диапазона называются негативными. Задача этих тестов — проверка системы на корректную реакцию на такие значения (или невозможность ввода оных). И пишутся они как раз с помощью EP + BVA техник.

13 тест-кейсів для чорно-ящичного тестування забагато. Автор малює табличку — це вже сірий ящик. Націнка може не зберігатися в БД а розраховуватися «на льоту». Якщо націнка все ж зберігається для кожного розміру, то на таку розробку треба заповнювати не 13 тест-кейсів, а один баг-репорт (або ж пропозицію про покращення по формі баг-репорту): Правильна модель даних замість однієї таблички (id,size,coefficient) містить дві sizes(id,size) і coefs(coef,size_min,size_max). А та сама табличка може бути отримана «на льоту» через SQL-запит select id,size,isnull(coef,1) as coefficient from sizes left join coefs on size between size_min and size_max;

Тест-кейс для покращеної моделі повинен перевіряти, чи не можуть перетинатися діапазони для коефіцієнтів: негативний тест — вводимо в coefs (42, 45, 1.1) та (45, 50, 1.2) — програма повинна зафіксувати помилку «перетин діапазонів».

Якось так.

⚠️Автор вводить читача в оману⚠️
✅ По-перше, визначення техніки класів еквівалентності спрощене, що призводить до неправильного розуміння. Класи еквівалентності — техніка тестування чорного ящика (black box). Тобто, використовуючи її, ми не маємо знати, як софт влаштовано, нам достатньо опису його поведінки.
✅ По-друге, в сценарії із взуттям, автор ігнорує той факт, що умовні розробники створили продукт, що суперечить вимогам, тобто — баг🐞Саме те, що націнка задається не формулою, як написано, а береться з бази, має бути повідомлене і виправлене.

Дякую за коментар.
1. Так, це техніка черного ящика. І в кожному коментарі бачу, що всім дуже подобається цим прикриватися. І коли QA інженер звикає прикриватись такою відповідю, щоби не розширювати своє розуміння в тому як реализований продукт, який він первіряє, і чи насправді правильно визначені класи еквівалентності — цей факт мене дуже засмучує.
Безумовно, якщо у тестувальника немає ніякої можливості в доступі до коду чи бази даних, то все що залишається це black box, але з досвіду знаю, що в більшості випадків тестувальник має можливість але не має бажання вникати в технічні аспекти реалізації.
2. Чому ви вважаєте, що створений продукт суперечить вимогам? Вимоги можуть бути в повній мірі реалізовані розробниками і працювати коректно, але одні і ті ж вимоги можуть відрізнятись способом реалізації, що залежить від багатьох факторів (досвіду, обмеженнями системи, тощо). В даному спрощеному випадку, мета якого показати, що реалізація вимог може бути як на рівні коду так і на рівні баз даних, відображається глибина аналізу, до якої повинен прагнути хороший інженер з тестування.

1. Технікою чорного ящика не прикриваються. Її використання — здоровий глузд. Є опис взаємодії з інтерфейсом зрозумілі вхідні та вихідні дані, реалізація не важлива.
🤔 Уявіть собі автомобіль. Інтерфейс вводу — кермо. Поверну вліво — машина їде вліво, вправо — вправо, прямо — прямо. Незалежно від реалізації: ручка, автомат, бензин чи електро.
2. для демонстрації дефекту я б додав запис в БД: розмір = 38, коефіцієнт = 2 І поведінка програми вже суперечить вимогам. Мета якісного ПЗ — не дати користувачу (адміністратору чи покупцю) зробити помилку. Саме тому наведена вами реалізація — баг

Exhaustive testing is NOT possible це один з принципів тестування, авторе.

Не розумію. А де в статті вказується, що вичерпне тестування можливе?

Попри те, що я займаюсь автоматизацією, маю для вас не дуже втішну новину: успіх якості та достатності автоматизованого тестування залежить в більшості випадків не від кількості та якості коду, який ви пишете, а саме від адекватного та грамотного тест-дизайну, аналізу та планування.

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

13 тестів для прикладу зі взуттям — діч, чесно.
так само, як і аргумент, що воно буде з БД.
як мінімум тому, що ті значення треба туди покласти перед тим.
не руками ж записувати їх (+ як нижче написали, а якщо їх буде не 13, а 1300?)
я хочу подивитись на людину, яка буде в коді перевіряти кожне значення, а не робити отак:
if size >= 42 && <= 45 { price = price * 1.1 }
або тим більше вручну записувати це всі дані в базу, щоб потім кодом читати звідти.

З технікою все добре, якщо її застововувати з гаричними значеннями. Оатсанній приклад не корректний, тому що автор пропонує робити повне тестування, яке не можливе. Це одна із аксіом тестування. І якщо таких розмірів не 13 а 1300? Навіть якщо знаєш як воно реалізовано, то робити 1300 перевірок не еффективно.
Замість висновку: техніки тест дизайну не панацея, але вони дають змогу обрати потрібні тести.

P.S. Згідно ISTQB, описаны техніки — це Black Box. Якщо хочете брати до уваги внутрішню структуру — пишіть про White Box

Будь-яка техніка тест-дизайну покликана зменшити зусилля на тестування, і при цьому гарантувати належну якість.

Нет.

реалізація такої умови, скоріше за все
якщо ми вірно виділили класи еквівалентності

Ага, «скоріш за все» і «якщо». І ми можемо взяти числа з середини діапазонів (наприклад, 5 і 50) і пропустити помилку розробника на, наприклад «>=17» замість «>17».

P.S. Написав і тільки потім помітив анонс наступної статті про граничні значення :)

звеселило)) дякую))

Виглядає наче помилка починається зі скороченого припущення про то що є класом еквівалентності.

Якщо глянути в Копленда то там щось типу:
«Клас еквівалентності складається з набору даних, який обробляється однаково системою/модулем та/або призводить до одного результату.
Будь-які дані з набору еквівалентні з точки зору тестування
(якщо одні дані з класу не знайдуть помилку, то й інші данні також її не знайдуть, і навпаки, якщо одні данні в класі помилку знайдуть — то й інші також знайдуть).»

Звідки маємо:
1. «обробляється однаково системою/модулем» говорить про те що не тільки результат важливий при визначенні класу.
2. Про більш ніж одну перевірку з одного класу думаю зовсім очевидно.

Саме так і є. Помилка саме в тому, що ігноруючи знання про систему ії архітектуру та реалізацію ми допускаємо те, що здавалося б очевидні класи еквівалентності визначаються некорректно.

наче комікс про пригоди джуна у світі QA=) чекаэмо продовження!=)

дуже цікава задумка матеріалу, дякую, чекатиму на наступні)

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