Почему автоматическое тестирование не проходит в моей компании?

178

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

Несколько замечаний и вопросов:

  1. Автоматическое тестирование действительно работает? Большинство моих коллег, которые раньше работали в других компаниях, пытались и не смогли реализовать стратегию автоматизированного тестирования. Я до сих пор не видел реальной компании по разработке программного обеспечения, которая на самом деле использует ее, а не просто говорит об этом. Поэтому многие разработчики видят в автоматизированном тестировании нечто отличное в теории, но не работающее в реальности. Наша бизнес-команда хотела бы, чтобы разработчики делали это даже за 30% дополнительного времени (по крайней мере, так говорят). Но разработчики скептики.

  2. Никто действительно не знает, как правильно проводить автоматизированное тестирование. Да, мы все читали примеры модульного тестирования в Интернете, но их использование для большого проекта - это совсем другое. Основным виновником является насмешка над базой данных или что-то еще, что не является тривиальным. Вы тратите больше времени на насмешки, чем на написание реальных тестов. Затем, когда для написания тестов требуется больше времени, чем для кода, вы отказываетесь.

  3. Есть ли хорошие примеры модульных тестов / тестов системной интеграции, используемых в сложных ориентированных на данные веб-приложениях? Какие-нибудь проекты с открытым исходным кодом? Наше приложение ориентировано на данные, но также имеет много логики предметной области. В какой-то момент я попробовал подход с хранилищем и нашел его довольно хорошим для модульного тестирования, но он пришел ценой возможности легко оптимизировать доступ к данным и добавил еще один уровень сложности.

У нас большой проект, реализованный 20 опытными разработчиками. Казалось бы, это идеальная среда для внедрения модульного тестирования / интеграционного тестирования.

Почему это не работает для нас? Как вы заставили это работать в вашей компании?

Mag20
источник
14
Какой у вас технологический стек?
Флориан Маргэйн
7
Веб-формы практически невозможно правильно протестировать. Вы можете использовать шаблон MVP (Модель / Представление / Представитель) для перемещения логики представления в тестируемый компонент.
Пит
12
@MasonWheeler: В обоих случаях вы создали потрясающий аргумент, который опровергает предпосылки, которые не были приняты в первую очередь: то есть, что существуют модульные тесты, чтобы доказать правильность.
Стивен Эверс
10
@ MasonWheeler - Используя этот аргумент, вы никогда не должны пытаться проводить QA, потому что вы никогда не докажете, что ошибок нет. Это даже не цель. Хорошая стратегия автоматизированного пользовательского интерфейса и модульного тестирования состоит в том, чтобы просто освободить QA от тестирования и дать им возможность сосредоточиться на предварительном тестировании.
Алекс
15
Я шокирован тем, что несколько человек заявили, что они никогда не видели автоматизированного тестирования более нескольких месяцев. Я работал консультантом в пяти крупных компаниях в Германии, и они уволили бы вас, если бы вы не написали тесты. Автоматизированное тестирование не является теоретическим предметом, оно успешно практикуется во всем мире и значительно повышает качество кода (если все сделано правильно).

Ответы:

89

Самая сложная часть модульного тестирования - это научить писать тесты сначала / рано. Большинство разработчиков привыкли просто погружаться в код. Это также замедляет процесс разработки на раннем этапе, так как вы пытаетесь выяснить, как написать тест для кода. Однако, по мере того, как вы становитесь лучше в тестировании, это ускоряется. И из-за написания тестов начальное качество кода начинается с более высокого уровня.

Когда вы начинаете, попробуйте просто написать тесты. Не стоит так сильно беспокоиться о насмешках / заглушках. Сделайте тесты простыми. Тесты являются кодом и могут / должны быть реорганизованы. Хотя в этом отношении, если что-то трудно проверить, это может быть и дизайн. TDD действительно использует большинство шаблонов проектирования (по моему опыту, в частности, шаблон Factory).

