By Stanislav Taran

Залежні тести в автоматизації тестування


Вступне слово

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

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

Перш ніж ми розпочнемо, я хотів би поділитися з вами однією думкою. Деякий час тому я не пам’ятаю де я це прочитав, але це досі у мене в голові. Яка різниця між Junior та Senior розробником. Обидва можуть писати поганий код, але відмінність полягає в тому, що Senior розробник знає, що його код поганий.

У вас можуть вже бути залежні тести, але ви повинні знати, що вони не ок.

Що таке залежні тести?

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

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

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

Dependent tests causes
  • Shared fixture dependency. Тести падають через те, що початкові умови/середовище були скомпрометовані попереднім тестом і не були належним чином очищені. Наприклад, ваш контекст браузера не ізольований/повторно використовується для кількох сценаріїв тестування і має деякі кукі, залишені після попередніх тестів.

  • Interdependent test cases. Це, ймовірно, найбільш поширений випадок. Це відбувається, коли тест залежить від стану або даних, змінених іншим тестом або скриптом, що призводить до непередбачуваних і ненадійних результатів тестування. Тести залежать один від одного, тобто їх можна виконувати тільки в певній послідовності. Наприклад, попередній тест не виконався/не пройшов і залишив систему не в тому стані як очікувалося (залишилися зайві дані або навпаки певні дані не були створені), тому всі наступні тести також впали.

  • Test case Contamination. Це спеціальний випадок залежних тестів. Тест падає через те, що ви вибрали неправильний підхід для виконання перевірок. Ви виконуєте SENSITIVE COMPARE там, де це не потрібно, тому зміни, які не мають нічого спільного з вашим тестовим випадком, впливають на результати. Це часто відбувається, коли ви мігруєте ручні тесткейси в автоматизацію і не змінюєте підхід коли потрібно. Деякі кроки в ручних тесткейсах часто повторюються, і ви не звертаєте на них увагу.

  • Test data dependency. Декілька тестів використовують одні й ті ж тестові дані, і зміни в даних одного тесту впливають на інші. Неспівпадіння даних може призвести до падінь тестів і до ускладненого пошуку першопричини таких падінь. Наприклад, ви використовуєте одного й того ж юзера для декількох тестів. Дії, виконані в одному тесті, можуть вплинути на всі інші. Проблем буде ще більше при виконанні тестів паралельно.

  • Corrupted data. Тести падають через те, що дані були пошкоджені або змінені іншим додатком/користувачем. Наприклад, ви хочете виконати просту перевірку і не хочете підготовлювати дані, оскільки це займає набагато більше часу, ніж сам тест. Ви повністю або частково покладаєтеся на існуючі дані на певному середовищі. Але в один момент властивості цих даних були змінені рандомною людиною або іншим додатком або взагалі видалені. Упс :(

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

По факту, є правило, яке допоможе вам уникнути залежних тестів.

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

Чому залежні тести це погано?

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

Dependent tests consequences
  • False failures. Тести падають не через помилки в SUT, а через помилки в тестовому фреймворку або проблеми з середовищем. Цей тип помилок найнебезпечніший, оскільки він може призвести до втрати довіри до автоматизації тестування. Крім того, він може призвести до втрати часу та ресурсів, витрачених на вирішення проблеми.

  • Flaky tests. Flaky tests - це тести, які іноді проходять і іноді не проходять без будь-яких змін в SUT або тестовому фреймворку. Flaky tests - це кошмар для автоматизаторів, оскільки вони непередбачувані.

  • Inflexible automation. Залежні тести важко підтримувати та рефакторити. Ви не можете змінити один тест без впливу на інші. Ви не можете виконувати тести паралельно, оскільки вони будуть впливати один на одного. Ви не можете виконувати окремі тести, оскільки вони покладаються на стан системи після попередніх тестів. Ви не можете виконувати тести в будь-якому порядку, оскільки вони залежать один від одного. Ви не можете виконувати тести в будь-якому середовищі, оскільки вони залежать від існуючих даних.

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

Є і інші наслідки, але ці найпоширеніші. Я думаю, що навіть цього достатньо, щоб переконати вас, що залежні тести це погано.

Як уникнути залежних тестів?

Я сподіваюся, що це питання вже у вас в голові.

Давайте пригадаємо правило, яке я згадував раніше.

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

Які питання ви повинні задати собі, щоб переконатися, що ваші тести незалежні?

  1. Чи можу я виконати цей тест в ізоляції (без інших тестів)?. Якщо відповідь “ні”, то ваш тест залежний.
  2. Чи можу я виконати цей тест в будь-якому порядку?. Якщо відповідь “ні”, то ваш тест залежний.
  3. Чи можу я виконати цей тест в будь-якому середовищі?. Якщо відповідь “ні”, то ваш тест залежний.
  4. Чи можу я виконати цей тест в будь-який час?. Якщо відповідь “ні”, то ваш тест залежний. (Я повинен визнати, що це питання не завжди застосовується, оскільки деякі тести залежать від часу за своєю природою)

Давайте розглянемо причини, які ми згадували раніше і як їх уникнути.

  • Shared fixture dependency. Використовуйте механізм setup/teardown, щоб забезпечити однакові початкові умови. Якщо ми говоримо про e2e тести, використовуйте новий контекст браузера для кожного сценарію тестування.

    Якщо ви використовуєте Playwright, це реалізовано під капотом, тому вам не потрібно про це турбуватися. Я рекомендую використовувати Playwright для e2e тестів. Оскільки ідея ізоляції була вбудована в дизайн Playwright.

  • Interdependent test cases. Уникайте використання стану системи після попередніх тестів. Використовуйте механізм setup/teardown, щоб забезпечити однакові початкові умови. В основному, цього правила легко дотримуватися, якщо ви дотримуєтеся попереднього.

    Знову ж таки, якщо ви використовуєте Playwright, ви можете використовувати кастомні фікстури, щоб забезпечити сетап для ваших тестів.

  • Test data dependency. Використовуйте унікальні дані для кожного тесту. Використовуйте бібліотеки, як Faker, для генерації випадкових даних. У більшості випадків, якщо ви використовуєте одні й ті ж дані між тестами, це означає, що ви покладаєтеся на певний порядок тестів.

    Звісно, можуть бути випадки, коли вам потрібно використовувати одні й ті ж дані згідно з бізнес-логікою. Але насправді ці випадки рідкісні.

  • Corrupted data. Не покладайтеся на існуючі дані, якщо це можливо. І з практичного досвіду, це майже завжди можливо. Підготуйте дані, які вам потрібні для тесту. Це може зайняти деякий час, але в майбутньому воно зекономить вам багато часу.

    Playwright fixtures та project dependencies допоможуть вам підготувати дані, які вам потрібні для тестування.

  • Test case Contamination. Використовуйте правильний підхід для виконання перевірок. Не використовуйте SENSITIVE COMPARE там, де це не потрібно. Якщо ви не впевнені, чи варто робити перевірку чогось, запитайте себе, чи це пов’язано з вашим тесткейсом. Коли ви перевіряєте, чи “користувач може додати товар до кошика”, вам не потрібно перевіряти, чи товари відсортовані за ціною. Коли ви перевіряєте, чи “користувач може залогінитись”, вам не потрібно перевіряти всі елементи на сторінці.

    Якщо будь-яка перевірка, не пов’язана з основною метою тесту, впаде до основної перевірки, ви не зможете сказати, чи успішна основна перевірка чи ні, оскільки тест вже впав. Звісно, ви можете використовувати soft assertions, але якщо ви вже використовуєте їх, ви, ймовірно, знаєте, чому вони вам потрібні.

Висновок

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

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

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

Можете мені вірити на слово. Я це проходив.

Дякую за увагу!