Несмотря на то, что технологии модульного тестирования существуют уже 30 лет (в 1989 году Кент Бек написал статью “Simple Smalltalk Testing: With Patterns”), тем не менее не все программисты владеют этой технологией и не все компании сделали автоматическое тестирование частью своей корпоративной культуры. Даже несмотря на очевидные преимущества автоматического тестирования, все равно поведенческое сопротивление достаточно сильное. Кто пробовал внедрять автоматические тесты, тот знает, что всегда найдется какая-то причина, почему это не удалось сделать.


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


Все возражения я сгруппировал в пирамиду надежного программирования, которая включает четыре уровня:


  • Профессиональная культура (самый высокий уровень, основа надежного программирования) — совокупность норм, неписаных правил, убеждений сотрудника, которыми он руководствуется в работе. Например: “Отправить в репозиторий код непокрытый тестами — плохо”, “Замолчать о найденных ошибках в коде — стыдно”.
  • Менеджмент — это процедуры, политики, правила, принятые в организации, а также воля (решения) руководителей. Например: “Каждая разработанная функция приложения должна пройти код ревью. Без исключений!”.
  • Методы — это научные подходы, способы решения той или иной задачи. Например: “Если функцию приложения сложно протестировать, нужно повысить тестопригодность приложения, применив шаблон Dependency Injection”.
  • Технологии (самый низкий уровень) — это языки программирования, библиотеки, фреймворки, инструменты. Например, JUnit, Selenium, XCTest и так далее.


Зачем нужно такое деление? Потому что проблема одного уровня решается методами этого же уровня или методами более высокого уровня. Например, если в организации не принято писать автоматические тесты (проблема профессиональной культуры), то эту проблему невозможно решить подробно описав бизнес-процесс тестирования (уровень “менеджмент”) или установив современный фреймворк (уровень “технологии”). Даю гарантию, что через неделю никто писать тесты не будет, невзирая на утвержденный бизнес-процесс.


Возражения культурного уровня


“Мои программы не ломаются. Я не вижу нужды в тестировании”.


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


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


На одном из собеседований, которое я проводил, произошел такой диалог:


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


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


Нежелание брать ответственность за качество кода, за тестирование.


Автоматические тесты — единственный источник оперативной и объективной информации об истинном качестве программного продукта. Иными словами за спиной у программиста всегда стоит надсмотрщик, который в любой момент времени может доложить руководству о том, насколько качественно программист выполняет свою работу. Автоматические тесты позволяют увязать результативность труда не с закрытыми тикетами в Джире, а с истинным качеством программного продукта. А здесь уже нужно думать о том, как писать надежно, чтобы каждое очередное изменение кода не ломало существующие функции. Чтобы каждая новая функция работала не только в сценарии, когда все хорошо, но и корректно обрабатывает ошибки.


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


"Пишите сразу правильно без ошибок"


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


— Давайте покроем приложение автоматическими тестами.
— Зачем?
— Чтобы убедиться, что все работает корректно и нет ошибок.
— Вы пишите с ошибками? У вас низкая квалификация? Пишите сразу правильно без ошибок.
— Да, но все допускают ошибки…
— А вот друга компания XYZ сказала, что у них топ-программисты, которые пишут без ошибок!


Таким образом, разработку тестов сложно “продать” заказчикам, которые не подкованы технически. В результате, менеджмент вынужден разрабатывать проект без автоматических тестов, что приходит к известным проблемам.


Возражения на уровне менеджмента


“C тестами программу писать в два раза дольше. Мы не уложимся в сроки”.


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


У автоматических тестов есть несколько функций:


  1. Проверяющая.
    1.1. Тесты проверяют, корректно ли работает объект тестирования.
    1.2. Тесты проверяют качество работы программиста: решена ли поставленная задача, нет ли побочных эффектов в виде регрессий.
  2. Диагностирующая. Диагностические тесты позволяют существенно сократить время на поиск дефекта. Тесты позволяют определить место ошибки с точностью до класса и метода, а иногда и с точностью до строчки кода.
  3. Автоматизирующая. Тесты позволяют быстро и легко вводить объект тестирования в нужное состояние для отладки.
  4. Документирующая.
    4.1. Приемочные тесты фиксируют требования заказчика к разрабатываемому продукту.
    4.2. Тесты показывают примеры использования разрабатываемого компонента, тем самым сокращая время на изучение работы системы другим программистом.

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


— Но ведь тесты писать долго! Мы не уложимся в сроки!
— У вас есть ошибки, которые вы очень долго искали и исправляли?
— Да, есть такие.
— Какой самый сложный случай?
— Одну ошибку мы искали 80 часов.
— 80 часов — это две недели работы программиста. Если бы вы потратили даже целую неделю на автоматизацию тестированию, то это сэкономило бы вам месяцы на диагностировании и отладке вашего приложения!