Убедитесь, что тесты получают уровень видимости. Интегрируйте их в процесс выпуска, во время проверки кода спросите о них. Любые найденные ошибки должны пройти проверку. Эти вещи - то, где TDD сияет.

Вот несколько ресурсов, которые я нашел полезными:

http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf

http://www.agitar.com/downloads/TheWayOfTestivus.pdf

Редактировать:

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

Schleis
источник
Еще один способ подойти к представлению этого в качестве диагностической функции ... он же самопроверка при включении питания (POST), которая может почти доставлять код клиента ... а не просто набор простых тестов, какими должны быть тесты и функции.
JustinC
Также избегайте TDD Anti-Patterns .
Гэри Роу
4
Misko Hevery также имеет несколько отличных видео на YouTube о написании тестируемого кода, который я считаю бесценным. youtube.com/watch?v=acjvKJiOvXw
Despertar
«Убедитесь, что тесты получают уровень видимости» - это очень важно для успеха. Если никто не может увидеть, как выполняются ваши тесты, они не увидят значения. Тесты должны выполняться при регистрации автоматически в рамках непрерывной интеграции, а затем сообщаться. Я работаю в Tesults ( tesults.com ), и причина, по которой он существует, заключается в том, что из-за огромного влияния, которое дает тестовый обзор.
Умение M2
77

Во многом я согласен с вашей командой.

  1. Большинство модульных тестов сомнительны по стоимости. Поскольку подавляющее большинство тестов кажутся слишком простыми.

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

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

  4. Выяснение того, как адекватно протестировать более сложный код (т. Е. Материал, который вы действительно заинтересованы в тщательном тестировании), выходит за рамки возможностей многих разработчиков.

  5. Ведение юнит-тестов занимает слишком много времени. Небольшие изменения могут иметь большой волновой эффект. Основная цель автоматизированных модульных тестов - выяснить, не нарушают ли изменения код. Тем не менее, 99% времени заканчиваются взломом тестов, а не кода.

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

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

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

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

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

Замочить
источник
24
Я склонен с этим согласиться. Мы привыкли делать тесты только после того, как что-то сломалось (даже если это было во время разработки). Никогда не заблаговременно, занимает слишком много времени за слишком маленькое вознаграждение.
Изката
5
@Izkata другой подход, который я видел успешно реализованным, состоит в том, чтобы написать относительно небольшое количество высокоуровневых тестов, вызывающих метод верхнего уровня Frobinate()(вместо десятков более мелких методов, вызываемых под ним) после проверки системы другими средствами для обслуживания. как тест дыма, что ни одно из изменений более низкого уровня ничего не сломало. Как правило, в этих тестах использовались те же данные, которые составляли часть фунта в пользовательских тестах клавиатуры, чтобы клиент мог видеть, что система делает то, что хочет. Впоследствии инструменты покрытия кода могут идентифицировать, где крайние случаи еще не покрываются.
Дэн Нили,
3
Я не сказал «полномасштабное автоматическое тестирование», я сказал «полномасштабное автоматическое тестирование UNIT». Большая разница. Я использовал автоматическое тестирование на уровне модулей, по крайней мере, десять лет. Модульное тестирование на уровне класса. Я считаю, что я получаю больше отдачи при тестировании классов, которые должны работать вместе, а не как отдельные лица. Тем не менее, даже там мы все еще используем прагматичный подход и выборочно выбираем, что / где писать автоматизированные тесты.
Данк
2
Без хорошего охвата модульных тестов, как вы рефакторинг? Или без рефакторинга, как вы препятствуете постепенному вырождению кода до неуправляемости?
Кевин Клайн
1
@ Леонардо Они не сделали - они были слишком напуганы, чтобы что-то изменить. Или же они накопили весь этот технический долг и отложили несколько недель / месяцев спустя, чтобы решить его одним махом.
GraemeF
34

Основным виновником является издевательство над базой данных или что-то непростое.

И есть твоя проблема.

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

