В своем текущем проекте (игра на C ++) я решил, что я буду использовать Test Driven Development на 100% во время разработки.
С точки зрения качества кода это было здорово. Мой код никогда не был так хорошо спроектирован или так без ошибок. Я не смущаюсь при просмотре кода, который я написал год назад в начале проекта, и у меня появилось гораздо лучшее понимание того, как структурировать вещи, чтобы не только быть более легко тестируемыми, но и быть проще в реализации и использовании ,
Однако ... прошел год с тех пор, как я начал проект. Конечно, я могу работать над этим только в свободное время, но TDD все еще значительно замедляет меня по сравнению с тем, к чему я привык. Я читал, что медленная скорость разработки со временем становится лучше, и я определенно думаю, что тесты гораздо проще, чем раньше, но я занимался этим уже год, и все еще работаю в темпе улитки.
Каждый раз, когда я думаю о следующем шаге, который требует работы, мне приходится каждый раз останавливаться и думать о том, как написать для него тест, чтобы позволить мне написать реальный код. Иногда я застреваю на несколько часов, точно зная, какой код я хочу написать, но не зная, как разбить его достаточно точно, чтобы полностью покрыть его тестами. В других случаях я быстро придумаю дюжину тестов и потрачу час на написание тестов, чтобы покрыть крошечный кусочек реального кода, который в противном случае занял бы несколько минут.
Или, после завершения 50-го теста, чтобы охватить конкретную сущность в игре и все аспекты ее создания и использования, я смотрю на свой список дел и вижу следующую сущность, подлежащую кодированию, и ужасаюсь от мысли о написании еще 50 аналогичных тестов для его реализации.
Дошло до того, что, глядя на прогресс прошлого года, я рассматриваю возможность отказаться от TDD ради «завершения чертового проекта». Тем не менее, отказ от качества кода, который пришел с ним, не то, чего я с нетерпением жду. Боюсь, что если я перестану писать тесты, я избавлюсь от привычки делать код таким модульным и тестируемым.
Возможно, я делаю что-то не так, чтобы все еще быть таким медленным в этом? Существуют ли альтернативы, которые ускоряют производительность без полной потери преимуществ? TAD? Меньше тестового покрытия? Как другие люди переживают TDD, не убивая всю производительность и мотивацию?
источник
Ответы:
Позвольте мне вначале поблагодарить вас за то, что вы поделились своим опытом и высказать свои опасения ... которые, я должен сказать, не редкость
И это подводит меня к последнему запросу: как мне стать лучше? Мой (или An) ответ: « Читай, размышляй и практикуйся».
Например, в последнее время я продолжаю следить за
источник
Вам не нужно 100% тестовое покрытие. Будьте прагматичны.
источник
a = x + y
и хотя все строки в коде выполнялись в тестах, тесты тестировались только для случая, когда y = 0, поэтому ошибка (так и должно было бытьa = x - y
) никогда не обнаруживалась в тестах.Это на самом деле неверно.
Без TDD вы тратите несколько недель на написание кода, который в основном работает, а в следующем году «тестируете» и исправляете многие (но не все) ошибки.
С TDD вы тратите год на написание кода, который действительно работает. Затем вы проводите окончательное интеграционное тестирование в течение нескольких недель.
Прошедшее время, вероятно, будет таким же. Программное обеспечение TDD будет значительно лучшего качества.
источник
Это заставляет меня задуматься о том, насколько сильно вы следуете этапу «Рефакторинг» TDD.
Когда все ваши тесты пройдены, настало время для рефакторинга кода и устранения дублирования. Хотя люди обычно помнят об этом, иногда они забывают, что пришло время и рефакторинг их тестов , чтобы удалить дублирование и упростить вещи.
Если у вас есть две сущности, которые объединяются в одну для повторного использования кода, рассмотрите возможность объединения их тестов. Вам действительно нужно только проверить инкрементные различия в вашем коде. Если вы не проводите регулярное обслуживание своих тестов, они могут быстро стать громоздкими.
Пара философских моментов о TDD, которые могут быть полезны:
РЕДАКТИРОВАТЬ: На тему философии модульного тестирования, я думаю, что это может быть интересно для вас прочитать: Путь Testivus
И более практичный, если не обязательно очень полезный, пункт:
источник
Очень интересный вопрос
Важно отметить, что C ++ не очень легко тестируется, и игры, в общем, также являются очень плохим кандидатом на TDD. Вы не можете проверить, если OpenGL / DirectX рисует красный треугольник с драйвером X и желтый с драйвером Y легко. Если нормальный вектор карты рельефа не перевернут после преобразования шейдера. Вы также не можете тестировать проблемы отсечения версий драйверов с различной точностью и так далее. Неопределенное поведение при рисовании из-за неправильных вызовов также может быть проверено только с точным просмотром кода и SDK под рукой. Звук тоже плохой кандидат. Многопоточность, которая, опять же, очень важна для игр, практически бесполезна для юнит-тестирования. Так что это сложно.
В основном в играх много GUI, звука и потоков. GUI, даже со стандартными компонентами, на которые вы можете отправить WM_, сложен для модульного тестирования.
Итак, что вы можете протестировать, так это классы загрузки моделей, классы загрузки текстур, библиотеки матриц и тому подобное, что не так много кода и, как правило, не очень многократно используется, если это только ваш первый проект. Кроме того, они упакованы в собственные форматы, поэтому маловероятно, что сторонние материалы могут сильно отличаться, если только вы не выпустите инструменты для моддинга и т. Д.
Опять же, я не гуру или евангелист TDD, так что возьмите все это с крошкой соли.
Возможно, я бы написал несколько тестов для основных компонентов ядра (например, матричная библиотека, библиотека изображений). Добавьте кучу
abort()
неожиданных входов в каждую функцию. И самое главное, сконцентрируйтесь на стойком / отказоустойчивом коде, который нелегко ломается.Что касается одних ошибок, умное использование C ++, RAII и хороший дизайн имеют большое значение для их предотвращения.
По сути, вам нужно многое сделать, чтобы охватить основы, если вы хотите выпустить игру. Я не уверен, поможет ли TDD.
источник
Я согласен с другими ответами, но я также хочу добавить очень важный момент: рефакторинг затрат!
С хорошо написанными модульными тестами вы можете безопасно переписывать свой код. Во-первых, хорошо написанные модульные тесты предоставляют отличную документацию о намерениях вашего кода. Во-вторых, любые неблагоприятные побочные эффекты вашего рефакторинга будут обнаружены в существующем наборе тестов. Таким образом, вы гарантировали, что допущения вашего старого кода верны и для вашего нового кода.
источник
Это полностью отличается от моего опыта. Вы либо поразительно умны и пишете код без ошибок (например, от одной ошибки), либо не понимаете, что в вашем коде есть ошибки, которые мешают работе вашей программы, и поэтому на самом деле они не завершены.
TDD - это смирение, чтобы знать, что вы (и я!) Совершаете ошибки.
Для меня время написания юнит-тестов более чем сэкономлено за счет сокращения времени отладки для проектов, которые выполняются с использованием TDD с самого начала.
Если вы не делаете ошибок, возможно, TDD не так важен для вас, как для меня!
источник
У меня есть только несколько замечаний:
Кажется, вы пытаетесь все проверить . Вы, вероятно, не должны, только случаи высокого риска и крайние случаи конкретного куска кода / метода. Я почти уверен, что здесь применимо правило 80/20: вы тратите 80% на написание тестов для последних 20% своего кода или случаев, которые не охвачены.
Расставлять приоритеты. Начните гибкую разработку программного обеспечения и составьте список того, что вам действительно нужно сделать, чтобы выпустить его за один месяц. Тогда отпустите, просто так. Это заставит вас задуматься о приоритете функций. Да, было бы здорово, если бы ваш персонаж мог сделать сальто назад, но имеет ли это деловую ценность ?
TDD хорош, но только если вы не стремитесь к 100-процентному тестовому покрытию, и это не так, если он не позволяет вам создавать реальную ценность для бизнеса (т.е. функции, вещи, которые добавляют что-то в вашу игру).
источник
Да, написание тестов и кода может занять больше времени, чем просто написание кода, но написание кода и связанных с ним модульных тестов (с использованием TDD) гораздо более предсказуемо, чем написание кода и его отладка.
Отладка практически исключается при использовании TDD, что делает весь процесс разработки гораздо более предсказуемым и, в конце концов, возможно более быстрым.
Постоянный рефакторинг - невозможно провести серьезный рефакторинг без комплексного модульного тестирования. Наиболее эффективный способ создания этой системы безопасности на основе модульного тестирования - это TDD. Хорошо переработанный код значительно повышает общую производительность дизайнера / команды, которая поддерживает код.
источник
Подумайте о том, чтобы сузить сферу своей игры и найти ее там, где кто-то может сыграть или вы ее выпустите. Поддержание ваших стандартов тестирования без необходимости ждать слишком долго, чтобы выпустить вашу игру, может быть промежуточным звеном, чтобы поддержать вас. Отзывы ваших пользователей могут принести пользу в долгосрочной перспективе, а ваше тестирование позволит вам чувствовать себя комфортно с дополнениями и изменениями.
источник