В нашей организации есть постулат: “С тестами писать программу в два раза быстрее!” и этот постулат не обсуждается. Обсуждается только коэффициент 2 — иногда бывает и 3, и 4. А некоторые проекты просто невозможно завершить без грамотного автоматического тестирования (см. заваленный проект).


“У нас уже есть отдел ручного тестирования, пусть они и тестируют”.


С первого взгляда разделение специализаций на тестирование и программирование кажется логичным.


Но давайте рассмотрим недостатки ручного тестирования:


  • Стоит очень дорого.
  • Выполняется очень долго. Например: тестовые сценарии для мобильного приложения “Онлайн кинотеатр” тестер делает 40 часов. И это только для одной платформы! Если нужно протестировать приложение на iPhone, iPad, Apple TV, Android, Fire TV, то нужно потратить 40 ? 6 = 240 часов рабочего времени, это полтора месяца, что неприемлемо для коротких циклов разработки.
  • Ручное тестирование подвержено обычным человеческим ошибкам — не дает объективного и истинного результата.

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


  1. Функция импорта CSV-файлов.
  2. Парсеры текстовых документов.
  3. Финансовые инструменты.

Возражения на уровне методов


Незнание методов автоматического тестирования.


Из-за кризиса образования в вузах нигде нет дисциплин автоматического тестирования. Таких же курсов очень мало в коммерческих айти-школах. А существующие курсы — поверхностные и низкого качества. Поэтому, я часто встречал ступор у программистов: они не знают, как протестировать нетривиальные приложения (сложнее, чем 2 + 2 = 4).


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


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


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


Особенность некоторых проектов в том, что они разрабатываются по технологии Minimum Viable Product, который иными словами можно охарактеризовать так: “Давайте сделаем хоть что-то за минимальное время и минимальный бюджет”, а программист рассматривается заказчиком или менеджментом как аналитик, дизайнер, архитектор, программист и тестировщик в одном флаконе. При таком подходе исключается формальный этап проектирования программной системы: определение бизнес-логики, предметной области, интерфейсов компонентов, а также их внутренней организации их отношений между ними. Нет формализованной архитектуры, нет интерфейсов, нет прописанных бизнес-процессов — непонятно, что тестировать, через какие интерфейсы и какой ожидаемый результат.


Нетестопригодный код.


Тестопригодность — свойство проекта, которое говорит: насколько легко его можно протестировать. Тестопригодность определяется двумя другими свойствами: управляемостью и наблюдаемостью. Управляемость — свойство, которое определяет насколько легко можно ввести приложение в нужное состояние для тестирования (выполнить предусловия). Наблюдаемость — как легко можно считать состояние после проведения теста, сравнить его с ожидаемым.


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


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


Подготовка тестовых данных.


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


Решение:


  • разработка эталонных значений и примеров на этапе разработки приемочных тестов — они также помогут решить конфликты с заказчиком на этапе приема работ;
  • разработка эталонных значений на этапе проектирования системы. Например, эталонные HTTP запросы и ответы — помогут легче интегрировать клиент и сервер;
  • разработка специальных процедур сборки баз данных, при которых требуемое состояние базы данных создается автоматически, а не вручную
  • использование шаблона Object Mother [Fowler, Schuh, Peter, and Stephanie Punke. "Easing Test Object Creation in XP." XP Universe. 2003], который помогает легко аллоцировать и инициализировать объекты в требуемом состоянии.

Обслуживание тестов.


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


Решение:


  • использование шаблона “адаптер” для того, чтобы отвязать логику теста от того интерфейса, который он тестирует;
  • использование высокоуровневых тестов (Gherkin, Cucumber, Given-When-Then);
  • см. решение к сопротивлению “подготовка тестовых данных”.

Заключение


Нет сомнений, что программное обеспечение должно быть надежным: превосходить ожидания потребителей. Автоматические тесты — хоть и не единственный, но важный компонент при разработке надежного программного обеспечения.


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


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


  1. Формирование и пропаганда новой культуры ИТ-проектирования, которая заключается в надежности, гордости и персональной ответственности за результат.
  2. Разработка новых высоких стандартов тестирования кода.
  3. Разработка и внедрение учебных курсов.
  4. Введение мотивации в карьеру программистов и менеджеров, увязанной с качеством разрабатываемых программных продуктов, а также с навыками автоматического тестирования.

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


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