Уничтожение базы данных должно быть очень простым. Вместо того, чтобы ваш интерфейс обращался к какой-либо базе данных БД, чтобы предоставить ее результаты, вы помещаете простой жестко закодированный объект. Если вы не можете этого сделать, то у вашего дизайна / архитектуры есть проблемы. Ваш код предполагает, что он собирается в базу данных, или у вас нет абстракции интерфейса для его изменения.

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

Telastyn
источник
4
Жесткое кодирование возвращаемых значений базы данных из небольшой заглушки фиктивного объекта - хороший способ изолировать тест от всего в базе данных, которое может изменить и нарушить код (например, переименование столбцов). Это целесообразно при определенных обстоятельствах, но важно иметь простую в использовании временную базу данных тестирования, если вы не хотите, чтобы когда-нибудь что-то сломалось, когда вы ее измените. Если ваш код не работает, когда вы меняете базу данных, это ошибка кода, который должен поймать тест (и если вы хотите избежать этого, вам нужно будет запустить тестовый набор под несколькими базами данных)
8
@fennec - там нет модульных тестов для проверки базы данных, они там для тестирования кода, который зависит от значений базы данных для работы.
Теластин
3
Все хорошо, пока вы не протестируете код, который манипулирует базой данных. : P, для многих людей это большой код.
4
@fennec - немного сложнее, чем просто заглушить интерфейс, чтобы убедиться, что ваши записи пишут правильный объект. Это становится трудным только тогда, когда ваши классы пытаются отправить SQL напрямую через ваш интерфейс (читай: у вас ужасный дизайн).
Теластин
5
@Telastyn, возможно, я неправильно понимаю, но в конце концов некоторые классы должны выйти из строя и записать SQL или написать файл или отправить данные или интерфейс с GPU. Большинство абстракций имеют неизбежные утечки на некотором уровне; они просто прагматичны и не обязательно ужасны.
Очередь ученика
21

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

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

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

Добавление из комментария: Это больше проблема управления. Считается ли код «выполненным» до его документирования? Прежде чем это проверено? Прежде чем он включает и проходит модульные тесты?

Как вы к этому подходите, зависит от вашей роли. Вы сверстник? Если это так, покажите другим, как он облегчает повторное использование и поддержку вашего кода. Вы ведущий? Выберите своего программиста, у которого больше всего проблем с кодом, и помогите им добавить тесты, чтобы избежать этих проблем. Ты начальник? Установите в качестве стандарта, что «код не будет выполнен, пока не пройдут и не пройдут модульные тесты.

Скип Хаффман
источник
17
«Сними сладкие, низко висящие фрукты, и ты сможешь продать процесс». Я думаю, что они уже достигли этой стадии (они увидели потенциальные преимущества в использовании модульных тестов), и именно поэтому они были убеждены дать его попытка Проблема скорее в том, как масштабировать низко висящие фрукты для систематического проведения юнит-тестирования. Единственный проект, над которым я работал, в котором систематически использовались модульные тесты, содержал больше кода модульных тестов, чем фактический код продукта. Если команда не готова тратить больше времени на модульные тесты, чем на реальный код приложения, то IMO-подход, вероятно, не сработает.
Джорджио
4
Это больше проблема управления. Считается ли код «выполненным» до его документирования? Прежде чем это проверено? Прежде чем он включает и проходит модульные тесты? Как вы к этому подходите, зависит от вашей роли. Вы сверстник? Если это так, покажите другим, как он облегчает повторное использование и поддержку вашего кода. Вы ведущий? Выберите своего программиста, у которого больше всего проблем с кодом, и помогите им добавить тесты, чтобы избежать этих проблем. Ты начальник? Установите в качестве стандарта, что «код не будет выполнен, пока не пройдут и не пройдут модульные тесты.
Пропустить Хаффман
1
@SkipHuffman Ваш комментарий должен быть добавлен в качестве редактирования к текущему ответу.
Раду Флореску
15

