Чому деякі тест-сьюіти стають поганими, або Способи покращення тестової документації

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Привіт, мене звати Володимир, я тестувальник компанії DevelopEx, з 2017 року працюю на кросплатформному (десктоп + мобайл) проекті, що розробляється на фреймворці Qt. Типовий стек задач тестувальників на проекті: ручна перевірка фіч, ведення тестової документації, регресійне тестування, автоматизація перевірки тестових сценаріїв.

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

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

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

Щоб було цікавіше, за тестований функціонал візьмемо абстрактну web-форму реєстрації нового користувача. А найбільш стійких в кінці тексту чекає історія з життя. :)

Неактуальні тести

Якщо під час виконання тест-сьюіту очікуваний результат не співпадає з актуальним результатом, можливо, тест-ранер має справу з застарілою тестовою документацією. Одна з причин застарівання — еволюційне оновлення user stories, які дотичні до тестованої user story. При цьому, відносно прямої user story тест-сьюіт формально є актуальним.

Наприклад, розглянемо такий тест-кейс реєстрації нового користувача:

КрокиРезультат

  1. Ввести валідне ім’я в поле Name
  2. Ввести валідну незареєстровану раніше адресу в поле Email
  3. Ввести валідний пароль в поле Password. Наприклад: qwe123
  4. Натиснути кнопку «Register»

1. Відбувається перенаправлення на сторінку registration/success
2. Відображається повідомлення «User has been registered»

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

Причини виникнення:

  • Еволюційне оновлення user stories, котрі непрямо пов’язані з тест-сьюітом.

Способи покращення:

  • Під час оновлення тест-сьюіта переглядати його повністю (а не тільки в місцях змін);
  • Доручати оновлення складних тестових сценаріїв досвідченим членам команди;
  • Менш деталізувати тест-кейси для випадків, прямо не передбачених в прямій user story.

Копіювання документації

Інколи в тест-райтера (тестувальника, який створює тестовий документ) виникає спокуса скопіювати шматок документації в якості тест-кейсу. Оскільки документація може не оперувати конкретними значеннями, підбір значень для тесту і розрахунок результату перекладено на тест-ранера. Звісно, тест-ранер все виконає, але часу буде витрачено набагато більше. Адже: потрібно розібратись в документації, детально ознайомитись з тим, як суміжні фічі впливають на тестовану фічу, і самостійно розрахувати очікуваний результат. Що не завжди швидко.

Наприклад, є такі витяги з документації:

Документ 1:

WHEN Бекенд шифрує дані
THEN Бекенд використовує алгоритм AES-128-ECB з ключем mysupersecretkey

Документ 2:

GIVEN Введені валідні дані в поля форми реєстрації
WHEN Користувач натискає кнопку “Register”
THEN Клієнт пересилає введені дані на сервер
AND Бекенд шифрує пароль та зберігає його в базі даних

Якщо тест-кейс буде приблизно таким:

КрокиРезультат

1. Ввести валідні дані в поля форми реєстрації
2. Натиснути кнопку «Register»

1. Клієнт пересилає на сервер введені дані
2. Бекенд шифрує пароль та зберігає його в базі даних

то добросовісному тест-ранеру не лишатиметься іншого, як самотужки з’ясовувати, чи справді пароль зашифровано правильно.

Щоб регресійне тестування було виконане якісніше і швидше, цей тест-кейс можна переписати так:

КрокиРезультат

1. Ввести валідні дані в поля форми реєстрації. Приклад паролю: QWErty123!@#
2. Натиснути кнопку «Register»

1. Введені дані пересилаються на сервер
2. Бекенд шифрує пароль. Результат: zJF2zGe61QesKmMTTKL6iA==
3. Бекенд зберігає пароль та інші дані в базі даних.

Примітка: якщо шифр відрізняється від очікуваного, зверніться до документації «Шифрування даних на проекті»

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

Причини виникнення:

  • Бажання або потреба швидко створити тестовий сценарій;
  • Нерозуміння документації.

Способи покращення:

  • Не копіювати документацію :)
  • Розібратись в документації досконально (або запропонувати бізнес-аналітику уточнити її);
  • Виписувати тестовий сценарій паралельно з проходженням тесту.

Відсутність негативних сценаріїв

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

Причини виникнення:

  • Загальна (поверхнева) User Story;
  • Велика User Story;
  • Нестача часу.

