TDD - проблемы новичка и камни преткновения

В то время как я записал модульные тесты на большую часть кода, я сделал, я только недавно достал копию TDD примером Kent Beck. Я всегда сожалел об определенных проектных решениях, которые я сделал, так как они препятствовали тому, чтобы приложение было 'тестируемым'. Я прочитал книгу и в то время как часть ее выглядит посторонней, я чувствовал, что мог управлять ею и решенный для испытания ее на моем текущем проекте, который является в основном клиент-серверной системой, куда эти две части связываются через. USB. Один на гаджете и другом на хосте. Приложение находится в Python.

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

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

  1. Kent Beck использует список, к которому он добавляет и наносит удар из вести процесс разработки. Как Вы составляете такой список? У меня первоначально было несколько объектов как "сервер, должен запустить", "сервер должен прерваться, если канал не доступен" и т.д., но они были смешаны и наконец теперь, это просто, что-то как "клиент должно смочь соединиться с сервером" (который включил в категорию запуск сервера и т.д.).
  2. То, как делают Вы обрабатываете, переписывает? Я первоначально выбрал половину дуплексной системы на основе именованных каналов так, чтобы я мог разработать прикладную логику на своей собственной машине и затем позже добавить коммуникационную часть USB. Это их перемещенный для становления основанной на сокете вещью и затем перемещенный от использования неструктурированных сокетов к использованию модуля Python SocketServer. Каждый раз измененные вещи, я нашел, что должен был переписать значительные части тестов, который был раздражающим. Я полагал, что тесты будут несколько постоянным руководством во время моей разработки. Они просто чувствовали себя подобно большему количеству кода для обработки.
  3. Мне были нужны клиент и сервер для передачи через канал для тестирования любой стороны. Я мог дразнить одну из сторон для тестирования другой, но затем целый канал не будет протестирован, и я волнуюсь, что пропустил бы это. Это умалило целый красный/зеленый/осуществлять рефакторинг ритм. Это - просто отсутствие опыта, или я делаю что-то не так?
  4. "Фальшивка она, пока Вы не делаете его", оставила меня с большим количеством грязного кода, который я позже провел много времени, чтобы осуществить рефакторинг и очистить. Действительно ли это - способ, которым работают вещи?
  5. В конце сессии у меня теперь есть свой клиент и сервер, работающий приблизительно с 3 или 4 модульными тестами. Мне потребовалась приблизительно неделя, чтобы сделать это. Я думаю, что, возможно, сделал это через день, если я использовал модульные тесты после кода путь. Мне не удается видеть усиление.

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

P.S.: сообщите мне, должна ли это быть общественная Wiki, и я отмечу ее как этот.

Обновление 0: Все ответы были одинаково полезны. Я выбрал тот, который я сделал, потому что он нашел отклик у моих событий больше всего.

Обновление 1: практика практики практики!

23
задан Community 23 May 2017 в 12:07
поделиться

7 ответов

Как предварительный комментарий, TDD занимается практикой. Когда я оглядываюсь на тесты, я написал, когда я начал TDD, я вижу много проблем, так же, как когда я смотрю на код, который я написал несколько лет назад. Продолжайте делать это, и так же, как вы начинаете признавать хороший код из плохих, то же самое произойдет с вашими тестами - с терпением.

Как вы делаете такой список? я Изначально имел несколько таких предметов «Сервер» следует запуск "," сервер должен прервать Если канал недоступен "и т. д. Но они были смешаны и наконец сейчас, это просто что-то вроде "клиент должен быть Способен подключаться к серверу «

« Список »может быть довольно неформальным (это дело в книге Beck), но когда вы перемещаетесь в создание предметов в тесты, попробуйте написать заявления в« [когда что-то происходит с этим » ] Тогда [это условие должно быть верно в том, что] «формат. Это заставит вас заставить вас думать о том, что вы проверяете, как вы его проверяете и переводятся непосредственно в тесты - или если это не должно дать вам Подсказка о том, какой кусок функциональности отсутствует. Думаю использовать Case / сценарий. Например, «Сервер должен запустить» неясно, потому что никто не инициирует действие.

Каждый раз, когда все изменилось, я обнаружил, что Я должен был переписать значительные части тесты, которые раздражали. Идентификатор подумал, что тесты будут несколько неизменных руководств во время моего разработка. Они просто чувствовали себя больше код для обработки.

Во-первых, да, тесты - это больше кода, и требует обслуживания - и писать ремонтопригодные испытания практикуются. Я согласен с S. Lott, если вам нужно много изменять свои тесты, вы, вероятно, тестируете «слишком глубоко». В идеале вы хотите проверить на уровне общедоступного интерфейса, который вряд ли изменится, а не на уровне деталей реализации, что может развиваться. Но часть упражнений происходит придумать с дизайном, поэтому вы должны ожидать, чтобы получить его неправильно и придется также перемещать / рефакторизовать свои тесты.

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

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