Следуйте этим основным правилам. тесты:

  1. должен бегать регулярно! Вы можете запускать тесты при каждой сборке, до / после каждой регистрации или просто каждое утро. Автоматически сработавший является более предпочтительным, чем сработавший вручную. Потому что теоретически вы можете поручить всем членам команды обеспечить выполнение тестов, но если это не автоматизировано, это, вероятно, происходит не достаточно часто! И если вы не запускаете свои тесты достаточно часто, они оба обнаруживают ошибки слишком поздно, поощряя множество неудачных тестов, что приводит к пункту 2:

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

    а. не должно слишком долго бегать (субъективно) за ценность, которую они предоставляют! Сделайте свои тесты быстрыми. Не позволяйте людям проверять тесты, которые будут пустой тратой вашего времени, чтобы позволить им работать!

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

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

И, наконец, правило № 3. Тесты должны не только не давать отрицательное значение, как в правиле 2, они должны давать положительное значение. Тесты ...

  1. Должно быть, на самом деле говорит вам кое-что, о чем вы заботитесь, когда они терпят неудачу! (Нет тестов с непонятными сообщениями об ошибках или просто с нелепыми жалобами типа «вы забыли запустить тест на компьютере с Windows 2008», пожалуйста!).

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

Вывод: эти основные правила указывают на общее направление дисциплины устойчивого тестирования, которой вы отчаянно жаждете. При тестировании спросите себя, является ли этот тест действительно устойчивым и ремонтопригодным. Помните:

  • если тесты не являются устойчивыми, они выходят из употребления и тем самым становятся напрасными усилиями
  • если тесты не являются устойчивыми, вы прекращаете делать тесты, и ваша команда перестает становиться лучше в тестировании! И, последний момент:

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

Тим Ловелл-Смит
источник
12

1. Это действительно работает?

Да, это так - если все сделано правильно. Дело в том, что тестировщики должны настраивать и расширять свои автоматизированные сценарии после того, как инженеры внедрили новые функции.

2. Никто на самом деле не имеет опыта и не знает, как правильно проводить автоматизированное тестирование.

Получить консультанта (тот, кто знает, как это делается правильно). Или потратьте больше времени. Альтернатива состоит в том, чтобы иметь большую команду по тестированию, которая выполняет такое же тестирование вручную (что подвержено ошибкам).

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

Я бы не назвал их «опытными разработчиками», если они откажутся проводить юнит-тесты. Есть много замечательных статей о положительных преимуществах тестирования (как модульного, так и интеграционного тестирования), и в конце все сводится к тому, сколько ошибок стоит ваша компания . Например, я работаю в компании, где качество имеет значение, поэтому модульные и интеграционные тесты неизбежны. Вы можете легко найти множество статей, в которых говорится, что только модульные тесты уменьшают количество ошибок на 30%! (На самом деле, он находится в диапазоне 20-90%, в среднем 30%, но это все еще много.)

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

BЈовић
источник
20
Я должен отметить, что практически ВСЕ работает "Если все сделано правильно". Однако это не очень полезно для всех, кроме очень маленького меньшинства среди населения. Чтобы процесс действительно мог претендовать на то, что он работает, он также должен работать, когда завершен «в некотором роде».
Данк
11
Я укажу, что чрезмерное обобщение ситуации каждого на свое усмотрение (то есть я бы не назвал их «опытными разработчиками» ... качество имеет значение) не только демонстрирует недостаток опыта, но и не очень продуктивно. Каждая отрасль имеет свое собственное определение «работ»; и какую степень тестирования необходимо выполнить на уровне подразделений, интеграции и системы. Многие «исключительно хорошие» разработчики пришли к выводу, что модульные тесты дают небольшую выгоду по сравнению с автоматизированным интеграционным тестированием. Они также понимают, что это, вероятно, относится только к их конкретной отрасли.
Данк
11
«Я бы не назвал их« опытными разработчиками », если они откажутся проводить модульные тесты». Это просто ошибка Нет Правдивого Шотландца. Индустрия программного обеспечения десятилетиями обходилась без модульного тестирования, и большая часть этой индустрии продолжает обходиться без него и сегодня. Это может быть хорошей идеей, но это просто не обязательно.
Ной Йеттер
1
«не тратить время на юнит-тесты»: я бы перефразировал это как «не трать время на бесполезные юнит-тесты». Слепое модульное тестирование всего может привести к огромной трате времени.
Джорджио
1
@ Я действительно ненавижу весь феномен TDD, основанный на первом тесте, но я не могу согласиться с вашим первым утверждением. Вы либо делаете что-то правильно, либо нет. Вы можете хорошо выполнить один модульный тест и, возможно, увидеть его достоинства, но вы никогда не увидите достоинств какого-либо одного дела, сделанного наполовину.
Эрик Реппен
10

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

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

