Что такое ddt тестирование
ABAP Blog
Все о разработке в решениях от SAP
ABAP Blog
Все о разработке в решениях от SAP
Ссылки
Цитаты
Я мог бы перечислить все признаки, присущие чистому коду, но существует один важнейший признак, из которого следуют все остальные. Чистый код всегда выглядит так, словно его автор над ним тщательно потрудился. Вы не найдете никаких очевидных возможностей для его улучшения. Все они уже были продуманы автором кода. Попытавшись представить возможные усовершенствования, вы снова придете к тому, с чего все началось: вы рассматриваете код, тщательно продуманный и написанный настоящим мастером, небезразличным к своему ремеслу.
М. Физерс
Новое
Последние комментарии
Тестирование, управляемое данными (Data-Driven Testing)
Методология тестирования, управляемого данными (DDT) применяется в автоматизации тестирования ПО, представляет собой тестирование, выполнение и верификация которого производится на основе данных, которые хранятся в БД или любых других источниках данных.
Обычно сравнивают эталонные данные с теми, что на выходе получает система из метода (функции, программы и т.п.).
Тестирование, управляемое данными подразумевает разделение юнит тестов и данных, которые в них проверяются. Юнит тесты получают эталонные данные из некого источника и сравнивают их с результатами, полученными при тестировании объекта.
Изначально ABAP Unit не предоставляет никакого сервиса для хранения и ведения тестируемых данных, как например это делают другие фреймворки для тестирования: jUnit, nUnit. В статье пойдет речь о том как обойти это недоразумение.
В качестве подобного сервиса можно использовать контейнеры данных eCATT. Что такое eCATT и для чего он нужен можно посмотреть тут. Нас интересует один из элементов eCATT, а именно контейнер тестовых данных. Исходя из названия, становится понятно, что контейнер позволяет хранить внутри себя какие-то данные, но кроме хранения можно так же и вести (изменять) эти данные.
Рассмотрим небольшой пример, допустим, есть метод рассчитывающий тип треугольника относительно размеров его сторон, как известно из школьной программы, тип может быть следующим:
Создадим класс ZCL_TRIANGLE c указанными атрибутами:
TDD: методология разработки, которая изменила мою жизнь
На часах 7:15 утра. Наша техподдержка завалена работой. О нас только что рассказали в передаче «Good Morning America» и множество тех, кто впервые посещает наш сайт, столкнулось с ошибками.
У нас настоящий аврал. Мы, прямо сейчас, до того, как потеряем возможность превратить посетителей ресурса в новых пользователей, собираемся выкатить пакет исправлений. Один из разработчиков кое-что подготовил. Он думает, что это поможет справиться с проблемой. Мы размещаем ссылку на обновлённую версию программы, пока ещё не ушедшей в продакшн, в чат компании, и просим всех её протестировать. Работает!
Наши героические инженеры запускают скрипты для развёртывания систем и через считанные минуты обновление уходит в бой. Внезапно число звонков в техподдержку удваивается. Наше срочное исправление что-то поломало, разработчики хватаются за git blame, а инженеры в это время откатывают систему к предыдущему состоянию.
Автор материала, перевод которого мы сегодня публикуем, полагает, что всего этого можно было бы избежать благодаря TDD.
Почему я использую TDD?
Я давно уже не попадал в подобные ситуации. И дело не в том, что разработчики перестали совершать ошибки. Дело в том, что уже многие годы в каждой команде, которой я руководил и на которую я оказывал влияние, применялась методология TDD. Ошибки, конечно, всё ещё случаются, но проникновение в продакшн проблем, способных «повалить» проект, снизилось практически до нуля, даже несмотря на то, что частота обновления ПО и количество задач, которые нужно решить в процессе обновления, экспоненциально выросли с тех пор, когда случилось то, о чём я рассказал в начале.
Когда кто-то спрашивает меня о том, почему ему стоит связываться с TDD, я рассказываю ему эту историю, и могу вспомнить ещё с десяток похожих случаев. Одна из важнейших причин, по которым я перешёл на TDD, заключается в том, что эта методология позволяет улучшить покрытие кода тестами, что ведёт к тому, что в продакшн попадают на 40-80% меньше ошибок. Это то, что мне нравится в TDD больше всего. Это снимает с плеч разработчиков целую гору проблем.
Кроме того, стоит отметить, что TDD избавляет разработчиков от страха внесения изменений в код.
В проектах, в работе над которыми я принимаю участие, наборы автоматических модульных и функциональных тестов практически ежедневно предотвращают попадание в продакшн кода, который способен серьёзно нарушить работу этих проектов. Например, сейчас я смотрю на 10 автоматических обновлений библиотеки, сделанных на прошлой неделе, таких, перед выпуском которых без использования TDD, я опасался бы того, что они могут что-то испортить.
Все эти обновления были автоматически интегрированы в код, и они уже используются в продакшне. Я не проверял ни одного из них вручную, и совершенно не беспокоился о том, что они могут плохо отразиться на проекте. При этом, мне, для того чтобы привести этот пример, не пришлось долго думать. Я просто открыл GitHub, взглянул на недавние слияния, и увидел то, о чём рассказал. Та задача, которую раньше решали вручную (или, ещё хуже, задача, которую игнорировали), теперь представляет собой автоматизированный фоновый процесс. Можно попытаться сделать нечто подобное и без хорошего покрытия кода тестами, но я бы не рекомендовал так поступать.
Что такое TDD?
TDD расшифровывается как Test Driven Development (разработка через тестирование). Процесс, реализуемый в ходе применения этой методологии очень прост:
Тесты выявляют ошибки, тесты завершаются успешно, выполняется рефакторинг
Вот основные принципы применения TDD:
Как TDD может помочь сэкономить время, необходимое на разработку программ?
На первый взгляд может показаться, что написание тестов означает значительное увеличение объёма кода проекта, и то, что всё это отнимает у разработчиков много дополнительного времени. В моём случае, поначалу, всё так и было, и я пытался понять, как, в принципе, можно писать тестируемый код, и как добавлять тесты к коду, который был уже написан.
Для TDD характерна определённая кривая обучаемости, и пока новичок карабкается по этой кривой, время, необходимое на разработку, может увеличиться на 15-35%. Часто именно так всё и происходит. Но где-то года через 2 после начала использования TDD начинает происходить нечто невероятное. А именно, я, например, стал, с предварительным написанием модульных тестов, программировать быстрее, чем раньше, когда TDD не пользовался.
Несколько лет назад я реализовывал, в клиентской системе, возможность работы с фрагментами видеоклипа. А именно, речь шла о том, чтобы можно было бы позволить пользователю указывать начало и конец фрагмента записи, и получать ссылку на него, что дало бы возможность ссылаться на конкретное место в клипе, а не на весь этот клип.
Работа у меня не шла. Проигрыватель доходил до конца фрагмента и продолжал её воспроизводить, а я не имел представления о том, почему это так.
Я полагал, что проблема заключается в неправильном подключении прослушивателей событий. Мой код выглядел примерно так:
Процесс поиска проблемы выглядел так: внесение изменений, компиляция, перезагрузка, щелчок, ожидание… Эта последовательность действий повторялась снова и снова.
Для того чтобы проверить каждое из вносимых в проект изменений, нужно было потратить почти минуту, а я испытывал невероятно много вариантов решения задачи (большинство из них — по 2-3 раза).
Закон отладки Мёрфи. То место программы, которое вы никогда не тестировали, так как свято верили в то, что оно не может содержать ошибок, окажется именно тем местом, где вы найдёте ошибку после того, как, совершенно вымотавшись, внесёте в это место изменения лишь из-за того, что уже попробовали всё, о чём только могли подумать.
Я не забыл об этом и годы спустя. И всё — благодаря тому ощущению, которое испытал, всё же найдя ошибку. Вы, наверняка, знаете, о чём я говорю. Со всеми это случалось. И, пожалуй, каждый сможет узнать себя в этом меме.
Вот как я выгляжу, когда программирую
Если бы я писал ту программу сегодня, я бы начал работу над ней примерно так:
Возникает ощущение, что тут куда больше кода, чем в этой строчке:
Но в том-то всё и дело. Этот код действует как спецификация. Это — и документация, и доказательство того, что код работает так, как того требует эта документация. И, так как эта документация существует, если я изменю порядок работы с маркером времени окончания фрагмента, мне не придётся беспокоиться о том, нарушил ли я в ходе внесения этих изменений правильность работы со временем окончания клипа.
Вот, кстати, полезный материал по написанию модульных тестов, таких же, как тот, который мы только что рассмотрели.
Начиная новый проект я, в качестве одного из первых дел, выполняю настройку скрипта-наблюдателя, который автоматически запускает модульные тесты при каждом изменении некоего файла. Я часто программирую, используя два монитора. На одном из них открыта консоль разработчика, в которой выводятся результаты выполнения подобного скрипта, на другом выводится интерфейс среды, в которой я пишу код. Когда я вношу в код изменение, я обычно, в пределах 3 секунд, узнаю о том, рабочим оказалось это изменение или нет.
Для меня TDD — это гораздо больше, чем просто страховка. Это — возможность постоянного и быстрого, в режиме реального времени, получения сведений о состоянии моего кода. Мгновенное вознаграждение в виде пройденных тестов, или мгновенный отчёт об ошибках в том случае, если я сделал что-то не так.
Как методология TDD научила меня писать более качественный код?
Мне хотелось бы сделать одно признание, хоть признавать это и неловко: я не представлял себе, как создавать приложения до того, как я изучил TDD и модульное тестирование. Я не представляю, как меня вообще брали на работу, но, после того, как я провёл собеседования с многими сотнями разработчиков, я могу с уверенностью сказать, что в похожей ситуации находится множество программистов. Методология TDD научила меня почти всему, что я знаю об эффективной декомпозиции и композиции программных компонентов (я имею в виду модули, функции, объекты, компоненты пользовательского интерфейса и прочее подобное).
Причина этого заключается в том, что модульные тесты принуждают программиста к тестированию компонентов в изоляции друг от друга и от подсистем ввода-вывода. Если модулю предоставляются некие входные данные — он должен выдать некие, заранее известные, выходные данные. Если он этого не сделает, тест завершается с ошибкой. Если сделает — тест завершается успешно. Смысл тут заключается в том, что модуль должен работать независимо от остального приложения. Если вы тестируете логику работы состояния, у вас должна быть возможность делать это без вывода чего-либо на экран или сохранения чего-нибудь в базу данных. Если вы тестируете формирование пользовательского интерфейса, то у вас должна быть возможность тестировать его без необходимости загрузки страницы в браузер или обращения к сетевым ресурсам.
Кроме прочего, методология TDD научила меня тому, что жизнь становится гораздо проще в том случае, если при разработке компонентов пользовательского интерфейса стремиться к минимализму. Кроме того, от пользовательского интерфейса следует изолировать бизнес-логику и побочные эффекты. С практической точки зрения это означает, что если вы используете UI-фреймворк, основанный на компонентах, вроде React или Angular, целесообразным может быть создание презентационных компонентов, отвечающих за вывод чего-либо на экран, и компонентов-контейнеров, которые друг с другом не смешиваются.
Презентационный компонент, получающий некие свойства, всегда формирует один и тот же результат. Подобные компоненты можно легко проверить, используя модульные тесты. Это позволяет узнать, правильно ли компонент работает со свойствами, и то, корректна ли некая условная логика, используемая при формировании интерфейса. Например, возможно, компонент, формирующий список, не должен выводить ничего кроме приглашения на добавление в список нового элемента в том случае, если список пуст.
Я знал о принципе разделения ответственности задолго до того, как освоил TDD, но я не знал о том, как разделять ответственность между разными сущностями.
Модульное тестирование позволило мне изучить использование моков для тестирования чего-либо, а затем я узнал, что мокинг — это признак того, что, возможно, с кодом что-то не так. Это меня ошеломило и полностью изменило мой подход к композиции программного обеспечения.
Вся разработка программного обеспечения — это композиция: процесс разбиения больших проблем на множество мелких, легко решаемых проблем, а затем создание решений для этих проблем, которые и формируют приложение. Мокинг, выполняемый ради модульных тестов, указывает на то, что атомарные единицы композиции, на самом деле, не атомарны. Изучение того, как избавиться от моков, не ухудшая покрытие кода тестами, позволило мне узнать о том, как выявлять бесчисленное множество скрытых причин сильной связанности сущностей.
Это позволило мне, как разработчику, профессионально вырасти. Это научило меня тому, как писать гораздо более простой код, который легче расширять, поддерживать, масштабировать. Это относится и к сложности самого кода, и к организации его работы в больших распределённых системах наподобие облачных инфраструктур.
Как TDD помогает экономить рабочее время команд?
Я уже говорил о том, что TDD, в первую очередь, ведёт к улучшению покрытия кода тестами. Причина этого заключается в том, что мы не начинаем писать код реализации некоей возможности до тех пор, пока не напишем тест, проверяющий правильность работы этого будущего кода. Сначала пишем тест. Потом позволяем ему завершиться с ошибкой. Потом пишем код реализации возможности. Тестируем код, получаем сообщение об ошибке, добиваемся правильного прохождения испытаний, выполняем рефакторинг и повторяем этот процесс.
Этот процесс позволяет создать «заграждение», через которое способны «перескочить» лишь очень немногие ошибки. Эта защита от ошибок оказывает удивительное воздействие на весь коллектив разработчиков. Оно избавляет от страха перед командой merge.
Высокий уровень покрытия кода тестами позволяет команде избавиться от желания вручную проконтролировать любое, даже маленькое изменение кодовой базы. Изменения кода становятся естественной частью рабочего процесса.
Избавления от страха внесения изменений в код напоминает смазывание некоей машины. Если этого не делать, машина, в конце концов, остановится — до тех пор, пока её не смажут и снова не запустят.
Без этого страха процесс работы над программами оказывается гораздо более спокойным, чем прежде. Pull-запросы не откладывают до последнего. CI/CD-система запустит тесты, и, если тесты окажутся неудачными, остановит процесс внесения изменений в код проекта. При этом сообщения об ошибках и сведения о том, где именно они произошли, очень сложно будет не заметить.
В этом-то всё и дело.
Уважаемые читатели! Пользуетесь ли вы методикой TDD при работе над своими проектами?
Data Driven Testing (содержит 7 примеров использования с рабочих проектов)
Введение
Преимущества использования
Также, руководителю проекта становится легче контролировать разработку, ему не приходиться вникать в суть алгоритмов, и даже качества сделанного кода, DDT тестов вполне достаточно для продвижения вперёд.
Использование DDT, как ни странно, позволяет использовать на проектах менее квалифицированных инженеров, так как хорошее покрытие сложных участков с помощью DDT сразу же всё показывает, и человек за счёт Continuous Integration и прогонки тестов локально или на Dev окружении, имеет возможность самостоятельно фиксить внесённые проблемы.
Нюансы
Отмечу, что при определённом подходе в использовании, Robot Framework тесты могут быть очень DDT-ориентированными, и давать массу выгод.
Простейшая форма DDT — параметризованные тесты в JUnit, когда с помощью Data Providers в тест поставляются наборы данных для тестирования.
DDT — не панацея, но грамотное применение в нужных местах помогает очень и очень.
Как понять, когда нужно создавать DDT
Как создавать DDT
Чаще всего, достаточно сделать цикл над основным тестом, и организовать сравнение выходных данных и эталонных, а также реализовать репортинг — путём логгирования, или другим способом.
Но в нетривиальных случаях, возможно построение архитектуры вокруг необходимости создать DDT. Смотрите примеры 3 и 7.
Примеры
1. Самый простой, который автор использует для набора стажёров и практикантов
Задание : Перевод числа в цифровой записи в строковую. Например 134345 будет «сто тридцать четыре тысячи триста сорок пять». * Учесть склонения — разница в окончаниях (к примеру, две и два).
Вот как реализовал такой тест один из наших стажёров https://sourceforge.net/p/jazzteamedu/code/HEAD/tree/practice/NumbersToWords/ — обратите внимание, он решил наборы данных для тестирования положить в эксель, то есть любой, в том числе, мануальный тестировщик, сможет тестировать его алгоритм.
2. Пример, который автор часто приводит на лекциях
Один инженер будет идти таким путём. Он попросит время, чтобы вычитать спецификацию. Потом попросит подумать над архитектурой. Потом будет делать прототипы. Как-то их тестировать. Всё это время, дни, недели, менеджер и команда не смогут проверять его статус на деле.
3. Подход, который применяется в тестировании платформы для автоматизации тестирования XML2Selenium
XML2Selenium — система, построенная на плагинах и на взаимодействии плагинов. Плагины генерируют ивенты, подписываются на ивенты других плагинов. То есть от пользователя скрыто сложное взаимодействие.
XML2Selenium умеет прокрутить тесты, записанные в формате XML, и тестировать Web UI приложение (внутри мы используем Selenium/Web Driver).
После того, как разработчик или тестировщик вручную верифицировали, что данное дерево для данного теста — корректно, оно отправлялось в набор эталонных значений, и таким образом, на Continuous Integration сервере Jenkins мастер ветки для каждого запущенного теста сравнивалось дерево разбора, что крайне стабилизировало состояние системы.
4. Подход, который применялся на одном из проектов к тестированию выгрузки данных
В этом случае на проекте требовалось протестировать, насколько правильно работал компонент выгрузки данных. Выгрузка была нетривиальная, зависела от состояния базы данных, и в ней то и дело всплывали баги. Можно было сказать, что команда не контролировала стабильность этого компонента. Требовалось радикально увеличить его стабильность.
Решение было в использовании DDT. Входным параметром выступал дамп базы данных в формате XML. Эталонным значением — ранее проверенный файл выгрузки, заведомо безошибочный. Таким образом, тестирование свелось к созданию разных версий базы данных, а также к проверке эталонных файлов, и созданию таких тестовых наборов.
На проекте была обеспечена достаточная регрессионность. Каждый раз, когда появлялся баг в выгрузке — добавлялся ещё один набор данных, который покрывал эту ситуацию. Наборы накапливались, их существование не позволяло вносить новые баги, и через какое-то время компонент стабилизировался.
Насколько я помню, мы также реализовали генерацию нужного состояния базы данных из Java, чтобы не зависеть от дампов, и не обновлять их постоянно с изменениями схемы данных.
5. Реальный проект — тестирование обработки ошибок в сложной грамматике
Суть проекта была следующей. На клиентскую часть от сервера приходил XML с полным описанием не только UI, который нужно было отрисовать, но и с поведением, которое передавалось в бинарном формате в этом же XML. То есть поведение могло быть каким угодно, налицо плагинная система.
Данный XML имел достаточно сложный синтаксис, и наша команда была независима от разработчиков backend. Нам необходимо было обезопасить себя от неправильных XML, мы должны были начинать построение UI только тогда, когда 100% понимали, что XML правильный.
Для этого был использован DDT. Мы создали огромное количество вариантов входного XML, в том числе, неправильных, некорректных, и проверяли, что выбрасываются нужные исключения с нужными сообщениями.
Таким образом, входной параметр — это XML, эталонное состояние — тип исключения, его сообщение, или даже, часть stack trace. Было создано несколько сотен тестовых наборов, и каждый раз, когда менялось что-то в формате, появлялись новые параметры, или же, появлялись новые исключения и баги — тесты расширялись. Под окончание проекта это была самая стабильная часть системы.
На этом изображении приведена часть Excel файла, в котором задаётся входной параметр и эталонное поведение — в нашем случае, информация об исключениях (тип и сообщение).
6. Тестирование сложной загрузки данных. Изолирование логики хранимых процедур
На одном из проектов происходит загрузка данных в формате CSV (очень сложного внутреннего формата) в базу данных. Притом нам достался legacy код, и вся логика загрузки происходит в хранимых процедурах, в которых порядка десятка тысяч строчек. Задача состояло в том, чтобы стабилизировать этот компонент выгрузки, и обеспечить регрессионное тестирование.
Как и в примере 4. с выгрузкой данных, мы применили DDT, и в качестве входных параметров использовали 1) состояние базы данных (мы использовали дамп в формате SQL) и 2) файл, который нужно будет загрузить. В качестве эталонного значения мы использовали XLS файл, который представлял содержимое нужных нам таблиц этой базы данных после загрузки.
Все баги, которые часто случались, мы помещали в DDT.
Вскоре, мы обнаружили, что наши фиксы не влияют на прошлые баги, и что багов стало меньше, а контроль над ними — стал выше, так как сейчас есть возможность быстро и эффективно их воспроизводить автоматически, добавляя новые наборы.
В случае этого проекта, ввиду отсутствия времени, использовались сырые дампы, соответственно, потенциально поддержка такой системы в дальнейшем будет требовать затрат.
7. Наиболее сложный пример DDT из практики автора
При создании SOA платформы (то есть фреймворка для SOA проектов) была поставлена задача тестирования поведения системы, системной шины, воспроизведения всех возможных ситуаций, которые могут случиться во время жизненного цикла SOA проекта.
Для реализации этой задачи был создан фреймворк, позволяющий по описанию системы разворачивать её — в реальности это разные виртуальные сервера, которые связаны друг с другом через нашу SOA платформу. На каждом из серверов было развёрнуто приложение, которое было подключено к системной шине, и умело выполнять скрипты, которые ему поступали. В передаваемых скриптах мы зашивали требуемое поведение и требуемый сценарий.
Таким образом, входными данными были 1) файл описания топологии системы и 2) набор скриптов для каждого узла этой топологии, которые говорили, что происходит на каждом из узлов, а эталонными значениями было дерево (своеобразный лог) обработки сообщений в такой системе.
3 thoughts on “ Data Driven Testing (содержит 7 примеров использования с рабочих проектов) ”
Что такое ddt тестирование
Тестирование и его разновидности
Обеспечение качества (Quality assurance, QA) — способ предотвращения ошибок и дефектов в производимых продуктах, а также предотвращения проблем при доставке продуктов или услуг клиенту.
Тестируемая система (System under test, SUT) — система, которая тестируется на корректность работы.
Ручное и автоматизированное тестирование
Ручное тестирование — прямое взаимодействие QA-инженера с приложением.
QA ищет неисправности и недостатки, а затем информирует о них программиста.
Плюсы ручного тестирования
Минусы ручного тестирования
Автоматизированное тестирование — написание кода для тестов.
Ожидаемый сценарий описывается кодом, затем при запуске тестов он сравнивается с реальным и программа указывает расхождения.
Плюсы автоматизированного тестирования
Минусы автоматизированного тестирования
Майк Кон, автор книги «Scrum. Гибкая разработка ПО», представляет тестирование приложения в виде пирамиды.
Чем выше по пирамиде, тем дольше и затратнее делать тесты.
По этой причине автор расставил следующие приоритеты: 80% — модульные тесты, 15% — интеграционные и API-тесты, 5% — UI-тесты (могут быть как автоматизированными, так и ручными).
Подходы к написанию тестов
Test-Driven Development (TDD) — разработка через тестирование; подход к разработке и тестированию, при котором сначала создаются тесты, которым должен удовлетворять код, затем его реализация.
TDD имеет итеративный процесс. Сперва пишется тест на новый, ещё не реализованный функционал, а затем пишется минимальное количество кода (ничего лишнего) для его реализации. При успешном прохождении теста, можно задуматься о качестве кода и сделать его рефакторинг.
Например, напишем тест для функции, которая должна возводить двойку в степень.
Теперь на основании теста пишется сама функция.
Функция удовлетворяет тестам выше, добавим новые тесты.
Дописываем нужный функционал.
Далее снова пишем тесты.
Приемочное тестирование (Acceptance Testing) — тестирование, направленное на проверку соответствия системы требованиям.
Сперва придумываются критерий выполненной работы и критерий того, что она выполнена правильно. Эти критерии описываются доступным для понимания нетехническому человеку языком.
ATDD вносит ястность, что все участники проекта точно понимают, что необходимо сделать и реализовать.
Behavior-Driven Development (BDD) — разработка, основанная на поведении; расширение подхода TDD, где особое внимание уделяется поведению системы в терминах бизнеса. Такие тесты обычно иллюстрируют и тестируют сценарии, интересные заказчику системы. Поэтому для BDD-тестов используются фреймворки (Chai, Mocha, Jest) с синтаксисом, понятным не только программисту, но и представителю заказчика. Обычно этот синтаксис похож на английский язык.
Сравнение TDD, ATDD и BDD
TDD-тесты пишутся программистами для программистов. Они не указывают, что конкретно нужно тестировать и как именно должны выглядеть и называться тесты.
BDD вдохновлено архитектурой DDD (Domain-Driven Design) и фокусируется на предметной области приложения, в то время как TDD фокусируется на сам код, реализацию.
ATDD фокусируется на отображении требований в приёмочных тестах и использует эти тесты для разработки. Вопрос, определяющий ATDD-тесты: «Система делает то, что от неё требуется?».
BDD ориентирован на клиента (customer-focused), в то время как ATDD больше ориентирован на разработчика (developer-focused) и часто использует те же технологии, что и TDD.
BDD-тесты могут быть написаны и поняты не только программистом, но и техническими менеджерами или тестировщиками, что позволяет убрать языковой барьер между всеми ними.
Data-Driven Testing (DDT) — тестирование, управляемое данными; подход к архитектуре автоматизированных тестов, при котором тестовые данные хранятся отдельно от тестов (в файле или базе данных).
Перепишем функцию pow2 из раздела TDD.
Что можно сделать?
Можно взять файл, содержащий степени двоек и подгружать данные из его.
Пишем функционал, загружающий данные из файла и возвращающий их в виде массива.
Пишем функционал для тестов таким образом, чтобы можно было запускать их с массивом данных.
Считываем данные из файла и запустить тесты.
Загружаем данные из другого файла или же из другого источника, снова запускаем тесты.
Keyword-Driven Testing (KDT) — тестирование, управляемое ключевыми словами; подход, использующий ключевые слова, описывающие набор действий, необходимых для выполнения определённого шага тестового сценария.
Для использования подхода нужно определить набор ключевых слов и сопоставить им действия (функции).
В KDT используется что-то вроде таблиц, чтобы ключевые слова могли иметь параметры, поэтому подход иногда называют Table-Driven Testing (TDT).
Пусть наш тестовый сценарий требует входа в пользовательский аккаунт, отправки двух сообщений на разные адреса и выход из аккаунта.
Сопоставим им функции.
Обработаем этот файл.
Осталось только считать строки из файла и выполнить то, что описано в каждой.
Тут можно сделать вспомогательную функцию.
Теперь можно выполнять любые последовательности, состоящие из определённых нами ключевых слов.
Для достижения изолированности какого-то блока тестируемого кода внешние зависимости при его тестировании заменяются тестовыми объектами.
Пустышка (Dummy) — простейший тестовый объект, реализующий интерфейс, минимально совместимый с интерфейсом реального объекта.
Код Dummy не содержит никакой логики.
Dummy используется в тех случаях, когда обращение к реальному объекту в данном тесте не имеет значения или отсутствует.
Например, нам в контексте теста не нужна проверка авторизации, поэтому мы заменяем реальную функцию checkAuth() на тестовую, которая всегда возвращает истиное значение.
Stub обычно содержит тривиальную логику, имитирующую работу нескольких методов реального объекта.
Например, имитируем создание пользователя в базе данных: принимаем данные пользователя и сразу же возвращаем полученные данные вместе с сгенерированным id (должен был сгенерироваться в бд).
Перепишем пример для Dummy так, чтобы он смог стать Stub (принимает валидные данные и отдаёт тоже).
Макет (Mockup) — модуль или класс, представляющий собой конкретную фиктивную (dummy) реализацию определенного интерфейса.
Макет, как правило, предназначен для подмены оригинального объекта системы исключительно для тестирования взаимодействия и изолированности тестируемого компонента.
Методы макета чаще всего из себя представляют заглушки.
Пусть имеется интерфейс, описывающий методы работы с базой данных.
Вместо того, чтобы использовать реальную базу данных, мы заменяем её фиктивной реализацией: реализуем интерфейс при помощи заглушек.
Объект-страница (Page Object Model, POM) — модуль (класс), представляющий интерфейс отдельной страницы тестируемой системы.
При использовании POM тесты оперируют с абстрактными объектами страниц и не завязаны на конкретную реализацию пользовательского интерфейса (его дизайн и вёрстку).
Тесты используют методы POM каждый раз, когда требуется взаимодействие с UI страницы.
Преимущества Page Object
Шпион (Spy) — объект-обёртка (по типу прокси), слушающий вызовы и сохраняющий информацию об этих вызовах (аргументы, количество вызовов, контекст) оригинального объекта системы.
Сохраненные шпионом данные используются в тестах.
Испытательная Платформа (TestBed) — это специально воссозданная тестовая среда, платформа для тестирования (например, комплекс Макетов, Заглушек и Шпионов).
Испытательная Платформа применяется для комплексного тестирования отдельных связок системы или её компонентов.
Фикстура (Fixture) — механизм, позволяющий привести объект или всю систему в определенное состояние и зафиксировать это состояние для тестов.
Под фикстурой чаще всего понимают тестовые данные необходимые для корректного запуска тестов, а также механизмы загрузки/выгрузки этих данных в хранилище.
Основное назначение фикстуры: привести данные системы к определенному (фиксированному) состоянию, которое будет точно известно во время выполнения тестов.