«подделка, пока не сделаешь это», оставило меня с большим грязным кодом, который я позже провел много времени на рефтектора и убирать. Это то, как вещи работают?

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

Я думаю, что я мог бы сделать это за день Если бы я использовал тесты подразделения после кодовый путь. Я не могу видеть выгоду.

Опять же, практикуется, и вы должны получить быстрее со временем. Кроме того, иногда TDD более плодотворна, чем другие, я обнаруживаю, что в некоторых ситуациях, когда я знаю, что именно код, который я хочу написать, это просто быстрее написать хорошую часть кода, а затем писать тесты.
Кроме того, Beck, одна книга, которую мне понравилось, - это искусство тестирования подразделения, Рой Осерово. Это не книга TDD, и она ориентирована на .NET, но вы, возможно, захотите поверить в любом случае: хорошая часть - о том, как писать ремонтопригодные тесты, тесты качества и связанные с ними вопросы. Я обнаружил, что книга реновала с моим опытом после написания тестов, а иногда изо всех сил пыталась сделать это правильно ...
Так что мой совет, не бросайте полотенце слишком быстро и дайте ему некоторое время. Вы можете также захотеть дать ему выстрел на что-то проще - тестирование Сервера Связь, связанные с этим, что не звучит, как самый простой проект, чтобы начать!

10
ответ дан 29 November 2019 в 02:46
поделиться

Я никогда об этом не слышал, и единственное, что я нахожу в Google, это " IP * Works! ", но это, похоже, рамка Mac (и может не работать на iPhone, если она не скомпилирована как файл .a).

Ваша лучшая ставка может заключаться в том, чтобы свернуть свой собственный. http://cocoabuilder.com имеет в своих архивах несколько электронных писем о людях, просящих библиотеки SNMP, но ответы так и не были получены.

-121--4950822-

С подстановками:

'/\b(?![0-9]+\b)(?![a-z]+\b)[0-9a-z]+\b/i'

Быстрый тест, который также показывает пример использования:

$str = 'foo bar F0O 8ar';
$arr = array();
preg_match_all('/\b(?![0-9]+\b)(?![a-z]+\b)[0-9a-z]+\b/i', $str, $arr);
print_r($arr);

Output:

F0O
8ar
-121--4817978-

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

Вместо того, чтобы рассматривать другие точки по очереди, я предложу некоторые глобальные советы. Практика. Мне потребовалось хорошее время и несколько «дерзких» проектов (личных, хотя), чтобы реально получить TDD. Просто Google по гораздо более убедительным причинам, почему TDD так хорош.

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

Одна вещь, которая выделялась из вашего вопроса, - это акт повторного переписывания ваших тестов. Похоже, вы проводите поведенческие тесты, а не государственные. Другими словами, тесты слишком тесно связаны с вашим кодом. Таким образом, простое изменение, которое не влияет на выходные данные, нарушит некоторые тесты. Модульное тестирование (по крайней мере, хорошее модульное тестирование) тоже является навыком для овладения.

Я рекомендую Google Testing Blog довольно сильно, потому что некоторые статьи на там сделали мое тестирование для проектов TDD намного лучше.

1
ответ дан 29 November 2019 в 02:46
поделиться

именованные каналы были помещены позади правильного интерфейса, изменившись, как тот интерфейс реализован (с именованных каналов на сокеты к другой библиотеке сокетов), должен только испытания на удар для компонента, который реализует тот интерфейс. Так вырезание вещей больше/по-другому помогло бы... Тот интерфейс сокеты находятся позади, вероятно, разовьется к.

я начал делать TDD, возможно, 6 месяцев назад? Я все еще изучаю меня. Я могу говорить со временем, что мои тесты и код стали намного лучше, поэтому продолжите его. Я действительно рекомендую книге Шаблоны разработки XUnit также.

1
ответ дан 29 November 2019 в 02:46
поделиться

Идея, требующая реализации:

Можно написать функцию, которая при вызове проверяет, остается ли единственный буфер (или, возможно, единственный буфер, не являющийся буфером помощи, если вы предпочитаете) NERDTree, и, если это так, удаляет его (или просто выходит).

Тогда у вас есть autocmd запустить его всякий раз, когда буфер удален/скрыт/что на самом деле происходит, когда вы: q (это позорит меня признать, что я не совсем уверен!).

-121--1063039-
  1. Кент Бек использует список... Наконец, теперь это просто что-то вроде «клиент должен быть в состоянии подключиться к серверу» (который вложил запуск сервера и т.д.).

Часто плохая практика.

Отдельные тесты для каждого отдельного уровня архитектуры являются хорошими.