Модульные тесты - это хорошие тесты для автоматизации. Все вышеперечисленное (интеграционные тесты, тесты компонентов, системные тесты) также может быть протестировано автоматически, но соотношение затрат и выгод быстро снижается при одновременном тестировании большего количества функциональных возможностей. Этот негативный эффект усиливается, если вы строите такие тесты на плохо протестированном модуле функционале. Совет: вводите автоматизированные тесты на уровне модульных тестов и создавайте автоматизированные интеграционные тесты на прочной основе модульных тестов .

От вышеприведенных пунктов большая часть успеха автоматизированного тестирования зависит от того, насколько эффективны юнит-тесты. У вас есть эффективные юнит-тесты, если вы чувствуете себя продуктивно с юнит-тестами. Когда люди начинают с модульного тестирования, они склонны преобразовывать свой существующий код и привычки кодирования в модульные тесты. По иронии судьбы это самый сложный способ научиться юнит-тестированию. Также модульное тестирование требует, чтобы вы изменили способ кодирования (например, применяя принципы SOLID ). Большинство программистов вскоре прекращают написание модульных тестов, потому что они думают, что кривая обучения слишком крута, и считают неудобным заключать модульные тесты в не так проверяемый код. Совет: Изучите модульное тестирование с нуля с новым кодом и учтите тот факт, что вам нужно изменить свои привычки кодирования.

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

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

Тео Ленндорф
источник
Introduce automated tests on the unit test level and build automated integration tests on a solid foundation of unit tests.+1
c69
10

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

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

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

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

Marco
источник
8

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

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

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

То, что я бы назвал «промежуточным ПО», идеально подходит для модульного тестирования. Код с четко определенными условиями ввода и вывода. Если вы следуете принципу СУХОЙ (не повторяйте себя), вы напишете несколько небольших классов или функций для решения повторяющихся проблем, уникальных для вашего приложения.

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

Рон Хейфитц сказал бы: «Разрешать конфликты в ценностях, которые придерживаются люди, или уменьшать разрыв между ценностями, за которые люди выступают, и реальностью, с которой они сталкиваются. Адаптивная работа требует изменения ценностей, убеждений или поведения». После того, как вы преодолеете сопротивление человека изменениям, вы можете перейти к более сложным областям тестирования по мере необходимости.

GlenPeterson
источник
6
«Преодолеть сопротивление разработчиков к изменениям»: не каждое сопротивление без причины, и не следует избегать честного обсуждения, используя аргумент «сопротивление изменениям».
Джорджио
7

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

Такие вещи, как синглтоны, статические методы, реестры, локаторы сервисов и т. Д., Вводят зависимости, которые очень трудно смоделировать. Нарушения закона Деметры означают, что слишком много частей вашей кодовой базы слишком много знают о том, как функционируют другие части вашей кодовой базы, создавая дополнительные скрытые зависимости, которые может быть трудно сломать. Все это затрудняет изоляцию модуля от остальной части кода, и если вы не можете тестировать свои модули изолированно, то модульные тесты теряют большую часть своей ценности. Если тест не пройден, это из-за ошибки в тестируемом модуле, или из-за ошибки в одной из его зависимостей, или, возможно, это из-за того, что данные, которые извлекаются через зависимый источник данных, не соответствуют ожиданиям автора теста ? Если вы можете'

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

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

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

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

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

