Зачем нужны фейковые данные для тестирования?

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

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

Но как быть если данные которые создаются пользователем в рабочей базе данных влияют на структуру программы, например, в некоторых CMS в базе храниться почти всё, что касается программы (сайта).

У меня примерно похожая ситуация — то, что пользователь создаёт в базе, непосредственно влияет на всю программу и часто является источником сложноуловимых ошибок.

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

Но я не могу не замечать мощной индустрии создания фейков и моков с целыми фреймвоками. Интуитивно (поскольку опыта тестирования маловато) я вижу противоречие — с одной стороны мы создаём фейковое хранилище данных с достаточно жёсткой структурой классов, с другой есть тренд автомоков то есть когда все зависимости разрешаются автоматически на уровне фреймворка и данные возвращаются всегда валидные.

Не приводит ли это к логическому противоречию? Мы тестируем всегда валидные хранилища и классы.
При этом если логика программы влияет на порядок создания, хранения в куче и удаление объектов то мы никогда ошибок не найдём.

То же касается и ошибок данных которые могут влиять на бизнес-логику.

У меня такое ощущение, что удобство и быстрота тестирования с помощью моков или автомоков ухудшают качество тестирования.

Простой, вырожденный пример — Юзер пишет в карзину Яблоко — 100 кг по 1 грн, а в это время Администратор меняет условие скидок — за каждый килограмм более 10 — минус 1.5 грн. расчитывая что в розницу никто больше двух килограмм не купит. В результате минус в сумме.

На самом деле ситуация уменя гораздо сложнее. И я точно знаю что никаким фейкоым хранилищем для тестирования я эту проблему не решу, поскольку даже не представляю, что может прийти в голову Администратору. Точнее сама предметная область может заставить его написать бесчисленное множество вариантов, которые будут невалидными только при совместных действиях Администратора и Юзера, при чём действия эти будут разнесены во времени и внешне будут выглядеть валидными по отдельности.

Может быть есть какая-то область знаний типа Тестирование данных о которой я не знаю?

Кто-то с чем то подобным сталкивался? Куда копать?

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

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
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

Всё это бюрократическая чушь, порождённая силой ануса мысли бюрократов. Тестировать один и тот же код и базу ’кошерными’ данными — всё равно что проверять пищеварение 18-летнего пацана, прикладывая к женской груди. Результата никакого, но процесс доставляет своей зрелищностью, и возбуждает умы бюрократов заказчика.

Главная цель — писать код, в котором будешь уверен. А тесты должны покрывать ключевую логику. И чем более зрелый код — тем более длинная цепь в тестах. Короткие же в большинстве своём стоит выпиливать на этапах рефакторинга.

Кстати, твой пример при грамотной организации даже не потребовал бы тестирования. Потому что риск нерентабельной скидки должен решаться исключительно людьми, в процессе риск-менеджмента, и данный случай — ещё до написания кода. Если люди на этапе ТЗ забили болт на это всё, то бага обязательно выйдет в продакшен. Ибо кодеры не принимают решений о рентабельности. Да, ты можешь присечь цену −1 грн. Но что если итоговая цена будет 0.01 грн? И если под эту тему сами же работники немало стырят? Эти вопросы должен решать не разработчик.

Eсли в итоге сумма ноль, как ты собираешься выловить возможные деления на ноль в весьма далёких участках кода? В твоём примере, ты получаешь итоговую цену −0.50 грн. И что? Дальше что происходит? Непонятное сообщение клиенту? Или оператору? Вгоняешь в краску работников техпо клиента? Валишь апликейшен? Хочешь поговорить об этом с заказчиком когда горит дедлайн?? Или во время сдачи проекта?

Есть правило, придуманное задолго до программистов, и заботливо сохранено для нас Мэрфи: Если данные не соответствуют теории — от них нужно избавиться!

В реальности, если пишешь тест для себя — фейковые данные необходимы. На случай изменений, или просто когда пойдёт отладка кода, или когда получены сообщения о баге — сможешь запросто погонять систему тестовыми данными.