Консолидированные тесты, как правило, скрывают архитектурные проблемы.

Однако проверяют только публичные функции. Не каждая функция.

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

2. Как вы справляетесь с переписями?... Я обнаружил, что пришлось переписать немалые части тестов.

Вы тестируетесь на слишком низком уровне детализации. Протестируйте внешний, открытый, видимый интерфейс. Часть, которая должна быть неизменной.

И

Да, значительное изменение архитектуры означает существенное изменение тестирования.

И

Код теста - это то, как вы доказываете работу. Это почти так же важно, как и само приложение. Да, это больше кода. Да, ты должен им управлять.

3. Мне нужен был клиент и сервер для связи через канал, чтобы протестировать любую сторону. Я мог бы поиздеваться над одной из сторон, чтобы проверить другую, но тогда весь канал не будет проверен...

Есть единичные тесты. С насмешками.

Есть интеграционные тесты, которые проверяют все это.

Не путайте их.

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

И вам нужно сделать и то, и другое.

4. «Подделка, пока не сделаешь» оставила мне много грязного кода, который я потом потратил много времени на восстановление и очистку. Так ли обстоят дела?

Да. Именно так это и работает. В конечном итоге, некоторые люди находят это более эффективным, чем напрягать свой мозг, пытаясь сделать весь дизайн заранее. Некоторые люди не любят это и хотят делать весь дизайн заранее; вы можете делать много дизайна, если хотите.

Я обнаружил, что рефакторинг - это хорошая вещь, и дизайн спереди слишком труден. Может, это потому, что я кодирую почти 40 лет и мой мозг изнашивается.

5. Я не вижу выигрыша.

Все истинные гении обнаруживают, что тестирование замедляет их.

Остальные из нас не могут быть уверены, что наш код работает, пока мы не получим полный набор тестов, которые докажут , что он работает.

Если вам не требуется подтверждение того, что ваш код работает, вам не требуется тестирование.

8
ответ дан 29 November 2019 в 02:46
поделиться

Как вы делаете такой список, чтобы добавить в и вычеркните, чтобы направить процесс разработки? Я изначально имел Немногие элементы, такие как «Сервер, должен начать вверх "," сервер должен прервать, если канал Недоступно, «

элементы в списках TDD TodDo являются более тонкими, что они стремятся к тестированию одного поведения одного метода, например, только для тестирования одного поведения одного метода:

  • Испытание Успешное клиентское соединение
  • Ошибка ошибки подключения клиента теста Тип 1
  • Испытание клиент-соединение Ошибка типа 2
  • Испытание Успешное клиентская связь
  • Тестовая клиентская связь не удается при отсутствии подключения

, вы можете построить список тестов (положительных и отрицательных) для каждого приведенного вами. Вы не устанавливаете никакой связи между сервером и клиентом. Вы только что вызываете методы в изоляции, ... это ответы Вопрос 3.

Как вы обрабатываете переписывание?

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

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

1
ответ дан 29 November 2019 в 02:46
поделиться

Если он представляет точку времени, вы обязательно должны использовать UTC. Это звучит как правильный выбор в этом конкретном случае.

В некоторые другие случаи, вы хотите хранить в местном времени - например, для представления тревоги, который должен выходить на 8 утра в местное время, в любой часовой пояс пользователь. Это Обычно полезно для календаряных приложений ... и вы не храните единую точку во времени здесь.

Один конкретный пример того, почему стоит хранить точки во времени в UTC, заключается в том, что местные времена могут быть неоднозначными из-за летних переходов - если часы возвращаются с 2 утра до 1 утра, там будет местное время 1:30 дважды. В UTC такая двусмысленность нет.

-121--3286752-

Q. Кент Бек использует список, который он добавляет и ударяет от того, чтобы направлять процесс разработки. Как вы делаете такой список? Я изначально имел несколько таких предметов, как «сервер должен запустить», «Сервер должен прервать, если канал недоступен» и т. Д. Но они были смешаны и, наконец, теперь это просто что-то вроде «Клиент должен быть в состоянии подключиться к серверу» (который Подключенный сервер запуска и т. Д.).

Я начинаю, собирая все, что я мог бы проверить. В вашем примере вы выбрали «Сервер запуска».

Server starts

Теперь я ищу любой простой тест, который я мог бы захотеть написать. Что-то с меньшим изменением и меньше движущихся частей. Я мог бы рассмотреть «сконфигурированный сервер правильно», например.

Configured server correctly
Server starts

Действительно, хотя «Сервер запускается» зависит от «Настроенных серверов правильно», поэтому я делаю эту ссылку очистить.

Configured server correctly
Server starts if configured correctly

Теперь я ищу вариации. Я спрашиваю: «Что может пойти не так?» Я мог настроить сервер неправильно. Сколько разных способов? Каждый из тех делает тест. Как сервер не начнется, хотя я правильно настроил это правильно? Каждый случай этого делает тест.