TL: DR: Большинство людей думают, что тестирование легко, и вы можете легко переоборудовать тесты в существующий код. Оба эти предположения неверны. Если вы приступаете к проекту, чтобы провести модульное тестирование в своих проектах с учетом обоих этих фактов, у вас больше шансов на успех.

GordonM
источник
подсказка: поместите TL; DR: вверху - мне нужно было прочитать все ваши посты только для того, чтобы добраться до них! (что-то вроде
победы над идеей
4
  • Есть ли в вашей компании кто-нибудь с большим опытом автоматизированного тестирования?

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

  • Есть ли у кого-то власть лидера? Могут ли они требовать перемен?

Если никто не слушает, это не имеет значения, если они говорят, что тест не годится. (Обратите внимание, что власть лидера не должна быть формализована. Наличие команды, которая заботится, тоже хорошо.)

  • Вы разрабатываете инструменты и процессы, чтобы упростить внедрение и интеграцию автоматизированного тестирования в цикл разработки?

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

Вы также должны убедиться, что у ваших IDE есть хороший способ запустить набор тестов. Вам следует часто запускать тестовый набор, чтобы люди замечали, когда он терпел неудачу, а не позволяли ему оставаться в нищете. Разработчики также хорошо реагируют на отзывы, например, автоматизированная система интеграции, которая отменяет свои изменения, если они не прошли тест. Или, что еще лучше, положительные отзывы: автоматизированная система интеграции, которая улавливает ошибки и избавляет вас от поломок.


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

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

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

Вы хотите избежать этого.

С тех пор я использовал другой подход к тестам. Вместо пары реализации интерфейса у меня есть интерфейс, реализация, тестовая тройка . Интерфейс определяет поведение, реализация выполняет поведение, тест проверяет поведение.

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

В этом случае я хотел бы спросить разработчиков, видят ли они естественное разделение в коде, где такой тест был бы уместен. Есть ли интерфейс, который реализует команда A и использует команда B? В этом случае в интересах группы B обеспечить, чтобы интерфейс вел себя так, как он ожидал. Попросите команду B написать тест для нее, затем скажите команде A, чтобы убедиться, что их реализация соответствует тесту; или, если нет, и намеренно не обсуждает неожиданные изменения с другой командой, чтобы они могли подготовиться к ней.

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

нарисовался
источник
1
Мне нравится код, который я могу читать лучше, чем код, который кто-то посчитал нужным протестировать вплоть до таких мелочей.
Эрик Реппен
1
Я чувствую, что милые зеленые галочки - это тестирование в какую-то игру.
gbjbaanb
2

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

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

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

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

мозг
источник
2

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

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

the_mandrill
источник
1

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

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

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

Но есть исключение

Я твердо верю, что принятие модели автоматического теста является функцией "человечности" проводимых тестов. Если вы тестируете веб-модуль с внешним интерфейсом, вы, несмотря на такие инструменты, как Selenium, с большей вероятностью сможете заполнить форму самостоятельно, увидеть результат и поверить в детерминизм. Вы забудете перезапускать тесты позже, или вам просто будет лень повторять старые тесты, и именно поэтому ошибки иногда обнаруживаются позже. Чтобы использовать это, сильная модульность кода и строгие правила «модификации старого кода» оказались приемлемыми в банковской среде (по моему личному опыту работы).

Вместо этого, если разработчик отвечает за разработку высокоавтоматизированного модуля с большими объемами данных, он с большей вероятностью напишет подробные модульные тесты и отправит их на тестовые пакеты. Это связано с тем, что заполнение большой полезной нагрузки XML данными, преобразованными из внешнего источника данных (поддельные или нет), не является делом человека. Некоторые разработчики тестов в конечном итоге создадут крошечный и забавный интерфейс для этого конкретного вида тестов. Когда я работал над магистерской диссертацией, я работал на шине протоколирования, которая обрабатывала более 6000 сообщений системного журнала в секунду, и мне приходилось измерять потерю пакетов и их повреждение: естественно, я написал модульные и стресс-тесты почти для всех компонентов, особенно парсера системного журнала.

Чтобы сделать разработчиков более склонными к юнит-тестированию

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

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

USR-местный ΕΨΗΕΛΩΝ
источник
1

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

Как только они получают обязанности по автоматическому тестированию, это включает в себя некоторое количество разработки программного обеспечения. Суть в том, что автоматическое тестирование, независимо от того, какие инструменты вы используете (и ради всего святого, не спорьте об этом), требует ежедневного обслуживания и обновления. Как разработчики меняют код,

  • Вы должны убедиться, что тесты продолжаются.
  • Вы должны убедиться, что тесты не удалены, так как они не запускались
  • ваши тестовые показатели должны показывать, что вы выполняли в последней сборке и в этой сборке. Чтобы убедиться, что количество тестов не уменьшается.
  • Тестовые случаи должны быть рассмотрены так же, как и разработка, чтобы убедиться, что люди не напутают, вроде разбить 1 тест на 2, просто чтобы увеличить цифры (иногда тестирование выполняется на стороне, поэтому это отслеживание важно)
  • важно гораздо больше «здорового» общения между разработчиком и тестом
  • держите non-functionalтесты отдельно и не ожидайте, что они будут выполняться ежедневно, требуется время, чтобы сохранить эти обновления, и это хорошо. Но не сдавайтесь, убедитесь, что они поддерживаются.

Вы терпите неудачу по этим причинам

  • Ваши инженеры-тестировщики - это инженеры-тестировщики, не имеющие аналитических навыков. они не знают разницы между а ifи whileпетлей. Потому что, откровенно говоря, ни один курс не учит автоматическому тестированию, а только ручной тест.
  • ваши инженеры по тестированию слишком заняты ручным тестированием ваших сборок и регистрацией ошибок, поэтому они не отслеживают автоматизированные тесты
  • ваши менеджеры по тестированию не заботятся о показателях из автоматических тестов, просто потому, что они показывают недопустимые данные (когда проект запускается), и они не придают усилий или приоритетов в ежедневных сессиях и встречах, чтобы подчеркнуть, насколько важно запустить автоматизацию
  • Вы выбираете автоматизировать тесты для мобильных приложений, которые имеют очень короткий срок годности. к тому времени, когда вы пишете, стабилизируйте набор автоматизированных тестов, требования к вашему приложению изменятся, вместо этого вам следует сосредоточиться на тестировании веб-сервисов, на которых выполняется ваше приложение.
  • вы не понимаете, что группа автоматизированного тестирования следует одной и той же вехе: команда разработчиков, функция завершена, код завершен, блокировка кода и заморозка кода.
  • Вы не различаете людей, проводящих ручное тестирование, и людей, проводящих автоматическое тестирование.
  • им обоим выплачивают одинаковую зарплату и они подчиняются одному и тому же менеджеру, в идеале они должны отчитываться перед менеджером разработки, а их зарплаты должны соответствовать зарплатам разработчиков.
  • Вы действительно думаете и считаете, что junit недостаточно для разработки автоматических тестов :).

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

Сиддхарт
источник
В случае модульного и интеграционного тестирования люди, которые должны писать тесты, являются разработчиками, а не отдельными «инженерами-тестировщиками». (Как написано в вопросе, QA, то есть инженеры-тестировщики, фактически уже используют автоматизированные тесты пользовательского интерфейса.)
Pa --lo Ebermann
На самом деле, любой, кто пишет автоматизированные тесты, должен иметь навыки разработки.
Сиддхарт