Но в этом случае никакая автоматика не поможет тебе их создать. Ручками! Кстати, этот скромный факт является причиной серьёзного явления в программировании — раннего пуска версий. Интерфейсы и базовые обработчики должны появиться как можно раньше, чтобы упростить (ускорить в разы) отладку сложных надстроек.

Но... приходится мириться с достаточно серьёзным недостатком: в очень дорогом и качественном коде заложен фундамент дешёвого прототипа, созданного на скороую руку. Он ещё не раз встанет костью в горле. И требуется глубокая квалификация и авторитет руководства, чтобы отдать команду переделать логику прототипа. Особенно, если наследники уже в эксплуатации.

Прблема растёт пирамидально: с первым успехом изменениея прототипа появляется успешное руководство. Которое, воодушевившись успехом, ещё не раз рискнёт изменить прототип. И посчитает себя умнее других, услышав (пересилив) скромное сопротивление подчинённых команд. И даже переступив (не желая увидеть) возражение потребителя. Пример — windows 8.

И казалось бы, при чём тут фейковые данные? А такой вот, малоизвестный, катализатор. Многие люди приклоняют колени перед системой, когда система предписывает: как себя вести, что делать, а чего не делать. И мало кто знает, что поведение системы тоже управляемо, и катализаторы могут писать программисты.

Ответ простой: есть два разных вида тестов: юнит-тесты и функциональные тесты.
Цель юнит теста — протестировать один, небольшой, полностью изолированный кусочек кода на предварительно подготовленных данных. Тут смысл не в поиске ошибок, а наоборот: тест декларирует и проверяет «контракт» (en.wikipedia.org/...ign_by_contract ). И он будет всегда проходить успешно — пока код кто-нибудь не «сломает». Такие тесты дополняют компилятор (и должны всегда запускаться после билда): он ищет синтаксические ошибки, а тесты — рантайм ошибки.
А вот тестированием функциональности (бизнес-логики, юзер-стори про «яблоко») занимаются функциональные тесты. И они как раз должны работать без всяких моков и фейков. Могут даже с реальной базой, но только тогда нужно продумать стратегию «отката» изменений в базе после теста.
Тестирования данных как отдельный тип особого смысла не имеет: ведь данные ничего сами не делают — просто лежат себе тихонько. А вот подготовить правильные (и разнообразные) тестовые данные и проверить их изменение после тестов — это часть функционального тестирования.
Еще один тип тестирования, который как раз покрывает «совместные действия» — это Concurrent Testing. Это те же функциональные тесты, но более хитрые: они запускают несколько потоков и часто делают несколько повторов с целью вызвать коллизию в действиях пользователей. Их пишут редко. Во-первых потому, что это технически сложно и дорого (особенно поддерживать их постоянно). А во-вторых потому, что изначально сложно составить для них тест-кейсы т.е. предусмотреть все возможные коллизии и как их правильно обрабатывать.
Ну и напоследок еще вспомню стресс-тесты. Это обычно многократный параллельный прогон функциональных тестов с целью узнать на какой нагрузке система «сдохнет» и где именно.

Отлично ответил, даже добавлять ничего не хочу.

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

Кто имел счастье видет эти чудес в банкоматах — меня поймёт. Никакими тестами это не покроешь! А на потраченные на создание тестов деньги можно было бы сделать кошерный баг-трекинг для поздних этапов.

Стресс-тесты тоже глупость. Кто имел счастье делать многозвенные действия, работающие со сторонними серверами неизвестной надёжности — понимает что стресс-тест попросту ничего не найдёт. Потому ему помогут «не найти». Покажите мне того идиота, который потратит неделю овертайма на отладку звена, которое может быть (низкая неизвестная вероятность) откажет на стресс-тесте?

Для этого компания должна быть владельцем продукта, мало того — поощрять сотрудников в случае успеха продукта и успеха компании. В наших украинских реалиях, с нашими украинскими манагерами — имеем строго обратное. Кто везёт — того и погоняют. И того кто будет излишне стрессовать систему — попросту уволят, за то что медленно пишет код. Либо, что ещё хуже — раз и навсегда отучат писать хороший код, чем похоронят квалификацию программиста.

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