Комментарии (89)


  1. obrizan Автор
    28.07.2018 11:19

    Для любителей посмотреть и послушать: некоторые из этих сопротивлений были озвучены на IT-Weekend Kharkiv: Software Testing: youtu.be/AoPmghGFFD4


  1. denis-19
    28.07.2018 12:03

    А еще можете привести примеры нетестопригодных систем?
    Существуют вариации переработки таких систем в тестопригодные?


    1. obrizan Автор
      28.07.2018 12:16

      Можно рассмотреть мобильное приложение «Сканнер штриховых кодов для мероприятий». В ней есть несколько основных сценариев:

      1. Пропустить пользователя с валидным билетом.
      2. Показать предупреждение, если билет поддельный (не найден код в базе данных).
      3. Показать предупреждение, если билет уже использован (например, дал другу, он распечатал такой же куар-код).

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

      Но автоматически это сделать сложно.

      Решение:
      1. Изоляция компонента, который сканирует куар-код и подстановка тестового двойника.
      2. Моканье (mock) метода SDK, который возвращает считанный код.

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


    1. obrizan Автор
      28.07.2018 12:37

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


      1. igor_suhorukov
        30.07.2018 22:55

        Из более формальных критериев — завязаны ли конструирование и внедрение объектов на DI, как часто используются моки статичных методов, эмуляцию системных классов (в java передача параметров через System.getProperty(...) и других вызовов методов с побочными эффектами.


    1. VolCh
      28.07.2018 14:03

      В целом этот большие сложные системы, в которых:
      а) сложный граф зависимостей её частей, вследствие чего практически невозможно инициализировать конкретную часть без инициализации всей системы
      б) различные виды IO не вынесены в изолированный слой. Сюда же работа с текущими датами/временами и случайными числами
      в) активная работа в коде с глобальными состояниями, включая глобальные переменные, и, как их разновидность, статические переменные классов, в том числе в синглтонах
      г) неактуальная или вообще отсутствующая документация по архитектуре, конфигурированию и развёртыванию системы, в лучшем случае тестовые окружения периодически синхронизируются с продакшеном с "вырезанием" потенциально чувствительных или просто объёмных данных, притом, как говорится, на глазок, без чёткого понимания может ли, например, система в принципе работать, если, скажем, в базе данных ни одного пользователя нет.
      д) много захардкоженных значений типа имен и портов внешних сервисов


      Способов переработки много, в целом они заключаются в уменьшении связанности отдельных частей системы друг с другом и средой исполнения без изменения функциональности, то есть один из видов рефакторинга. Основная проблема (если вопрос с руководством о повышении тестопригодности уже решён) — обычно нетестопригодные системы почему-то тестами не покрыты или покрыты очень слабо, а значит приводя систему в тестопригодное состояние мы вносим изменения корректность которых автоматически проверить не можем, только путём полного ручного регрессивного тестирования, что обычно очень дорого. Хорошо если рефакторинг ограничивается автоматизированными средствами рефакторинга, например из инструментов IDE, но часто нет.


      1. obrizan Автор
        28.07.2018 14:17

        «нетестопригодные системы почему-то тестами не покрыты»

        В проблеме сразу и отгадка: не покрыты, потому что нетестопригодны. :)

        Из нашего опыта для нетестопригодных систем:
        1. Расставляем функции по приоритету в соответствии с ценностью для клиента/пользователя.
        2. Пишем высокоуровневые (UI или API) тесты.

        Тем самым снижаем вероятность внесения случайных регрессий.

        Хоть какие-то тесты лучше полного отсутствия.


        1. VolCh
          28.07.2018 16:03

          В проблеме сразу и отгадка: не покрыты, потому что нетестопригодны. :)

          Надо было кавычки поставить вокруг "почему-то" :)


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


        1. Antervis
          28.07.2018 21:47

          2. Пишем высокоуровневые (UI или API) тесты.

          там может быть намного сложнее с наблюдаемостью…


    1. dimm_ddr
      28.07.2018 15:06

      А еще можете привести примеры нетестопригодных систем?

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


      1. obrizan Автор
        28.07.2018 15:34

        Совершенно верно, не бинарное. В идеале, нужно разработать формулу, которая оценит систему, компонент или функцию в интервале от 0 до 1, где 1 — идеальная тестопригодность, 0 — полная нетестопригодность.

        Например, идеальная тестопригодность у функции:

        def sum(a, b):
             return a + b
        


        Потому что совершенно не нужно прикладывать никаких усилий, чтобы ее протестировать. :)


        1. oxidmod
          28.07.2018 16:16

          Не так то просто
          habr.com/post/416819/#comment_18914575


          1. dimm_ddr
            28.07.2018 20:14

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


  1. dipsy
    28.07.2018 12:19
    +1

    Очень сложно внедрить автоматические тесты, если программист не обучен методам тестопригодного проектирования или если менеджмент не поддерживает культуру надежного программирования в организации.
    С точки зрения кого нужно их внедрять? Вы здесь в какой роли, консультант, рядовой программист, менеджер смежного подразделения?
    То что тесты нужны, мне например очевидно, статью с интересом прочитал, всё доходчиво, всё по делу. Условный Василий, мой коллега за соседним столом, тоже статью прочитает, если я ему скину ссылку, но сделает для себя прямо противоположные выводы, он-то пишет быстро и четко, рефакторинг не практикует, тесты/отладка вручную 1 раз при написании, затем код лежит и не меняется практически, зачем тратить в 2-3 раза больше времени, у него свой путь. Нет, через год-два-пять, по мере разрастания проекта или работы с горами чужого легаси он конечно поймет, что тесты нужны, рефакторинг важен, и т.п. Но он поймет это сам, отбив себе всё самолюбие собственноручно расставленными в прошлом граблями. Наверное только так, через боль и унижения, это всё усваивается, а не по указке сверху.


    1. obrizan Автор
      28.07.2018 12:31

      Из моей практики «драйвером» изменения культуры программирования выступали разные роли.

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

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

      Мне такие «Василии» знакомы. Для таких Василиев шанс для изменения, увы, только один — это глубокий кризис. Такие кризисы рано или поздно переживают все программисты: это и бессонные ночи на работе, и увольнения, и штрафы, и судебные иски. Те моменты, когда человек уверенно говорит: «Никогда в жизни больше я не буду писать без автоматических тестов!»

      Мы с единомышленниками видим такую стратегию изменения культуры программирования:

      1. Сформировать новый источник этических профессиональных норм. Иными словами, сформулировать, что хорошо, что плохо. «Тесты, рефакторинг — хорошо», «Редактировать исходники прям на сервере — плохо».

      2. Подготовить материалы (статьи, курсы, видео) в поддержку п. 1. Чтобы нельзя было сказать, что мы голословны и кидаемся громкими лозунгами.

      3. Пропаганда этой новой культуры надежного программирования.

      Программист «Василий» должен сам добровольно выбрать, на какой он стороне: с тестами, рефакторингами и счастьем? Или без тестов, с авралами и без работы? :)


  1. obrizan Автор
    28.07.2018 12:30

    Не туда ответил


  1. VolCh
    28.07.2018 13:42

    Самое странное с чем встречался лично: компанией формально признаётся необходимость писать тесты, это вроде как даже обязанность всех разработчиков, технологии в проект внедрены, но в целом покрытие порядка 30% (это без учёта легаси) и уменьшается, тесты и тестовые окружения не поддерживаются, при ревью или мерже не тесты запускаются, когда запускаешь полный прогон самостоятельно раз в неделю-две — десятки сломанных тестов выплывают, часть разработчиков тесты пишут из под палки или для галочки, часть пишет много тестов, но бОльшая часть из них это тестирование геттеров/сеттеров на ошибки, которые можно выявлять статанализом, а непосредственное руководство считает, судя по всему, наличие тестов опциональной документацией к уже выполненной задаче, типа если срочных задач нет (что редко бывает), то можешь и тесты пописать.


    1. obrizan Автор
      28.07.2018 13:54

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

      «если срочных задач нет» — 99% срочных задач можно было бы избежать, если бы заранее было сделано надежно: проработаны требования, архитектура, сделан код ревью, написаны тесты. ;)


    1. dimm_ddr
      28.07.2018 15:11

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


      1. obrizan Автор
        28.07.2018 15:31

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


        1. VolCh
          28.07.2018 17:25

          Не согласен. По пунктам:


          • профессионал не должен доказывать ничего руководству или заказчику на этапе сдачи работы, если это не предусмотрено законом, договором или заданием. Есть конкретные претензии? Назовите, обсудим это невыполненные требования или новые. Нет? Оплатите. Писать тесты в оплачиваемое время без ведома заказчика и руководства — в лучшем случае неэтично.
          • это возможно и без автоматических тестов, ручным тестированием по тем же кейсам как минимум. Даже юнит тесты можно вручную делать, особенно если язык интерпретируемый или имеет "псевдоинтерпретатор" в наборе инструментов.


          1. obrizan Автор
            28.07.2018 18:26

            «Есть конкретные претензии? Назовите, обсудим это невыполненные требования или новые.»

            Вот тут-то и самое интересное! Профессионал прислал работу, сказал: «Я все сделал», руководитель полез перепроверить, а там на 2 из 10 юз-кейсов приложение просто крешится. Говорить «я все сделал», когда на самом деле «я что-то там написал, но не проверял» — это непрофессионально и ненадежно.

            «это возможно и без автоматических тестов, ручным тестированием»

            Повторюсь, 500 тест-кейсов для мобильного приложения «Онлайн-кинотеатр» тестировщик проверяет за 40 рабочих часов для одной версии iOS, а поддерживаем мы их три. Автоматический тест смог бы проверить правильность за несколько часов.

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


            1. VolCh
              28.07.2018 20:41

              А если полез проверять и все 10 кейсов проходят? При том нет следов того, что профессионал как-то проверял.

              Ну, то есть всё же не невозможно, а вполне конкретных и реальных 40 часов занимает. Если релизы раз в месяц, то одного тестировщика хватит с запасом. Можно обсуждать что выгоднее в тех или иных аспектах. Покрыть такое приложение автотестами на всех уровнях скорее всего займёт довольно много времени минимум трёх человек: разработчика, тестировщика и девопса. При том необходимость в тестировщике не исчезнет вообще после покрытия. И время всех троих надо будет тратить и на поддержку, и на развитие. Может оказаться выгодно, может нет.

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


              1. obrizan Автор
                28.07.2018 20:45

                Предположим, что релиз раз в месяц. Программист три недели писал код, затем тестировщик неделю тестировал, и в пятницу в 15:00, сообщил о 3 критических ошибках, 10 major и 20 minor. Общий эстимейт на исправление — 40 часов. А релиз версии был обещан в понедельник.

                Ваши действия? :)


                1. VolCh
                  28.07.2018 20:54

                  Откат фич/фиксов, вызвавших мажорные ошибки, смок тест и релиз без них, если смок-тест не прошёл, то откладывание релиза до прохождения :)

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


          1. dimm_ddr
            28.07.2018 20:17

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


            1. obrizan Автор
              28.07.2018 20:35

              Есть приемочные тесты, которые по сути — условия приема-передачи работ, факт оказания услуги.


              1. VolCh
                28.07.2018 20:48

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


  1. aamonster
    28.07.2018 14:39

    Отвратительная статья. "Вы все дураки и не лечитесь, только я знаю, что вам надо". И автор думает, что с таким настроем ему удастся кого-то убедить в необходимости автоматизированного тестирования? (а оно таки зачастую очень нужно, но такие вот, с позволения сказать, "евангелисты" только отбивают людям охоту его внедрять… Нужен ведь не такой "энтузазист", а специалист, который поможет внедрить малой кровью)


    1. obrizan Автор
      28.07.2018 15:27

      Вы плохо обо мне думаете, такого в статье я не писал!

      «Нужен ведь не такой „энтузазист“, а специалист, который поможет внедрить малой кровью»

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

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

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

      К сожалению, объем статьи не позволяет сразу и решение расписать. Это темы для будущих статей.

      Если у вас уже есть решения — прошу, напишите!


      1. aamonster
        28.07.2018 17:10

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


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


    1. ta6aku
      31.07.2018 18:00

      Статья, я думаю, не мотивационная, а системная. Не для тех кто не может решиться, а для тех кто решился, но никак не может понять на что.


  1. oq0po
    28.07.2018 15:36

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


    1. VolCh
      28.07.2018 17:27

      Такие виды тестирования не автоматизируются. Максимум, А/Б тестирование со снятием целевых метрик типа конверсии.


      1. ta6aku
        31.07.2018 18:02

        Строго говоря, автоматизируются, и даже двумя способами. Для интеграционного тестирования GUI есть сторонние решения вроде Селениума, а для тестирования логики можно и модульное применять.


        1. VolCh
          31.07.2018 18:51

          Тестируется соотвествие нового дизайна макетам, но не степень офигивания пользователя от них :)


          1. ApeCoder
            31.07.2018 20:38

            Это уже A/B тестирование и фокусгруппы


    1. obrizan Автор
      28.07.2018 23:00

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

      Ну а так, да, например, Скайп меняет дизайн ежемесячно — я уже не то, что офигеваю, я просто не понимаю, куда нужно нажать, чтобы просто початиться с человеком. :)


  1. Antervis
    28.07.2018 22:33

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

    1. Нужно сделать Minimum Viable Product за заниженные в 2-3 раза сроки. Ну, вроде пока ничего страшного — жертвуются автоматическое тестирование и расширяемая архитектура, пишется миниальное решение и тестируется вручную, благо скудный набор фич позволяет. «А потом если что переделаем»
    2. Возникает набор дополнительных, «необходимых вчера» фич. Приоритет отдается им, проектирование архитектуры и тесты уходят на второй план.
    3. Проект потихоньку растет, из-за плохой архитектуры проект обрастает костылями и становится малонепригодным для тестирования, усложняется поддержка, рефакторинг напрашивается, но менеджмент по очевидным причинам не одобряет огромные трудозатраты на него.
    4. Проект развивается очень медленно, превознемогая регрессии и руководствуясь девизом «работает — не трогай».


    Что необходимо чтобы так не происходило? Да черт его знает


    1. obrizan Автор
      28.07.2018 22:58

      Поменять культуру, картину мира в голове. ;)


      1. Antervis
        30.07.2018 20:43

        В своей? — не вопрос. У всех? — едва ли.


        1. dimm_ddr
          30.07.2018 22:44
          +1

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


          1. VolCh
            31.07.2018 09:52

            Писать — может быть. Что коммитится в центральный репозиторий или его аналог — уже дело менеджера.


            1. dimm_ddr
              31.07.2018 14:06
              +1

              С какой стати? Дело менеджера — насколько продукт соответствует желаниям заказчика с одной стороны, и насколько много можно продать клиенту того что может сделать команда с другой. Процесс разработки включающий или не включающий тесты его никак и никогда не касается. Если менеджер считает что касается — значит он не компетентен. Это конечно мое мнение и мы можем аргументированно о нем поспорить, но на данный момент я не вижу ни одной причины менеджеру лезть в репозиторий, хоть центральный, хоть локальный.


              1. VolCh
                31.07.2018 18:53

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


  1. MaxEdZX
    29.07.2018 01:48
    +1

    Вот у меня как раз возражения всегда на тему «не понимаю, как тестировать что-то сложное» и «понятия не имею, как будет выглядеть система, пока её не напишу (и не перепишу два раза)». Возможно это специфика области, разработка игр — у нас никогда не бывает чётких требований, всё кардинально меняется на лету, и компоненты системы совершенно отказываются изолироваться друг от друга, протягивая щупальца порой в совершенно неожиданные места. То есть вот скажем автоматические тесты для парсера скриптов, или для хитрого контейнера, или там для библиотеки конечных автоматов — это ОК, это я понимаю, но как тестировать что-то более высокоуровневое — игровую механику, рендер или UI — это уже за пределами моего понимания.


    1. obrizan Автор
      29.07.2018 09:13

      Не специалист в нише рендеринга и разработки игр.

      Для рендера и UI могут подойти тесты, которые сравнивают результаты рендеринга (скриншоты) с эталонными с какой-то долей погрешности. Например, если кадр совпадает на 99% с эталонным, то все ок, если 95% — то все плохо.

      Кроме этого на рендеринг наверняка performance тесты есть.

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

      Здесь большое поле для творчества.


    1. Antervis
      29.07.2018 22:37

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


      1. MaxEdZX
        29.07.2018 22:51

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


        1. ApeCoder
          30.07.2018 21:19

          А на какие юниты это обычно делится?


          1. MaxEdZX
            30.07.2018 21:40

            А вот ни на какие обычно не делится. Для всего кода игровой механики, какой я видел, характерно было стремление к нескольким огромным классам, которые делали всё, что в эту механику было заложено, изредка делясь обязанностями с классами, у которых область действия была более очерченной (типа поиска пути). Мой личный более-менее удачный опыт был, когда я попробовал применить разбиение игровых объектов на компоненты a la Unity, но и он скатился, в конце концов, к тому, что взаимодействие _между_ компонентами — а это как раз самое интересное — было организованно в одном большом классе, называвшемся «логика уровня». В бОльших играх видел попытку организовать подсистемы («квестовая подсистема», «социальная подсистема»), но каждая из них в результате опять-таки оказывалась классом на 1000+ строк имплементации. То есть вот эта красивая картинка, где вся функциональность разбита на маленькие, легко тестируемые классы с небольшим количеством функций — она никак не получается. Но возможно я просто ни разу за 10+ лет не работал с хорошим архитектором (то что я сам плохой — я и так знаю).


            1. ApeCoder
              30.07.2018 22:24

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


              1. MaxEdZX
                30.07.2018 23:51
                +2

                Я думаю проблема в предметной области довольно большая. У игрового кода очень высокая связность между разными частями потому, что правила того требуют. Тут есть такая проблема, что игра не моделирует какую-то реальность (у которой есть логичные, и не очень изменчивые законы — даже у финансов), а фантазию дизайнера, поэтому у неё могут возникать самые неожиданные взаимодействия, причём внезапно. Вчера классу Персонаж ничего не надо было знать о классе Дерево, а завтра — они вдруг лучшие друзья с интимным доступом к кишкам друг друга. Потому что так веселее.

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

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


            1. dimm_ddr
              30.07.2018 22:47

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


              1. MaxEdZX
                31.07.2018 00:01

                github.com/MaxSavenkov/drdestructo2 — вот мой пет-прожект, можно посмотреть. Это правда довольно старый код, сейчас я наверное смог бы уже лучше, но как пример можно оценить. Самый сок находится в файле github.com/MaxSavenkov/drdestructo2/blob/master/src/GameStateLevel.cpp — скромных 2051 строк. Код местами комментирован.

                Общие идеи кода описаны тут: github.com/MaxSavenkov/drdestructo2/blob/master/docs/ReadMe_Source.txt, но в целом идея была в том, чтобы разбить код на Компоненты, которые почти ничего не делают, а только пассивно содержат данные, и Процессоры, которые обрабатывают Компоненты каждого типа в один проход (например, всю физику, потом всю графику, потом весь звук). А весь код, которые требует взаимодействия _между_ разными компонентами (в т.ч. копирование данных из компонента в компонент, т.к. они дублируют данные — иначе бы Процессорам пришлось принимать на вход более чем один тип компонентов), находится в GameStateLevel :)


                1. obrizan Автор
                  31.07.2018 08:37

                  Может написать тесты на самые лютые методы? Например:
                  GameStateLevel::ControlsToPhysics
                  GameStateLevel::PhysicsToGraphics
                  GameStateLevel::FireWeapon
                  GameStateLevel::ProcessSingleCollision
                  GameStateLevel::Update


                  Там очень много условий и ветвлений — навряд ли такое качественно тестируется вручную. Кроме этого: «It grown organically, so be prepared.» — будет расти, будет меняться, будут появляться регрессии. ;) Ну и в третьих, если эти алгоритмы рефакторить, то лучше это делать на тестах.

                  Ну а так вообще конечно нужен отзыв эксперта в написании игр. Как такой код отрефакторить к какой-то стандартной игровой архитектуре.


                1. dimm_ddr
                  31.07.2018 08:51

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


                  GameStateLevel::ExitGame
                  GameStateLevel::PauseGame

                  метод


                  GameStateLevel::Update

                  просто просится в кандидаты на разбиение на более мелкие и тоже в отдельный класс (скорее всего не в одиночестве конечно). Легко должно быть вынести что-то вроде


                  GameStateLevel::TutorialTimerUpdate
                  GameStateLevel::LevelTimerUpdate
                  GameStateLevel::ReapplyKeyboardSettings

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


    1. dimm_ddr
      30.07.2018 12:30

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


  1. SergejSh
    29.07.2018 22:03

    Культура программирования это конечно важно, но дело столько в культуре как таковой.
    Отсутствие автоматического тестирования свидетельство, что программистам ведущим по крайней мере НЕ ИНТЕРЕСНО ПРОГРАММИРОВАНИЕ. Они привыкли делать свою работу определенным образом. Книги и статьи о программировании перестали читать много лет назад. И они ни чего не хочет менять, они искренне уверены, что тесты просто пустая трата времени. Продумывайте интерфейс, не совершайте ошибок и все будет ок.
    Нормальному программисту как минимум должно быть интересно, что за тесты такие и действительно ли они помогают. А начальник программистов просто ОБЯЗАН изучать практики помогающие улучшить работу своих подчиненных и соответственно внедрять их.
    Рядовые же программисты просто серая масса которой однозначно пофигу все. Пока деньги платят.


    1. obrizan Автор
      29.07.2018 22:21

      «Не можешь — научим, не хочешь — заставим!»

      Нужно выстраивать систему мотивации, финансовой, карьерной, чтобы люди внедряли тесты. Например, не повышать до middle software engineer, пока программист не докажет на практике, что внедряет автоматические тесты.


      1. NeverIn
        30.07.2018 17:31

        >Например, не повышать до middle software engineer, пока программист не докажет на практике

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


        1. obrizan Автор
          30.07.2018 17:32

          «Повысьте вашу ценность и ценности потянутся к вам!» (Джим Рон)

          Если сотрудник приносит больше ценности компании, то и получать он будет пропорционально.


          1. dimm_ddr
            30.07.2018 19:53
            +1

            Если сотрудник приносит больше ценности компании, то и получать он будет пропорционально.

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


    1. VolCh
      30.07.2018 07:45

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

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


      1. SergejSh
        30.07.2018 08:40
        +1

        1) В том то и дело что не Не пробовали может кто то и сделал пару тестов из под палки чисто для галочки но большинство не пробовало.
        2) Я люблю писать тесты. Но есть ситуации когда я то же не пишу тесты потому что понимаю что овчинка не стоит выделки.Понимаю на основании опыта написания тестов.
        И наоборот есть ситуации когда ОТЛАДКА через тесты экономит время.
        Ну а когда с помощью теста кусочек кода отлажен, я просто пишу асерт начинаю отлаживать следующий кусочек кода в другом тесте.
        Таким образом я экономлю время а тесты остаются как полезный артефакт от разработки.


        1. VolCh
          30.07.2018 12:42

          1) Не пару тестов, а пару месяцев. Не из под палки, а из интереса. И не просто поробовали, а снимали метрики производительности, которіе показали, что скорость разработки уменьшается значительно, а количество проблем незначительно.


          1. SergejSh
            30.07.2018 13:04
            +1

            Если кто то проводил такие исследования то выложите их в открытый доступ пож


          1. SergejSh
            30.07.2018 13:13

            Далее результат может быть отрицательный потому что.
            1) Разработчики изначально учились что замедляет процесс.
            2) Разработчики пробовали писать тесты на то что не стоит тестировать. Простой код, или GUI (овчинка выделки не стоит).
            3) Результат может появится когда кому ни будь приведется переписать функционал А это далеко не 2 месяца.
            У меня тесты 5- 6 летней давности работают себе без проблем а стоит полезть в этот код, что то ломается ( не было бы тестов и не узнал бы что внес ошибку) и ее словили бы в продакшене возможно с воем и с претензиями денежными.


            1. VolCh
              31.07.2018 09:59

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


              1. SergejSh
                31.07.2018 10:17

                Ответ только один включить голову и почитать «умные» книжки и статьи.
                Как вариант предложить эксперимент
                Сделать серьезные изменения в сложном коде коде
                1) который был покрыт тестами.
                2) который не был.
                Делать должен тот кто этот код не писал.(или писал очень давно).
                Вероятность внести ошибку во втором случае заставит разбираться как все работает досконально ( или положиться на авось).
                В первом же случае проще разобраться в том что написано и есть ГАРАНТИЯ что я ни чего не сломал.


                1. dimm_ddr
                  31.07.2018 14:08
                  +1

                  Я на вашей стороне, но на всякий случай добавлю: гарантия не 100% и важно чтобы разработчик это понимал. Не понимание этого нюанса в перспективе может привести к серъезным ошибкам и разочарованию в тестах.


                  1. SergejSh
                    31.07.2018 14:25
                    +1

                    Если тесты написаны правильно и покрывают все возможные сценарии (А именно так и должно быть при подходе через ТDD), то вероятность внесения ошибки ничтожно мала.


                    1. tundrawolf_kiba
                      31.07.2018 16:49
                      +1

                      все возможные сценарии

                      Исчерпывающее тестирование невозможно кроме тривиальных случаев.


                      1. obrizan Автор
                        31.07.2018 16:55

                        Для начала можно ограничиться сценариями из требований. Их обычно не очень много.


                        1. tundrawolf_kiba
                          31.07.2018 17:25
                          +1

                          Ну на самом деле можно даже несколько больше, чем только сценариями. Это просто был комментарий к тому — что действительно все сценарии учесть невозможно.


                1. VolCh
                  31.07.2018 18:56

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


              1. ApeCoder
                31.07.2018 10:26

                Можно попробовать поставить задачу по другому — есть ли какие-то варианты, когда тесты будут выгодны?

                Например для начала писать тесты только для того, что легко тестировать.

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


              1. obrizan Автор
                31.07.2018 10:53

                а польза от них минимальна


                Что значит «минимальная польза»? Т. е. они не обнаруживают никаких ошибок или регрессий?

                Как-то оценивалось функциональное покрытие тестов?


      1. SergejSh
        30.07.2018 09:07

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


        1. VolCh
          30.07.2018 12:43

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


      1. dimm_ddr
        30.07.2018 12:37
        +1

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


        1. VolCh
          30.07.2018 13:26

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


          1. dimm_ddr
            30.07.2018 16:33
            +1

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


            Ну и последнее: регулярно вижу на митингах по оценке тасков пойдущих в спринт как разработчики говорят что-то вроде: "Здесь на 2-12-бесконечность часов больше нужно, потому что нужно модифицировать кусок который делал человек который уже уволился, как он это сделал никто не знает, тестов чтобы хотя бы примерно убедится что ничего лишнего не поменялось нет. А значит придется тратить время на изучение не только куска который нужно поменять, но и массы других вещей." В результате разработчик недоволен потому что копается в ужасном по его мнению легаси, менеджер недоволен потому что нормальных точных сроков на такой таск никто не даст, клиент не доволен потому что типовой таск, который уже выполнялся в другой части системы за Х часов здесь требует Х + У часов которые нужно оплачивать, да еще и без гарантий что разработчики уложатся.


            1. VolCh
              31.07.2018 18:14
              -1

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

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


      1. ApeCoder
        30.07.2018 21:21

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

        Что значит не ошибки — а что?


        1. dimm_ddr
          30.07.2018 22:49

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


        1. VolCh
          31.07.2018 10:01

          Ещё не реализованная функциональность. При TDD падение теста сразу после его написания — норма. Вот если написал тест и он зелёный — значит, скорее всего, ошибка в тесте.


          1. ApeCoder
            31.07.2018 10:32

            Это не значит, что все красные тесты не ошибки. Есть красные тесты которые ошибки.


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


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


  1. NeverIn
    30.07.2018 17:28
    +1

    Отдельное спасибо за определение тестопригодности приложения.