Способи покращення:

  • Самостійно поглибити свою експертизу в доменній області;
  • Розбити один тестовий документ на кілька;
  • Ставити себе на місце користувача;
  • Писати дуже великий тест-сьюіт. А що поробиш?

Неоднозначна інтерпретація результату

Інколи тест-кейси містять таку послідовність кроків та результатів, з яких неясно, який саме результат має бути в певний момент проходження. Наприклад, маємо такий тест-кейс:

КрокиРезультат

1. Ввести невалідну електронну адресу
2. Натиснути кнопку «Register»

1. Виникає повідомлення «Email is invalid»
2. Виникає повідомлення «Please complete all fields»
3. Клієнт не надсилає дані

Можливо, результати 1-3 мають бути отримані після проходження всіх кроків. А можливо, що результат (1) має виникати після кроку (1), якщо реалізована динамічна перевірка введеної інформації.

Причини виникнення:

  • Бажання візуально зменшити кількість сценаріїв;
  • Припущення, що результати очевидні з кроків.

Способи покращення:

  • Розбивати складні тестові сценарії на прості;
  • Перегляд тест-кейсів іншими членами команди.

Неточні тести

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

Наприклад:

КрокиРезультат

1. Ввести валідну електронну адресу. Наприклад: john..doe@example.com
2. Прибрати фокус з поля «Email»

1. Поле «Email» підсвічене зеленим.

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

Причини виникнення:

  • Виписування сценарію «по пам’яті»;
  • Неуважність, втомленість;
  • Неглибоке знання продукту;
  • Неоднозначність документації.

Способи покращення:

  • Прогнати тест-кейс самому;
  • Рев’ю теста колегою.

Надлишкові перевірки

Завдання тестувальника — перевірити ПЗ якнайкраще, застосувавши для цього армію підходів та технік. Це добре для exploratory перевірок — коли фіча з пилу з жару. Але якщо ці перевірки перенести «на папір» як є, то швидкість тест-рану буде втрачена з-за великої кількості надлишкових рухів та неоптимізованої послідовності тест-кейсів у тест-сьюіті.

Причини виникнення:

  • Бажання перевірити фічу якнайкраще;
  • Документування exploratory перевірок «як є»;
  • Переоцінювання вартості гіпотетичних багів.

Способи покращення:

  • Продумувати послідовність тест-кейсів у тест-сьюіті;
  • Оминати детальну перевірку непрямих вимог;
  • Застосовувати відомі техніки тест дизайну.

Надмірно деталізоване інтеграційне тестування

Під «інтеграційним тестуванням» тут я маю на увазі перевірку взаємодії двох або більше компонентів (фіч) тестованого ПЗ. Часто дефекти зосереджуються саме в місцях взаємодії фіч. Природне бажання тестувальника — зосередити перевірки на таких взаємодіях.

Тест-райтер під час створення документації також описує перевірку взаємодії компонентів, щоб такі перевірки не було втрачені під час майбутніх регресій. Проблема в тому, що з часом логіка взаємодії компонентів може змінюватися. А деякі тест-кейси формально можуть лишатися незмінними (з причин, описаних в розділі «Неактуальні тести» цієї статті).

Детальні інструкції — як саме перевіряти взаємодію фіч — краще замінити тестовими сценаріями високого рівня або чек-лістами.

Наприклад, замінити тест-кейс:

КрокиРезультат

1. Зайти в «Особистий кабінет»
2. Ввести нове валідне ім’я в поле Name
3. Ввести нову валідну електронну пошту в поле Email
4. Натиснути на кнопку «Update»
5. Відкрити сторінку «Мої замовлення»
6. Відкрити сторінку «Список бажань»
1. Всюди відображаються актуальні значення Name та Email

На тестовий сценарій високого рівня:

  • Перевірити, що дані користувача після їх оновлення в «Особистому кабінеті» оновлюються на всіх релевантних сторінках.

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

Причини виникнення:

  • Детально прописані інтеграційні перевірки фіч.

Способи покращення:

  • Замінювати детальні інструкції тестовими сценаріями високого рівня або чек-лістами.

Резюме

Щоб з тестовою документацією було приємно працювати, а також бути впевненим в якості продукту, який перевірено, тести мають бути:

  1. Актуальні,
  2. Унікальні (не copy-paste з документації),
  3. З негативними сценаріями (навіть якщо тест-сьюіт вже великий),
  4. З однозначними причинно-наслідковими зв’язками (відповідність кроків і їх результатів),
  5. Точні (як написано, так і буде зроблено),
  6. Оптимальні з точки зору послідовності виконання,
  7. Без детальних інтеграційних перевірок.

Вийшло якраз сім критеріїв, прямо містика.

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

Історія з життя

Колеги, які переглядали цей текст перед передачею його в редакцію Dou, сказали: «Було б непогано додати якихось анекдотів чи історій з життя». Що ж, тримайте одну.

Оскільки продукти в рамках нашого проекту кросплатформні, їх UI та UX дуже близький. Однак є дисбаланс: в команді (і з боку замовника, і з боку розробника) — майже всі користувачі Windows. Відповідно, документацію прописуємо і узгоджуємо, спираючись на UX для Windows (за виключенням моментів, коли macOS використовує явно інші підходи в UX/UI).

Рік тому ми зарелізили продукт для Windows (через сайт замовника) та macOS (через App Store). Як і належить, релізу передувала регресія, баг-фікси, повторні перевірки...

Лише нещодавно було виявлено, що користувачі macOS весь цей час так просто не могли взяти і розшарити створені програмою файли. Тому що в програмі, яку завантажують на App Store, активована т.зв. «пісочниця» — sandbox. Програма зберігає файли, якими оперує користувач, в пісочниці. Яка, в свою чергу, знаходиться в глибинах прихованого каталогу ~/Library.

Під час розробки ми працювали без sandbox. Тому, в контексті збереження файлів, програма на macOS працювала, як і на Windows: з каталогом ~/Documents. Формально багу на macOS не було, фактично ж вийшло некрасиво.

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

Бажаю якісної тестової документації та безбажних продуктів на проді :)

👍НравитсяПонравилось7
В избранноеВ избранном2
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

Крайне забюркратизированный подход.
Тестирование не ради улучшения качества, — а ради тестирования. Смысл?
Приведённый в конце случай из жизни, казалось бы, должен подтверждать какой-то из наведённых примеров, — а по факту всё решалось банальным прохождением типичного флоу пользователя.

Залежить від проекту та від відношення замовника/менеджменту. Є проекти, де «бюрократія» (як ви кажете) потрібна в зв’язку зі складним функціоналом ПЗ. Приведений випадок з життя мав показати, що наскільки б добре тести не були виписані, все-одно завжди треба «включати голову».

Прочитал и понял следуещее: причина всех проблем — человеческий фактор, способ решения — устранить человека из тестирования!
Я еще ни разу ни видел мануальных тест кейсов, время на описание которых окупалось бы. Если тест описан недостаточно подробно, если он ПОДРАЗУМЕВАЕТ что тестировщик знает термины, знает где что надо включить, знает предметную область, знает какой результат правильный, а какой-нет и т.д — то такой тест кейс нельзя давать новичку. Он скорее всего не знает то, что опытный тестировщик ПОДРАЗУМЕВАЛ, но не написал в тесте. Результатом будут «дурные» баги или наоборот — всегда позитивный результат.
Если же тест кейс расписан максимально подробно, с точными входными значениями и точными ожидаемыми результатами, то опять плохо! Тест становится слишком узким и если написано вводить пароль 1234 то никто не попробует ФЫВА. При этои при малейшем изменении тест станет невалидным. Переименовали поле — нужно править десяток тест-кейсов.

ийшло якраз сім критеріїв, прямо містика.

Критерии правильные, но мануальные тесты написанные по ним будут требовать очень много времени на поддержание. Точно так же, как техническая документация.
Не зря современный подход говорит что «документация всегда врет» и даже комментарии в коде — врут. Потому что никто не будет тратить время что бы регулярно это проверять и обновлять. Единственная актуальная документация — это хороший, чистый и понятный код. Возможно — «живые» диаграммы, которые то же строятся на основе кода.
Аналогично и с тестами — лучшие тест кейсы это код! Потому что он максимально исключает человеческий фактор: разное понимание, разную трактовку и т.д. И как только авто-тест стал неактульным — он поломается.
С современным уровнем развития технологий мне уже сложно представить ситуацию, когда тестирование невозможно было бы автоматизировать и нужен был обязательно человек-тестировщик.

Мануальные тест-кейзы, которые прописаны аж до деталей, надо менять на скрипт. Реальный мануальный тестер может заметить то, чего НЕ ЖДАЛИ. Потому для мануальщиков важнее не тупорылая бюрократия «как тестировать», а пробитые сквозь бюрократические стены пути обратной связи.

Почему так: львиная доля ваших мануальщиков — реальные пользователи. И если ваш собственный мануальщик имеет проблемы с бюрократией, вы уже теряете реальных клиентов, которым эти все барьеры вообще не по зубам. Если же мануальщика вынуждают закрывать глаза на проблемы, потому что их нет в алгоритме — вы уже стоите жопой к клиенту. И что не менее важно, ко взломщику. Ибо проблемы безопасности вам тоже автотест не словит, даже 1 из 4.

Основная цель организации мануального тестирования — прокладка системы бета-теста. Без неё мануалка практически бесполезна. А с ней — часто тоже, особенно по мере вызревания проекта. В зрелом проекте вы просто переводите мануальщика в канал саппорта.

Реальный мануальный тестер может заметить то, чего НЕ ЖДАЛИ.

Согласен. То есть он должен тестировать неожиданные сценарии и пытаться «сломать» систему.
НО если у него случайно получилось найти проблему при ручном тестировании — то потом еще приходится тратить массу времени ему и разработчику что бы зарепродюсить этот сценарий!
А вот если бы QA написал или хотя-бы записал авто-тест со своими действиями — то это не только сэкономило бы время на репродюс, но и позволило бы создать авто-тест, который потом проверял бы этот сценарий постоянно, что бы проблема не вернулась!
Вот поэтому я и считаю что время потраченное на ручное тестирование — потраченно неэффективно. Хочешь проверить необычный сценарий — пиши авто-тест. Хочешь сделать «случайный поиск» — напиши тест, которые будет перебирать случайные значения, но при этом в случае обнаружения ошибки залогирует полный сценарий и все значения, которые привели к ней.

Почему же? Тестер должен тестировать ожидаемые сценарии. Но уж точно ожидаемые ПОЛЬЗОВАТЕЛЕМ, а не выполнять по пунктам хотелку разработчика, которую он сам уже проверил.

Пример: пользователь залогинился, сессия 20 минут, отработал, вышел. Сессия апдейтится при каждой смене страницы, по истечении — страница закрывается, переходя на страницу повторного входа.
Реальность: пользователь открыл несколько вкладок.
Суровая реальность: багу скоро 10 лет стукнет. Приватбанк — это не баги, это фичи!

Все це добре і правильно, але я (поки що) не зустрічав мануального тестувальника, який би взяв і по коду створив/пройшов тест. Бо це вже готовий програміст-сеньйор.

по ним будут требовать очень много времени на поддержание

Сильно залежить від відношення команди. Якщо прийняти такі підходи, як філософію — навпаки, на підтримку, імхо, менше часу. Тому «тести хороші», що на їх підтримку менше часу. В цьому ідея.

Все це добре і правильно, але я (поки що) не зустрічав мануального тестувальника, який би взяв і по коду створив/пройшов тест.

Именно поэтому многие известные ИТ компании в принципе не нанимают тестировшщиков! Потому что авто-тесты погут написать разработчики, а ручное тестирование — это прошлый век!

ручное тестирование — это прошлый век

що ж, тоді гугл все ще в минулому столітті

Если ваша реплика не была скрытым сарказмом, то:

Потому что авто-тесты погут написать разработчики

Даже если так, то это хотя бы для основной функциональности должны быть другие разработчики, чем авторы кода.
Авторы и думают иначе, и имеют замыленные глаза.

а ручное тестирование — это прошлый век!

Оно обязательно хотя бы периодически, чтобы поставить себя на место пользователя.
А то мало ли что там автотесты проверяют — может, систему, которую уже никто не использует...

Ідею потреби в ручному тестуванні я б сформулював просто: Якщо юзерами є люди, продукт мають перевіряти люди. І залучати для допомоги будь-які інструменти (в т.ч. автотести).

— Хто ми?
— Бюрократи!
— Чому деякі тест сьюіти сьюти стають поганими?
— Через бюрократію!
— Як ми їх покращимо?
— Бюрократією

PS. Я навіть перевірив, звідки взявся цей неологізм «сьюіти» — так от, усі посилання — на цей топік.

Тобто людина, яка НЕ ЗНАЄ як пишеться слово, при цьому ЗНАЄ, що не знає — і тим не менше викидає це творіння в публічну площину — буде вчити нас тестуванню? Да з такою толерантністю до помилок тобі не те що тестером протипоказано бути, а навіть сексом займатися. Бо **я зламаєш.