Q. Как вы обрабатыете переписать? Первоначально я выбрал половинную дуплексную систему на основе именованных труб, чтобы я мог бы разработать логику приложений на своей собственной машине, а затем позже добавить часть коммуникации USB. Их они переехали, чтобы стать вещью на основе сокета, а затем переместилась из используя сырые розетки для использования модуля Python SocketServer. Каждый раз, когда все изменилось, я обнаружил, что пришлось переписать значительные части испытаний, которые раздражали. Я бы подумал, что испытания будут несколько неизменным руководством во время моего развития. Они просто почувствовали себя большекором для обработки кода.

Когда я изменяю поведение, я считаю разумным изменить тесты, и даже изменить их первым! Если я должен изменить тесты, которые не проверяют непосредственно поведение, я в процессе изменения, хотя это признак того, что мои тесты зависят от слишком большого количества разных поведений. Это тесты интеграции, которые, я думаю, являются афером. (Тесты интеграции Google "- это мошенничество")

q. Мне нужен был клиент и сервер для связи через канал для проверки обеих сторон. Я мог бы издеваться над одной из сторон, чтобы проверить другой, но тогда весь канал не будет проверен, и я беспокоюсь, что я пропустил это. Это затруднено от всего красного / зеленого / рефакториста. Это просто не хватает опыта или я делаю что-то не так?

Если я построю клиент, сервер и канал, то я пытаюсь проверять каждый изоляцию. Я начинаю с клиента, и когда я проверяю его, я решаю, как надо вести сервер и канал. Затем я реализую канал и сервер каждый, чтобы соответствовать поведению, которое мне нужно. При проверке клиента я заглушаю канал; При проверке сервера я издеваюсь на канал; При проверке канала я заглушку и издеваюсь как клиент, так и сервер. Я надеюсь, что это имеет смысл вам, так как я должен сделать некоторые серьезные предположения о природе этого клиента, сервера и канала.

q. «Поддействуйте это, пока вы не сделаете его», оставили меня много грязного кода, который я позже провел много времени, чтобы рефакторировать и убирать. Это то, как вещи работают?

Если вы позволите своему «поддельному» коду стать очень грязным, прежде чем убирать его, то вы могли бы потратить слишком долго. Тем не менее, я обнаружил, что, хотя я в конечном итоге убираю больше кода с TDD, общий ритм чувствует себя гораздо лучше. Это происходит от практики.

q. В конце сеанса у меня теперь есть мой клиент и сервер работает с 3 или 4 модульными тестами. Мне потребовалось около недели, чтобы сделать это. Я думаю, что я мог бы сделать это за день, если бы я использовал тесты подразделения после кода. Я не могу видеть выгоду.

Я должен сказать, что, если ваш клиент и сервер не очень просты, вам нужно более 3 или 4 теста каждый, чтобы тщательно проверить их. Я догадаюсь, что ваши тесты проверяют (или, по крайней мере, выполняют) ряд различных поведений сразу, и это может объяснить усилия, которые потребовали их, чтобы написать их.

Также не измеряйте кривую обучения. Мой первый настоящий опыт TDD состоял из повторной записи работ на 3 месяца в 9, 14-часовых днях. У меня было 125 тестов, которые заняли 12 минут. Я понятия не имел, что я делал, и он чувствовал себя медленно, но он чувствовал себя устойчивым, и результаты были фантастическими. Я, по сути написал через 3 недели то, что первоначально заняло 3 месяца, чтобы ошибаться. Если я написал это сейчас, я мог бы сделать это через 3-5 дней. Разница? Мой тестовый люкс будет иметь 500 тестов, которые занимают 1-2 секунды. Это пришло с практикой.

3
ответ дан 29 November 2019 в 02:46
поделиться

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

Для новичка это не совсем так. Дизайн на первом месте. (Интерфейсы, объекты и классы, методы, все, что соответствует вашему языку). Затем вы пишете на это свои тесты. Потом пишете код, который на самом деле что-то делает.

Прошло много времени с тех пор, как я посмотрел книгу, но Бек, кажется, пишет так, как будто дизайн кода просто бессознательно происходит у тебя в голове. Для опытных программистов это может быть правдой, но для таких глупцов, как я, не-а.

Первые несколько глав Code Complete я нашел действительно полезными для размышлений о дизайне. Они подчеркивают тот факт, что ваш дизайн вполне может измениться, даже если вы находитесь на низком уровне реализации. Когда это произойдет, вам, возможно, придется переписать свои тесты, потому что они были основаны на тех же предположениях, что и ваш дизайн.

Кодировать сложно. Пойдем за покупками.

2
ответ дан 29 November 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: