- PVSM.RU - https://www.pvsm.ru -
Я читал про BDD, и понял одну вещь: BDD это блаблабла блабла бла. Нету у него нормального определения. Вот, например, написано:
BDD совмещает в себе основные техники и практики TDD и идеи DDD для того чтобы предоставить программистам, тестерам, аналитикам и менеджерам общий процесс взаимодействия по ходу разработки ПО.
Все понятно? Мне — ничего. Поэтому я расскажу, что мы делаем и зачем, из того, что может иметь отношение к BDD.
Приступая к планированию фичи, мы описываем ее в терминах «поведения системы», например:
Given Jira Issue with several bugs
When all that bugs are fixed
Then Issue is closed
Мы это пишем прямо на доске, по ходу планинга, вместе с Product Owner, в таком объеме, чтобы было понятно заказчику (product owner) и тестировщикам, и разработчикам: что же нам надо сделать, и как это тестировать. По сути, это требования/тесты, которые записываются в таком «кратком» (и заметьте, не четком) виде, всей командой, не тратя на это много времени. И больше никакой документации, только слова. Понимаю, это довольно «дикий» случай, и не всегда так все просто, но в любом случае, мы стараемся выделить бизнес проблему, и записать наиболее краткое решение, не вдаваясь в детали. Детали идут потом, они могут быть оговорены на планинге или выясняться уже по ходу разработки с PO (да, у нас заказчик быстро отвечает на вопросы), но они не документируются и не тестируются и никто не будет их читать.
Только не путайте описание поведения и системную документацию. Поведение может (и будет) меняться. Сегодня эта копка делает одно, завтра уже другое. Приведенное описание поведения устаревает с каждым спринтом/итерацией, на него нельзя полагаться и выяснить то, как же устроена фича спустя некоторое время. Поэтому существует системная документация, где описывается весь актуальный функционал. Нет, у нас такой документации нет, у нас все в голове и коде. И пока, лично я, не испытывал неудобств. А что будет если голова попадет под автобус? Я тоже задавал такой вопрос. Мне сказали: будет плохо, но мы не верим что документация спасет, вряд ли ее будут всю читать, и вряд ли она будет столь актуальна и сможет дать ответы так же, как голова.
Теперь про тесты. Есть замечательная штука — Cucumber (и еще похожее: concordion [1]). Он позволяет сопоставить каждой проcтой строчке текста (такой как: «all that bugs are fixed») свой метод на .Net,Java,Ruby и других языках программирования, и даже позволяет выделить переменные с помощью регулярных выражений, чтобы можно было повторно использовать методы.
И благодаря cucumber, все тесты имеют отличный читаемый вид, они отражают текущее состояние системы и могут являться своебразной системной документацией, а к тому же они уже написаны на планинге!
Все вроде замечательно, но мы не используем Cucumber, потому что:
Test), принимают на вход сложные значения/объекты (Map), которые трудно записать в простой текстовой форме и распарсить с помощью регулярных выражений.Вместо того, чтобы тратить усилия на разработку простотекстовых сценариев с помощью Cucumber, мы пишем их на Java (как и остальной проект) и тратим усилия на то, чтобы код был «чистым» и читаемым.
Вышесказанное не является критикой Cucumber, это отличная и нужная штука, просто в нашем случае она создала бы больше проблем чем решений (по-моему субъективному мнению).
Рассмотрим пример кода, соответcтвующий, приведенному выше, описанию поведения:
String issueId = issueHelper().createIssue();
List bugIds = new ArrayList();
int numberOfBugs = Random.getNumberBetween(1, 5);
while(numberOfBugs>0){
bugIds.add(issueHelper().createBug(issueId));
numberOfBugs--;
}
for(String bugId : bugIds){
navigator().goto(bugId);
workflowHelper().doAction("fixed");
}
navigator().goto(issueId);
assertThat(getField("status"),is("Closed"));
При выполнении теста, этот код выводит следующее:
Создать Issue с произвольными параметрами (Ключ нового issue HR-17)
Создать Bug на issue HR-17 (Ключ нового бага BG-26)
Создать Bug на issue HR-17 (Ключ нового бага BG-27)
Перейти на страницу по ключу BG-26
Выполнить действие fixed
Перейти на страницу по ключу BG-27
Выполнить действие fixed
Перейти на страницу по ключу HR-17
Проверить что Значение поля status is «Closed»
Такой тестовый вывод очень похож на cucumber сценарий в моем предыдущем проекте, и может читаться аналитиками/менеджерами (я проверял). Они могут даже проводить своеобразное «code review» того, на сколько соответствует лог первоначальному BDD описанию.
Потому у нас и получается «BDD наоборот».
Иногда аналитикам или разработчикам по ходу code review может что-то не понравится, тогда мы можем всего за пару кликов отрефакторить код, например объединить методы «Перейти на страницу по ключу» и «Выполнить действие» в один метод.
Вы могли заметить, что в коде теста нет никаких комментариев или специальных вызовов, которые могли бы выводить такой лог, и это не случайно.
Весь вывод лога сделан на основе технологии AspectJ, которая позволяет перехватывать любые вызовы методов и оборачивать их своим кодам. В нашем случае, мы выводим в лог описание метода из JavaDoc, подставляя в него значения параметров, с которыми произошел вызов и, если возможно, то возвращаемое методом значение.
Мы делаем то же самое, что в технологии Cucumber, с точностью до наоборот. В Сucumber, мы каждому методу сопоставляем регулярное выражение (или шаблон), согласно которому мы будем выделять переменные из текстовой строчки, у нас же, мы сопоставляем шаблон, в который мы будем подставлять переменные в выводимую строчку лога.
Какой в этом всем смысл?
С точки зрения BDD, документации и совместной работы всех вместе, в обнимку — не знаю.
Но я знаю точно, в красивом логе тестов, смысл есть:
log("I did something"). Тогда Вам приходится выделять методы, соответствующие бизнес понятиям, а потом, глядишь, и кода меньше дублируется, и структурирован он лучше. И следить за этим может аналитик, без опыта программирования, который скажет — ваш код оперирует бизнес понятиями, или какие-то непонятные кнопки нажимает, т.е. скатился куда-то, на нижний уровень интерфейсных галочек. Соответственно тесты короче и понятнее.doSomething(getSomething()) в лог doSomething() подставлялся не просто результат метода getSomething() (например просто 5), а с описанием из JavaDoc метода getSomething(), чтобы было понятно, что означает этот результат (5) и откуда он взялся. Я этим обязательно займусь, когда меня в очередной раз «все задолбает».Если кому-то интересны технические детали: как парсить JavaDoc, как работать c AspectJ, напишите коммент, и я подготовлю об этом отдельный пост, в котором также расскажу, как можно в JavaDoc запихнуть таблицу с тестовыми данными в простой текстовой форме (скопипастив ее из Excel), и сделать так, чтобы тестовый метод вызывался для каждой строчки этой таблицы — это, как раз то, как работает Cucumber, аналитикам это нравится, я же не вижу в этом прелести. А вы что думаете?
Мораль сей басни такова: экспериментируйте, пишите тесты, и лог вам в помощь.
Автор: susliks
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/testirovanie/14176
Ссылки в тексте:
[1] concordion: http://www.concordion.org/
Нажмите здесь для печати.