PPS. Як вже зазначили, в українську воно перейшло транслітом як «сьют», хоча насправді вимовляється «світи», через звук «w». Але у твоєму варіанті написання слово змінює наголос, тому звучить досить смішно.
Але мушу зазначити, з музичним терміном вийшло саме так — він змінив наголос через складність передачі звуку написанням. І замість одного дифтонгу слово отримало два окремих голосних.

Але ж не твій маразм з м′яким знаком, тобто з додаванням туди ще третього звуку «й».

Що ж, можливо. Спасибі. Чесно кажучи, переважно зустрічаю це слово в англомовному написанні (test suite), на автоматі транслітерував у «тест-сьюіт». Втім, «сьюіт» це, чи «сьют», зміст статті від цього не зміниться.

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

Потому что слово утащили из французского. А тащили в те времена, когда устный язык рулил над письменным, а народ был малограмотным. Потому упёрли и написание «как есть», и прочтение «как есть». Это французское слово «продолжение», «следование». Например, математическая последовательность. Но вот как раз смысл английский язык решил «покращить», превратив из последовательности в простое множество.

И этого дерьма в английском вероятно больше чем где бы то ни было. Страшнее только иероглифы.

Після прочитання слова

сьюіти

захотілося виколоти собі очі, не одразу навіть зрозумів, що йдеться про тест-план 😂
А якщо серйозно, то трохи сумно, що в час широкого поширення Agile та CI/CD практик, все ще є проекти, які роблять релізи раз на 10 місяців з 1000-годинним регрешином і де підхід до опису тестової документації попахує каскадною моделлю з 90-х.

Можливо, вартувало б половину із тих 1000 людиногодин потратити, щоб автоматизувати хоча б частину регресійного плану (зараз існує багато codeless automation підходів, які досить швидко та просто дозволяють покривати великі чаcтини функціоналу). Також можна спробувати писати менше традиційної тестової документації, яку, в результаті, не треба буде постійно покращувати, і можна буде більше зосередитися на самому тестуванні та альтернативних варіантах документації, таких як use-cases, service blueprints та інших. Ех, ці риторичні питання.

1. Ничего плохого в каскадной модели самой по себе нет. Есть проекты, где лучше применима инкрементальная модель, есть те, где лучше применима каскадная. Это — 1 из моих любимых вопросов на собесе :)
2. Автоматизация — абсолютно согласен, но вот codeless approach — ой не... Простота написания таких тестов полностью нивелируется стоимостью их поддержки. С учётом 10-месячного жизненного цикла — могу поспорить на пиво, что актуальных тестов между milestone N-1 и N останется не более 20%. Это означает, что, с учётом codeless подхода, их придётся переписать почти полностью. Я бы скорее опирался на низкоуровневые тесты (unit, integration) и немножко системных. С Qt на практике работать не доводилось, но вроде Robot его хавает с AutoIt, так что я бы скорее потратил немножко этих человекочасов в Python, ещё немножко — во вменяемый фреймворк, остальные — в написание нормальных автоматизированных тест кейсов.

вроде Robot его хавает с AutoIt

Не впевнений (хоча заводити не пробував). Але по відгукав виглядає сумнівно, з урахуванням, щоб працювало і на macOS.

Трудно сказать. Как уже писал выше, с Qt дела не имел раньше. От MacOs вообще предпочитаю держаться подальше. Мерзость редкостная, если честно :)
Но в любом случае, 1000 ч/ч регрессии — это уже беспредел какой-то :) Тут надо что-то решать. Не нравится Robot — не вопрос, подыщите себе фреймворк по душе и квалификации, но решать вопрос надо :)

Пропрієтарний Squish справляється.

йдеться про тест-план

Йдеться про тест-сьют в термінології ISTQB.

все ще є проекти, які роблять релізи раз на 10 місяців з 1000-годинним регрешином

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

Можливо, вартувало б половину із тих 1000 людиногодин потратити, щоб автоматизувати хоча б частину регресійного плану

Слушна думка, ми йдемо в цьому напрямку.

Дякую. Хоча деякі моменти злегка заплутані, але видно що автор старався.

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

Згоден, але якщо людина відкриває для себе нові горизонти і йде до них, працювати цікавіше.

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