company_banner

Мой ответ тем, кто полагает, что значение TDD преувеличено

Автор оригинала: Tylor Borgeson
  • Перевод
Однажды я разговорился с разработчиком из компании-клиента о программном обеспечении. Мне стоило бы понять то, что разговор пошёл куда-то не туда, когда собеседник сказал о том, как нам, разработчикам ПО, повезло: «Мы обманом заставляем организации платить нам за, как кажется, простую работу». Неважно — насколько некто продвинулся в деле написания кода, но я полагаю, что не стоит говорить обо всей индустрии разработки программного обеспечения как о чём-то вроде шайки мошенников.

Я не стал заострять на этом внимание, разговор добрался до Agile. Клиент, в целом, был открыт идее испытания новых методологий и улучшения своих рабочих процессов. Но — лишь до тех пор, пока я не упомянул о разработке через тестирование (TDD, Test-Driven Development). Единственным ответом на это была следующая фраза: «Значение TDD преувеличено».



Мне не только больно было это слышать, но это заставило меня понять то, что TDD — это ещё одна из тех Agile-методологий, которые могут выглядеть чем-то вроде «городских легенд». Это — то, что заставило меня написать данный материал, в котором мне хотелось бы обратиться к тем, кто сомневается в ценности TDD.

Что такое TDD?


Позвольте мне начать с определения TDD. Это стратегия разработки программного обеспечения, в ходе реализации которой при создании программы полностью руководствуются написанием тестов. Собственно говоря, это вполне понятно и из названия данной методологии. Эта идея предложена Кентом Беком в его книге «Разработка через тестирование», которая была написана в 2003 году. Применение TDD предусматривает выполнение следующих трёх шагов:

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

Этот процесс ещё известен как цикл «красный, зелёный, рефакторинг» («Red, Green, Refactoring»).

Вот — простой пример применения TDD. Здесь мы хотим написать на Python метод, который предназначен для вычисления переменной C по теореме Пифагора.

Вот код теста (файл test.py):

#!/usr/bin/env python

"""
test.py
"""

import unittest

from main import *

class TestDrivenDevelopment(unittest.TestCase):

        def test_pythagorean_theorem(self):
                a, b = 3, 4
                self.assertEqual(calculate_side_c(a, b), 5)

if __name__ == '__main__':
    unittest.main()

Вот код метода (main.py), в котором пока ничего не происходит:

#!/usr/bin/env python

"""
main.py
"""

def calculate_side_c(side_a, side_b):
    return True

Теперь попробуем запустить тест.


Тест дал сбой («Красная» часть цикла TDD)

Перепишем код, приведя содержимое main.py к следующему виду:

#!/usr/bin/env python

"""
main.py
"""

def calculate_side_c(side_a, side_b):
    c_squared = (side_a * side_a) + (side_b * side_b)
    c = c_squared ** 0.5
    return c 

Снова запустим тест.


Тест прошёл удачно («Зелёная» часть цикла TDD)

Теперь подвергнем код main.py рефакторингу:

#!/usr/bin/env python

"""
main.py
"""

def calculate_side_c(side_a, side_b):
    return ((side_a ** 2) + (side_b ** 2)) ** 0.5


Тест прошёл удачно и для кода, подвергнутого рефакторингу (Часть «Рефакторинг» цикла TDD)

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

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

  1. У нас есть QA-отдел. Писать тесты — это их работа.
  2. Создание тестов, в которых вполне могут понадобиться моки и стабы, способно отнять много сил и времени.
  3. У TDD нет никаких преимуществ перед обычной разработкой.
  4. TDD — это медленно.

Разберём эти идеи.

У нас есть QA-отдел. Писать тесты — это их работа


Этот ответ на мой вопрос о том, почему некто не использует TDD, всегда меня немного смешит. Я — большой сторонник принципа «You build it, you run it», когда тот, кто написал код, несёт за него ответственность. Поэтому меня коробит, когда я вижу, что разработчики ведут себя так, будто их единственная задача — это писать функциональный код.

Я глубоко убеждён в том, что разработчики несут ответственность за то, чтобы их код обладал бы следующими качествами:

  • Правильность — соответствие нуждам бизнеса.
  • Понятность.
  • Тестируемость.
  • Расширяемость.
  • Простота.

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

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


Мне понятны чувства тех, кто так говорит. Например, нужно реализовать метод, который принимает три разных входных значения. Каждое из них — это объект, а каждый из этих объектов не имеет необязательных атрибутов. Всё это нужно протестировать, проверив разные варианты работы метода. Для того чтобы это сделать, необходимо настроить стабы и моки, а также — написать большой объём дополнительного кода. И всё это — для тестирования всего одного метода. Я уже бывал в подобных ситуациях. Но я, однако, вижу всё это и с другой стороны.

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

Знакомство с SOLID можно начать отсюда. Здесь же мне хотелось бы остановиться на том, что в аббревиатуре SOLID представлено буквой S, то есть — на принципе единственной ответственности (The Single Responsibility Principle). Это — идея, в соответствии с которой методы и классы должны решать лишь одну задачу. Они должны функционировать так, чтобы их деятельность не влияла бы на остальные части системы.

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

Поговорим о пирамиде тестирования.


Пирамида тестирования (изображение взято отсюда)

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

Тесты пользовательского интерфейса (UI Tests) и сервисные тесты (Service Tests) требуют достаточно больших временных затрат на их проведение. Поэтому основной объём тестов должен быть представлен модульными тестами (Unit Tests), так как на выполнение даже больших количеств подобных тестов уходят миллисекунды. Это, конечно, помогает улучшить и цикл обратной связи, что является одной из основных целей DevOps.

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

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

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

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

У TDD нет никаких преимуществ перед обычной разработкой


По иронии судьбы, о том, что у TDD нет преимуществ перед обычной разработкой, говорят, в основном, те программисты, которые даже не пробовали работать в стиле TDD. А ведь пока что-то не попробуешь, нельзя понять — хорошо это или плохо. Даже группа Coldplay знает о том, что «if you never try you’ll never know».

У TDD есть две главных сильных стороны.

Первое преимущество TDD выглядит достаточно очевидным. Если перед написанием рабочего кода некто всегда пишет тесты для этого кода, то, по определению, в распоряжении программиста всегда оказывается самотестирующийся код. Вот что пишет об этом Мартин Фаулер: «У вас имеется самотестирующийся код в том случае, если вы можете запустить последовательность автоматизированных тестов на кодовой базе и, при успешном завершении тестов, можете быть уверены в том, код лишён существенных дефектов».

Другими словами — применение TDD означает, что код работает именно так, как нужно программисту.

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

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

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

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

TDD — это медленно


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

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

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

В этой работе описана система из четырёх показателей оценки эффективности DevOps:

  1. Частота развёртывания.
  2. Время выполнения изменений.
  3. Время восстановления сервиса.
  4. Частота провалов при изменениях.

Меня тут особенно интересуют показатели «Частота развёртывания» и «Частота провалов при изменениях».

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

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

В книге «The Phoenix Project» рассматривается четыре типа работ. Один из них — это «Неожиданная работа». Подобные работы приходится выполнять тогда, когда разработчикам нужно отвлечься от того, чем они заняты, и заняться чем-то другим. Обычно — исправлением некоей ошибки. Если проект построен из самотестирующегося кода — это минимизирует объём ошибок. Это, в свою очередь, приводит к минимизации объёма «неожиданной работы». А чем меньше в жизни разработчика подобных «неожиданностей» — тем лучше он себя чувствует и тем продуктивнее и качественнее работает.

Если разработчики смогут меньше беспокоиться о багах в продакшне, это значит, что они смогут больше времени уделить разработке нового полезного функционала продукта. А если разработчики заранее обдумывают код, применяют полезные принципы наподобие SOLID и постоянно занимаются рефакторингом — это минимизирует объём «технического долга». Когда команда уверена в функционале и в качестве кода, она может развёртывать его буквально в два счёта. Всё это повышает скорость работы.

Итоги


Как и любой другой инструмент, как и любой другой подход к разработке, методология TDD может поначалу показаться неудобной. А до того, как программисты как следует эту методологию освоят, она может показаться им немного медленной. Что тут сказать? Процитирую Джеза Хамбла: «Если нечто вызывает неприятные ощущения — занимайтесь этим чаще и вы с этим справитесь».

А теперь предлагаю вам попрактиковаться в методологии TDD и заниматься этим до тех пор, пока TDD перестанет вызывать у вас неприятные ощущения :)

Уважаемые читатели! Применяете ли вы методологию TDD при работе над своими проектами?

RUVDS.com
RUVDS – хостинг VDS/VPS серверов

Комментарии 501

    +5
    TDD использую только для сложных алгоритмов и меж-процессорных, меж-аппликационных взаимодействий.
    Для простых приложений, сервисов, библиотек TDD будет избыточным.
    Хотя по идее сам считаю, что нужно 100% покрывать код, но реалии диктуют совсем другие сценарии поведения.
    С TDD нужно же как минимум проверку всех входных и выходных диапазонов делать (черный ящик)
    Для белого ящика проверку всех веток и не только на True, но и на False и на грамотный Exception.
    Обожаю TDD но использую его, как уже писал, только для сложных алгоритмов.
    Есть же план выполнения, что бы модуль корректно работал, а то что он вообще не покрыт тестами или создан по TDD технологиям со 100% проверкой кода, никого в принципе не волнует, если код в 1-м и во 2-м случае работает одинаково.
    Критерии оценки только 2, срок и качество.
    Тут же на хабре была статья (которую автор удалил), в которой он рассказывал как делать фейковое покрытие тестами, обучал и рассказывал как не свихнуться в фирме в которой заставляют делать тесты на любой код. Потому из под палки TDD врятли приведет к чему то хорошему, тк проверяющему надо на 100% голову включить и на проверку кода алгоритма и на проверку всех вариантов по TDD. Может показаться, что проверка алгоритма и проверки по TDD одно и тоже, но это не так.
    С TDD нужно намного больше головой думать.
    Грамотно спроектировать приложение или библиотеку по TDD, ну как минимум на 25% нужно больше времени, чаще выходит увеличение времени в разы.
    Для сложных алгоритмов это окупается с лихвой, тк последующие внесение изменения алгоритма время затрачивается по экспоненте, для простых приложений и алгоритмов создавать проекты по TDD это чрезмерная трата времени и сил, по крайней мере для меня.
    — Тоже бы хотел услышать не просто использовать TDD или не использовать, для меня однозначно использовать, я бы хотел узнать КАК!!! сократить время на проектирование по TDD, потому что часто бывает описание алгоритма в ТЗ 4 строчки и спроектировать алгоритм и разрабатывать дальше по методике экстремального программирования это одно, а разрабатывать алгоритм по TDD технологии с описанием все параметров, проверкой всех веток, ну это абсолютно другое и время затраченное на простых приложениях по TDD может быть и в 10 раз больше, чем при экстремальном программировании.
      +4
      А правильнее будет как раз наоборот. Ну почти что.

      TDD — это про юнит-тесты. То есть тесты для компонентов*, которые написаны Вами, и в которых зависимости** замоканы. В них мы прогоняем большое количество различных случаев, в которых убеждаемся, что требования выполняются и программа работает именно так как это ожидается.
      Если компонент написан правильно, очень легко покрыть его юнит-тестами на 100%

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

      Типичный сценарий написания программы по TDD выглядит примерно так:
      1. Получаем требования, дизайним контракт вызовов. Получаем документ с описанием API.
      2. Пишем юнит-тесты согласно контракту. Получаем примеры использования API
      3. Пишем имплементацию. Наши юнит-тесты начинают проходить.
      4. Делаем интеграционные тесты с реальными зависимостями, убеждаемся что они проходят. Если нет — чиним инициализацию, DI, инфраструктуру и т.д.

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

      **зависимость (чужой компонент) — компонент, которому делегируется часть функций компонента, который мы разрабатываем. Может быть частью фреймворка, который мы используем, или написан нами, но вне рамок текущей задачи.
        0
        Я соглашусь с вами только в одном: принцип — никогда не доверяй входящим переменным. Только это всегда защищало мой код от всех вмешательств. Да, тесты избегали изменения функции, но также можно поменять и тесты (как и функцию — довольно часто это наблюдаю в бизнес разработке). Если поддерживать принцип «не доверяй входящим переменным» в рамках функции (и возврату из других), то все сразу становится на свои места и код становится нереально чистым и читабельным. И это сразу покрывает тесты и документацию (потому что стараешься чтобы код не был монструозным). Итого код защищен, а тесты чаще для того, чтобы было
          0
          fcoder
          TDD — это про юнит-тесты

          Сорри, надо было более подробно выразится на счет TDD
          Классическое TDD — это Test Driven Development, но для себя я его делю на 2 типа:
          1. Процедурное — когда нужно разработать функционал процедуры, функции.
          2. Архитектурное — когда нужно разработать архитектуру приложения/проекта по этим принципам.
          Я имел в виду только эти сложности самого проектирования по TDD.
          Юнит тесты, интергационное, интерфейсное, нагрузочное и прочее тестирование для меня не важно, для меня важно сейчас научиться грамотно создавать архитектуру проектов по этому принципу.
          Вот что для меня сейчас «больная мозоль» в TDD.

          DSL88
          никогда не доверяй входящим переменным

          У нас с этим попроще, pascal.
          Основной фокус на алгоритмах.

          * * * * * * * *
          * не могу писать в ветках, поэтому напишу тут, кому хотел ответить
          * * * * * * * *
          HellWalk
          Ведь самое главное, в TDD — это на 100% понимать какие публичные методы будет иметь объект(ы)

          M1haShvn
          Статьи говорят «продумать архитектуру». Но архитектура — это общий принцип, а не конкретные «потроха»

          Коллеги, вы понимаете мою «боль».
          Да же при наличии спецификации иногда трудно для себя определить не только уровень параноидальности проверок. даже для простой функции умножения.
          1. будут ли ограничения типов? (real/int/int64)
          2. будут ли отрицательные числа?
          3. что делать при переполнении?

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

          DistortNeo
          Понятное дело, что если вы пишете высокопроизводительный код, то подобное тестирование может начать вставлять палки в колёса.

          Не знаю, не знаю. Если мне надо написать высокопроизводительный код, я 100% его буду разрабатывать по TDD
          Druu
          Потому что программист между качеством кода и удобством тестирования вынужден в случае TDD выбирать второе в ущерб первому.

          Позвольте не согласится. Качество кода с TDD будет лучше однозначно, тк заставляет посмотреть на код более детально и глубже. Скорее всего речь идет о скорости разработки и сдачи кода, с этим соглашусь, но качество кода однозначно будет лучше с TDD.
          Докажу это на примере. Если у вас супер-мега-сложная функция, в которой просто ну нельзя вставить ни одного символа для тестирования, в таких случая просто тестируйте ф-ю как «черный ящик». И даже при использовании тестов методом только одного «черного ящика» качество кода гарантированного будет выше, чем вы сделайте это вообще без тестов. Тем более отлаживать то все равно будете, что мешает во время отладки сразу сделать тест и в последствии вместо отладки нажать на кнопку теста, автоматизировав эту проверочную ситуацию?
          Как я выше написал, конечно нужен баланс и я сам редко использую «процедурное» TDD, но хочу научиться 100% все делать по TDD и делать это быстро, но увы… если нужна скорость, то TDD первым идет в топку.

          netch80
          TDD не позволяет разработать реально сложный алгоритм

          TDD предназначена не для разработки алгоритмов, я для проверки алгоритма по спецификации.
          С пониманием этого, становится понятно, что важно не test-first, а чтобы тесты вообще работали

          100% соглашусь, тк в большинстве своем тесты пишутся после кода. TDD — это конечно идеал, когда много времени, четкая спецификация. Как по мне, первым тест-вторым код или первым код-вторым тест не принципиальная разница, если делается полное покрытие, но если писать код сложного метода, я начинаю делать именно по TDD. У меня по TDD сложный код быстрее пишется.
          Я вот хочу сейчас архитектуру проектов делать по TDD, тыкаюсь как котенок, попадалось ли на горизонте подобная информация?
            0
            Позвольте не согласится. Качество кода с TDD будет лучше однозначно

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


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


            в таких случая просто тестируйте ф-ю как «черный ящик»

            ЛЮБУЮ функцию следует тестировать как черный ящик. Иначе ваши тесты — это просто горка мусора, которая:


            1. бесполезная
            2. затратная

            Кроме того, TDD в принципе явно запрещает тестирование иначе как методом черного ящика.


            Тем более отлаживать то все равно будете, что мешает во время отладки сразу сделать тест и в последствии вместо отладки нажать на кнопку теста, автоматизировав эту проверочную ситуацию?

            То, что:


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

              Начните утро с волшебным вкусом Property Based Testing.

                0

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

                  +1

                  Не понимаю, к сожалению, о чем вы. Вы по ссылке-то сходили?

                    0
                    Не понимаю, к сожалению, о чем вы.

                    Чтобы написать тест (или сгенерировать автоматом как в QuickCheck, не важно) вам нужно знать какое-то св-во, которому должна удовлетворять ваша ф-я. Но если вы это св-во для тестов задали — значит, вы его не забыли. Значит, вы его учли в коде. Если же вы его забыли — то тест этой ошибки не поймает, т.к. не будет знать, что ему ловить.


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

                      +1
                      св-во для тестов задали — значит, вы его не забыли. Значит, вы его учли в коде

                      А, понял. Это не верно :) То есть, верно наполовину.


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

                        0
                        Чтобы написать тест (или сгенерировать автоматом как в QuickCheck, не важно) вам нужно знать какое-то св-во, которому должна удовлетворять ваша ф-я. Но если вы это св-во для тестов задали — значит, вы его не забыли. Значит, вы его учли в коде. Если же вы его забыли — то тест этой ошибки не поймает, т.к. не будет знать, что ему ловить.

                        В таких случаях может помочь QuickSpec

                          0

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

                    0
                    Мы пробовали… но для него надо специально готовить код, чтобы анализаторы понимали, куда тут чего внедрять. Это ещё хуже, чем TDD: там хотя бы понятные очевидные методы декомпозиции.

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

                      Что? Это в каком языке такой кошмар?

                        0
                        Erlang, игрались с PropEr.

                        Ну, может, мы просто что-то не так начали делать, но вот вам пример реальной задачи (честно — именно такое было в живом полезном коде). Есть список пар — двухэлементных кортежей. Сгруппировать его по этим первым элементам, заменив второй элемент пары на список таких из исходного списка. Выходной список должен быть отсортирован по первым элементам (UPD — а по второму должен сохраняться порядок исходного списка).
                        Например, из [{a,ax},{b,by},{a,aa},{b,bb}] должно получиться [{a,[ax,aa]},{b,[by,bb]}].
                        Юнит-тесты достаточно банальны. Можете описать, как это формализовать на QuickCheck или PropEr?
                          +1

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


                          • Генерируете список переменной длины, с повторяющимися первыми элементами кортежей (поэтому лучше использовать кастомный генератор).
                          • Для каждого такого списка вызываете проверяемую функцию на N пермутациях (можно даже просто на двух разных).
                          • Удостоверяетесь, что результаты совпадают.
                          • Voilà.



                          Но я не говорил, что property testing — серебряная пуля :) Конкретно для этой задачи я бы просто не переизобретал велосипед. Кладете первый список в ets, bag, идете по нему несколькими (по количеству ядер) процессами и перекладываете элементы в ets, ordered_set, с помощью ets:update_element-3. Теперь вычитываете новую таблицу и в один проход сортируете списки значений. Я не на 100% уверен, но, кажется, так и быстрее будет, и тестировать меньше, все уже протестировано.

                            0
                            > Для каждого такого списка вызываете проверяемую функцию на N пермутациях (можно даже просто на двух разных).
                            [...]
                            Ну по факту в этом случае никакой разницы с тем, что такой тест будет написан тупо вручную. В чём мы тогда и убедились.
                            Может, есть какой-то особый подвид задач, в которых подобная автоматизация идёт на пользу, но нам они не встретились.

                            > Кладете первый список в ets,

                            Могу рассматривать это только как шутку: суммарный объём кода окажется таким же, ясность — сильно меньше, ещё и привлечение ETS там, где без него можно свободно обойтись. Тестировать же надо будет по любому (и тоже не меньше).
                              +1
                              по факту в этом случае никакой разницы с тем, что такой тест будет написан тупо вручную

                              Шринкинг вы тоже вручную будете делать? Кроме того, оно может поломаться на своеобразных инпутах, типа 'ф́' — их PropEr вам нагенерирует в достатке, а руками — все не переберешь. Посмотрите, что он генерирует.


                              Тестировать же [ETS] надо будет по любому (и тоже не меньше).

                              Отнюдь. Полагается доверять тому, что ordered_set ведет себя как ordered, то есть вам не надо будет проверять собственно сортировку.

                                0
                                > Шринкинг вы тоже вручную будете делать?
                                > типа 'ф́'

                                Это да, аргумент. Такие вещи оно само за нас пусть автоматизированно делает :)

                                > Полагается доверять тому, что ordered_set ведет себя как ordered

                                Но правильность интеракции с ETS уже под вопросом, и её надо подтверждать тестом.
                                  +1

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

                            +1

                            А мне вот неочевидно, какие там надо написать юнит-тесты, чтобы было полноценное покрытие.

                              0
                              С ходу уже не помню, но рисовал где-то следующий комплект входных данных:
                              []
                              [{a,1}]
                              [{a,1},{a,11}]
                              [{a,1},{b,2}]
                              [{a,1},{a,11},{b,2},{b,22}]
                              [{a,1},{b,2}{a,11},{b,22}]
                              [{a,1},{b,2}{a,11},{a,12},{b,22}]

                              и ещё несколько в том же духе (в пределе до 3 ключей и 3 элементов к ним, кажется — решили, что больше точно не нужно).
                                0
                                (в пределе до 3 ключей и 3 элементов к ним, кажется — решили, что больше точно не нужно)

                                А что, если алгоритм ошибочен, но ошибки проявляются только на списках с 4 ключами и элементами?

                                  0
                                  А вот это уже вопрос анализа сути выполняемого в реализации: так как после сортировки по первому ключу все известные случаи, требующие продумки, это
                                  1) первый элемент списка
                                  2) элемент с тем же ключом, что предыдущий
                                  3) элемент с другим ключом, чем предыдущий
                                  4) конец списка
                                  то реально больше чем 2 ключа и 2 элемента на каждый проверять не нужно, они проблем не дадут. Даже 3 ключа и 3 элемента проверялись не на все случаи, а только для совсем уж оправдания своей совести :)
                                  (А если бы была реализация на mapʼе через дерево — те же самые числа, предполагая, что сама мапа корректно работает.)
                        0

                        Property-based testing — это такие формальные доказательства для бедных тех языков, где явно записать их нельзя.


                        И да, у меня не далее как позавчера был случай, когда quickcheck (да, я пишу на языке для бедных) мог найти контрпример только за 600-800 тестов в среднем (при дефолте в 100). Выводы очевидны, ИМХО.

                          0
                          для тех языков

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


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


                          Такие дела.

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

                            А можно пример свойства, проверяемого через property-based testing, для которого доказательства не существует в природе?


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

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


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

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


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

                              +1
                              Я тоже. Но я хочу иметь возможность особо важные/фундаментальные вещи доказывать, а не проверять сотней-другой примеров.

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


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


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


                              А потом — я стану проверять странные случаи (спойлер: в инверсии списка их нет). Пример из жизни: мы в некоторых случаях позволяем пользователям описывать триггеры по курсам валют в «свободной форме». Например: EUR/USD > 1.2. Парсим их кое-как. И используем, если они верные.


                              Критерий верности: курс похож на настоящий, а если не очень похож — то совсем не похож ни на один из других валютных пар, из всех триггеров этого клиента. Например, EUR/USD > 20 мы не примем никогда, а EUR/USD > 2 — примем, только если клиент не следит еще за EUR/NZD и не пытается там выставить триггер на > 1.2.


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

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

                                А, кстати, почему?


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

                                Но я и тестировать его не буду, понимаете?


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

                                Я не понимаю. Если вы используете property-based testing, то вы там формулируете некоторое свойство, которое проверяете для большого набора входов. Кто мешает его полноценно записать в типе и, ну, написать соответствующий proof term?

                                  0
                                  А, кстати, почему?

                                  Я не считаю его production ready по параметру fault tolerance. В том смысле, что я не очень понимаю, как его мониторить, и что будет, если какой-нибудь процесс помрет. Supervision trees очень быстро приучают к хорошему.


                                  Но я и тестировать его не буду, понимаете?

                                  Угу.


                                  Кто мешает его полноценно записать в типе [...]

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

                                +1
                                Непонятно, зачем рассматривать только два варианта из четырёх.

                                Отвечу отдельно, поскольку это совсем про другое.


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


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

                          0
                          >> Позвольте не согласится. Качество кода с TDD будет лучше однозначно
                          Ну это же очевидно ложное утверждение.

                          Приведите пожалуйста пример КАК (!!!) TDD может умудриться ухудшить качество кода?
                          При использовании «черного ящика» я определяю только входные и выходные параметры, внутрь никто не лезет, что там и как, никого не должно волновать. Как черный ящик со своими данными которые проверяют спецификацию может ухудшить качество кода, если он проверят функционал спецификации? Пример пожалуйста приведите ухудшения.
                          Совсем другое «белый ящик», с ним может снизится скорость и только, но никак не качество. Да и применение «белого ящика» ограниченно, куда его всунешь в MMX/SSE оптимизацию?

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

                          При чем тут «гипотезы»?
                          Ответьте пожалуйста, Вы реально применяете TDD или только «проверяете гипотезы»?
                          Если вы только «проверяете гипотезы», я даже общаться не хочу, я хочу поговорить только с теми кто использует у себя TDD.
                          Предположу, что Вы применяете у себя TDD, поэтому продолжу.
                          Кроме того, TDD в принципе явно запрещает тестирование иначе как методом черного ящика.

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

                          отвечу мемом:
                          «Может просто вы не умеете их готовить?» (с)

                          в общем случае написание подобного рода тестов обычно требует более чем удесятирения трудозатрат.

                          Если мы говорим про «Процедурное TDD» и «черный ящик», то однозначно нет, тк трудозатраты уменьшаются.
                          я сейчас говорю не о простых методах типа MyEcho который внутри вызывает только одну системную ф-ю Echo, а про более сложные алгоритмические методы
                          Если говорим про «белый ящик» и «Архитектурное TDD», то тут соглашусь, время увеличивается значительно.

                          юнит-тесты… А если вы кейз не учли

                          Я вот это выражение часто вижу, но вообще не понимаю, как такое может быть в процедурном TDD?
                          Есть спецификация и по ней пишется функционал, если уж пишутся тесты то спецификация должна полностью быть покрыта тестами.
                          А вот то что вместо бинарных чисел, кто то отправляет символьные числа (игнорируя спецификацию) или затирается память другим потоком, то на все случаи такие кейсы заранее не сделать, я сейчас говорю про кейсы по спецификации, а они должны быть покрыты полностью.
                          И вот это «кейз не учли», просто не допустимо. Или протестировали или нет функционал, вот и все.
                          PS:
                          Если вы используйте TDD (ну или кто то еще), пишите сразу в личку, ждать сутки что бы ответить, ну как то не камильфо, и кто нибудь знает хорошие форумы по TDD?
                            0
                            Если на заборе написано «слово», а за ним дрова, то вывод очевиден.

                            Ну да, сарай ill-typed.

                              +1
                              Приведите пожалуйста пример КАК (!!!) TDD может умудриться ухудшить качество кода?

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


                              При чем тут «гипотезы»?

                              А что это, если не гипотеза?


                              Если честно, мне по барабану, кто там что запрещает, я делаю как МНЕ удобно

                              Тогда при чем тут TDD, если то, что вы делаете, TDD, по определению, не является? Что мы вообще обсуждаем тогда?


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

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


                              Есть спецификация и по ней пишется функционал, если уж пишутся тесты то спецификация должна полностью быть покрыта тестами.

                              Ну так спецификация на практике будет неполна.

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

                                такого выбора не бывает


                                код который хорошо тестируется и есть качественный
                                именно некачественный код плохо тестируется

                                  +2

                                  Вам доводилось когда-нибудь тестировать взаимодействие сотен тысяч процессов (green threads), чтобы выявить возможные race conditions?

                                    0

                                    конечно доводилось.


                                    и выявить/устранить рейсы можно как раз сперва приведя код в вид "хорошо тестируется" и затем поправив проблемные места

                                    +1
                                    код который хорошо тестируется и есть качественный

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

                                      +1

                                      потому что сделать утверждение "качественный или нет" можно только протестировав


                                      а если код не поддаётся тестированию, то это код Шредингера


                                      пользы от него никакой. и вреда тоже никакого.
                                      поскольку код такой никто не использует

                                        +1
                                        потому что сделать утверждение "качественный или нет" можно только протестировав

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


                                        а если код не поддаётся тестированию

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

                                          +1

                                          по моему ударились в какие-то терминологические замороки.


                                          плохо поддаётся тестированию == плохой код.


                                          равенство однозначное. даже если этот плохой код работает так как требуется.
                                          "плохо поддаётся тестированию" — будут большие трудности вносить изменения.


                                          код, изменения в который вносить трудно == плохой код

                                            0

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


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


                                            Лихо.

                                              0

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

                                                –1
                                                Прекрасно, мы пришли к тому, что почти весь окружающий вас софт чуть сложнее интернет-магазина (да и то не всякого) — написан плохим кодом.

                                                Далее бритва нашего Оккама позволяет нам придти к выводу, что если большая часть кода в мире написана плохим кодом — это работает, и является (в масштабе человечества) наиболее эффективным в данный момент способом разработки. То есть, плохой код = реальный нужный код, а «хороший» (в ваших дефинициях) код = либо фантастика, либо трюизм.
                                                  +2
                                                  либо фантастика, либо трюизм

                                                  Либо интернет-магазин же.

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

                                                    Так и есть.

                                                0
                                                плохо поддаётся тестированию == плохой код.

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


                                                "плохо поддаётся тестированию" — будут большие трудности вносить изменения.

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

                                                  0
                                                  выбирая между "сделать код легко изменяемым" и "сделать код легко тестируемым"

                                                  нельзя противопоставлять эти параметры, они взаимосвязаны


                                                  легкотестируемый == изменяемый
                                                  труднотестируемый == трудно изменяемый

                                                    –1
                                                    легкотестируемый == изменяемый
                                                    труднотестируемый == трудно изменяемый

                                                    Вы опять просто повторили гипотезу. Аргументы в ее пользу какие-то у вас есть? С чего бы легкотестируемому коду быть легкоизменяемым?


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

                                                      +2
                                                      Не надо, кстати забывать, что код с тестами изменять более затратно, чем тот же код — но без тестов. Ведь кроме когда надо будет изменить еще и тесты.

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

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

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


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

                                                          0
                                                          Тесты позволяют улучшить качество приложения, увеличив затраты на разработку.

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


                                                          увеличение затрат — это актуально только для программ до 300-500 строк кода

                                                            0
                                                            тесты позволяют улучшить качество приложения и уменьшить затраты на разработку.

                                                            Конечно же, нет. Не бывает серебряной пули, которая может улучшить качество, снизив при этом затраты.
                                                            Тесты строго повышают затраты на разработку — это очевидно. Т.к. затраты на разработку с тестами = затраты на разработку без тестов + затраты на написание тестов. Где затраты на написание тестов > 0.

                                                              +2

                                                              Тоже неверно.


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


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


                                                              Хотя проще и быстрее, разумеется, сразу работающий код писать.

                                                                +1
                                                                Тесты могут помочь со сложным алгоритмом, например, потому что запустить → посмотреть чё не так — быстрее, чем вдумчиво изучать неработающий код.

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

                                                                +2

                                                                Да, тесты повышают затраты на разработку, но снижают затраты на поддержку и допиливание продукта.

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

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


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


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


                                                                  и вот написание кода с автоматическими тестами на него — один из таких оптимумов

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

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


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


                                                                    DistortNeo


                                                                    Да, тесты повышают затраты на разработку, но снижают затраты на поддержку и допиливание продукта.

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

                                                                      +1
                                                                      И тесты — повышают качество, повышая затраты.

                                                                      нет. Тесты повышают качество снижая затраты.


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


                                                                      • ручное обнаружение ошибок (расширенный отдел QA)
                                                                      • обнаружение ошибок пользователями (репутационные потери)

                                                                      итп


                                                                      говорить что код с тестами дороже кода без тестов можно только на начальном этапе развития проектов или для маленьких проектов. до 500 (моё имхо) строк кода в проекте.

                                                                        +1

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

                                                                          –1
                                                                          Тесты повышают качество снижая затраты.

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


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

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


                                                                          говорить что код с тестами дороже кода без тестов можно только на начальном этапе развития проектов или для маленьких проектов. до 500 (моё имхо) строк кода в проекте.

                                                                          Наоборот — чем больше у вас проект, тем выше суммарные издержки на тестирование.
                                                                          Еще раз, стоимость_проекта_с_тестами = стоимость_того_же_самого_проекта_без_тестов + стоимость_тестов


                                                                          Иными словами, вот вы можете взять некий проект Х с тестами. Допустим он стоит, ну, 1000 (просто число для определенности. Теперь мы берем и удаляем все тесты. А дальше говорим программистам "извольте покрыть проект тестами". И вот, программисты берут и покрывают проект тестами — это вам обходится, допустим, в 300. Тогда у вас стоимость проекта без тестов — 700 (т.е. за 700 вы могли бы получить вот этот продукт с этим функционалом), стоимость тестов — 300. Тесты увеличили стоимость проекта на 300.


                                                                          Volch


                                                                          Тут нужно уточнить, что затраты на поодержку и развитие снижают качественные тесты прежде всего.

                                                                          Затраты не снижают никакие тесты. Т.к. написание теста — это всегда дополнительные затраты, которые можно было бы не нести.

                                                                            0
                                                                            > Не бывает серебряной пули, которая бы и снижала затраты и повышала качество одновременно. Либо одно — либо другое.

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

                                                                            Польза тестов получается от того, что суммарные затраты от поиска ошибки на этапе её обнаружения у QA в разы выше, чем если бы она не вышла за пределы авторов-программистов, а у юзера — ещё выше, чем у QA. В ряде источников приводятся соотношения — 10 раз для первого и 10 для второго; сейчас источник не помню (что-то близкое к классикам типа Фаулера и Бека), но даже если они очень приврали и реально там получается 3 и 3, то этого уже достаточно, чтобы подумать.

                                                                            А вот дальше стоит вопрос, какое реально наблюдается качество кода без тестирования, какая его часть, грубо говоря, изначально корректна. Если он весь некорректен, то мы можем оправдать затраты на тесты в 2 раза больше, чем на сам код.
                                                                            А если, как для, простите, Боинга те разницы достигают тысяч (оплата страховок погибших плюс репутация), без тестирования всего и вся в тридевять слоёв — даже начинать нельзя…

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

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

                                                                            –1
                                                                            Откуда берется большее количество кода при доработках?
                                                                              0

                                                                              Основной код и код тестов же. Это если не учитывать увеличение объёма основного кода ради тестируемости.

                                                                                +1
                                                                                Не бывает серебряной пули, которая бы и снижала затраты и повышала качество одновременно. Либо одно — либо другое.

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


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

                                                                                если Вы отказываетесь от затрат на автоматические тесты, Вы ВЫНУЖДЕНЫ тратить существенно больше на QA, на репутационные потери связанные с тем что юзеры находят баги и так далее. И итого выходит что код с тестами развивается дешевле чем код без тестов.

                                                                                  0
                                                                                  это не серебряная пуля, а экспериментально найденный оптимум.

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


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


                                                                                  если Вы отказываетесь от затрат на автоматические тесты, Вы ВЫНУЖДЕНЫ тратить существенно больше на QA

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


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


                                                                                  И итого выходит что код с тестами развивается дешевле чем код без тестов.

                                                                                  Вы утверждаете что неравенство в вещественных числах a + b > a ложно при b > 0. То, что это не так, вам без особых проблем докажет практически любой ученик старшей школы. Прекратите спорить с математикой.

                                                                                    0
                                                                                    При этом в каждом проекте эта ф-я своя

                                                                                    вот тут ошибка.


                                                                                    эта функция в каждом проекте своя, пока проект не выйдет на число строк в проекте таким, что это число уже становится статистикой.


                                                                                    моё имхо — от 500 начинается.
                                                                                    а дальше уже развитие всех проектов одинаково


                                                                                    • внесение изменений = рефакторинг + добавление нового — релиз

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

                                                                                      0
                                                                                      эта функция в каждом проекте своя, пока проект не выйдет на число строк в проекте таким, что это число уже становится статистикой.

                                                                                      Нет, эта функция в принципе всегда своя. Вне зависимости от количества строк.


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

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

                                                                                        0
                                                                                        Нет, эта функция в принципе всегда своя. Вне зависимости от количества строк.

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


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

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

                                                                                          0
                                                                                          о том что затраты на то же качество при ручном QA и при использовании автотестов — разные. и при использовании автотестов существенно ниже

                                                                                          Вот это не факт. Вашим языком выражаясь, в разных организациях разные константы в этих затратах.

                                                                                            –1
                                                                                            нет. законы развития у всех проектов одинаковы.

                                                                                            При чем тут законы развития? Мы о требованиях к проекту говорим (функция оценки). А они всегда разные.


                                                                                            о том что затраты на то же качество при ручном QA и при использовании автотестов — разные

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

                                                                                              0
                                                                                              При чем тут законы развития? Мы о требованиях к проекту говорим (функция оценки). А они всегда разные.

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


                                                                                              Какое это имеет отношение к делу-то? Если вы заменяете "дешевыми" юнит-тестами "дорогие" ручные — вы снижаете качество, снижая затраты

                                                                                              нет, именно увеличиваю качество снижая затраты.


                                                                                              если это непонятно почему, давайте по аналогиям пройдёмся в мире.


                                                                                              вот например до какого-то момента в мире промышленности был развит то что называется "хендмейд". Ручная сборка/производство. Затем это повсеместно заменили "конвейером". И качество возросло при уменьшении затрат.
                                                                                              а за конвейером идёт роботизированная сборка/производство. и качество там ещё выше. просто роботов пока не на все операции умеют сделать. Однако всякие станки с ЧПУ повытеснили кучу ручных профессий — фрезеровщики, токари всякие.


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

                                                                                                0
                                                                                                требования примерно одинаковые во всех случаях.

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


                                                                                                нет, именно увеличиваю качество снижая затраты.

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

                                                                                                  0
                                                                                                  Нет, полностью заменив ручное тестирование юнит-тестами вы качество снизите

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


                                                                                                  и с тестами то же самое


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

                                                                                                  не отсутствие, а минимизация.


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


                                                                                                  PS и это, когда нормально покрыто тестами, то для релиза и запускать-то необязательно: в тестах запустится и проверит. В том числе интерфейс GUI

                                                                                                    0
                                                                                                    разработчик, очевидно, приложение запускал

                                                                                                    Не-а :)


                                                                                                    https://habr.com/ru/company/ruvds/blog/486684/#comment_21285792

                                                                                                      0
                                                                                                      когда внедряли конвееры

                                                                                                      При чем тут конвейеры? Это некорректная аналогия.


                                                                                                      и с тестами то же самое

                                                                                                      Практика показывает обратное.


                                                                                                      не отсутствие, а минимизация.

                                                                                                      Отлично. Какие именно ручные тесты не проводятся, когда у вас есть юнит-тесты?


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

                                                                                                      Так в юнит-тестах приложение не запускается. Это же юнит-тесты.


                                                                                                      Вы ж держите контекст — ни автоматические интеграционные, ни е2е-тесты мы тут не обсуждаем.


                                                                                                      chapuza


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

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


                                                                                                      И "нареканий нет" — это что значит? Код у вас с нулевым количествам багов? Или что?


                                                                                                      И, не поделитесь, сколько у вас в среднем кода юнит-тестов на 1000 строк обычного кода и какое покрытие ими?

                                                                                                        0
                                                                                                        Ну мы вроде серьезную разработку обсуждаем [...]

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


                                                                                                        И "нареканий нет" — это что значит? Код у вас с нулевым количествам багов?

                                                                                                        Выявленных — ноль, да.


                                                                                                        И, не поделитесь, сколько у вас в среднем кода юнит-тестов на 1000 строк обычного кода и какое покрытие ими?

                                                                                                        Зависит от многих факторов. Покрытие мы не считаем, это бессмысленная трата времени. Покрытие не показывает вообще ничего, это сто раз уже было отмечено и все, вроде, осознали, примерно лет 10 назад.


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

                                                                                                          0
                                                                                                          Пять экранов — это в данном контексте — размер PR, очевидно, а не проекта.

                                                                                                          Так можно в любом проекте пры при желании поделить так, чтобы каждый на 5 экранов был. И никаких тестов, получается не надо. И 0 багов. Так?


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

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

                                                                                                            0
                                                                                                            нам с вами, в общем-то, и нечего обсуждать тут

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

                                                                                                              0
                                                                                                              Мы тут обсуждаем, нужны ли тесты вообще, а если да — то в каком виде.

                                                                                                              Нет, мы конкретно в этой ветке обсуждаем, являются юнит-тесты серебряной пулей, или нет. Вы утверждаете, что — да, являются, а я — что нет, не являются, просто потому что, как минимум, не существует никакой серебряной пули. А если кто-то говорит, что существует — то это просто на*балово.


                                                                                                              а Вы не упирайтесь в именно юниттесты

                                                                                                              Но речь шла про юнит-тесты, остальное мы не обсуждаем.


                                                                                                              Для них это тоже по сути юнит

                                                                                                              Нет, это не юнит, это вообще уже е2е.


                                                                                                              и вот когда любой: бакендщик, фронтендер чета там пушает — CI присылает полный отчёт "не прошло"/"прошло".

                                                                                                              Ну так вопрос — сколько на это затратили времени программисты и сколько затратил бы тестировщик? При этом тестировщик сделает работу заведомо более качественно, чем автотесты, так как 90% инвариантов автотестами принципиально не проверяется (за приемлемый срок и с приемлемыми затратами). Пока что человек здесь на десятичные порядки дешевле машины. Вот лет через 10 (100, 1000), когда сделают ИИ — другое дело. А пока что слишком дорого это, да и ненадежно. По-этому везде, где заботятся о качестве, есть и нормальный QA.

                                                                                                                0
                                                                                                                Но речь шла про юнит-тесты, остальное мы не обсуждаем.

                                                                                                                речь про юнит тесты не шла.
                                                                                                                речь шла про автоматические тесты вообще.

                                                                                                                  +1
                                                                                                                  речь шла про автоматические тесты вообще.

                                                                                                                  Нет.

                                                                                                                    0
                                                                                                                    Нет.

                                                                                                                    Да.

                                                                                                          +1
                                                                                                          При чем тут конвейеры? Это некорректная аналогия.

                                                                                                          конвейер — пример частичной автоматизации производства


                                                                                                          роботизированный конвейер — пример полной автоматизации


                                                                                                          тесты — пример частичной автоматизации разработки ПО в области тестирования


                                                                                                          всё тут ок


                                                                                                          Практика показывает обратное.

                                                                                                          тем кто практикой занимается — не показывает.


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


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


                                                                                                          Вы ж держите контекст — ни автоматические интеграционные, ни е2е-тесты мы тут не обсуждаем.

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

                                                                                                            0
                                                                                                            всё тут ок

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


                                                                                                            причины сопротивления — чистая лень.

                                                                                                            Лень чего? Для программиста как раз обмазывание юнит-тестами очень выгодно — можно смело сидеть и разрабатывать проект 4 года вместо 1, потребовать себе повышенную зп за дополнительные компетенции и знания популярных баззвордов, ну и потом выдать говно вместо результата т.к. заказчик надеясь на то, что "у нас тут юнит-тесты" сэкономит на нормальном QA и, значит, сам себе злобный буратина, который получил за вчетверо больший срок и бюджет кусок какашки. А программист-то в малине — оставил за собой тысячи строк неподдерживаемых какашек в виде тестов, получил за это деньги и добавил в резюме строчку о завершении такого-то проекта с таким-то стеком и такими-то модными технологиями.


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

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


                                                                                                            то есть TDD — не самоцель, а средство прийти к разработке автоматических тестов одновременно с кодом.

                                                                                                            Не, если вы определяете какое-то свое особое ТДД, то так везед и говорите "TDD по rsync'у", чтобы собеседники понимали- с общепринятым понятием это ничего общего не имеет.


                                                                                                            Но мы тут не обсуждаем TDD rsync'a, мы обсуждаем классическое ТДД с размазыванием 100% покрытия по волосатой груди разработчиков. Если же вы хотите обсудить TDD rsync'а, то это не ко мне, я здесь содержательной темы для обсуждения не вижу.

                                                                                                              0
                                                                                                              А юнит-тесты — и вовсе не автоматизируют работу тестировщика ни на сколько.

                                                                                                              а Вы не упирайтесь в именно юниттесты


                                                                                                              вот мой отдел разрабатывает сайт


                                                                                                              • разработчики бакенда — пишут тесты на низкий уровень — то что работает с БД
                                                                                                              • на более высокий уровень — на ручки http

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


                                                                                                              разработчики фронтенда пишут тесты


                                                                                                              • зайти на страничку
                                                                                                              • убедиться что там есть такой-то элемент
                                                                                                              • нажать на такую-то кнопочку
                                                                                                              • убедиться что результат такой как ожидаем

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


                                                                                                              и вот когда любой: бакендщик, фронтендер чета там пушает — CI присылает полный отчёт "не прошло"/"прошло".

                                                                                                                0
                                                                                                                Лень чего? Для программиста как раз обмазывание юнит-тестами очень выгодно — можно смело сидеть и разрабатывать проект 4 года вместо 1, потребовать себе повышенную зп за дополнительные компетенции и знания популярных баззвордов

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


                                                                                                                Вам надо попробовать программировать с тестами и убедиться в этом.


                                                                                                                ПОНАЧАЛУ — работа в новой непривычной парадигме — вероятно будет какое-то замедление, а вот когда написание автоматических тестов станет привычным — скорость относительно коллективов не пишущих тесты возрастёт.


                                                                                                                Но мы тут не обсуждаем TDD rsync'a,

                                                                                                                мы тут обсуждаем TDD. А цель TDD по мнению rsync'а в том чтобы заставить программистов писать код вместе с тестами.


                                                                                                                а по Вашему какая цель у TDD?

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

                                                                                                            Конвейеры никогда не работают сами по себе. Над ними ещё один или больше уровней контроля качества, от самого конвейера (не сломан, крутится в нужную сторону, скорость оптимальна и не завышена, на ленте то, что надо, а не останки прошлогодних бегемотов) и до контроля качества выходного результата.
                                                                                                            Это хорошая аналогия в том смысле, что юнит-тест полезен только тогда, когда у вас этот юнит выполняет нужное по ТЗ и правильно подключен, а эти два условия вы никак юнит-тестами не проверите — только всяческими интеграционными и вплоть до финальных ручных проверок.
                                                                                                            А ещё надо убедить заказчика — который, если у него голова на плечах, поверит только при наличии успеха тестов верхнего уровня и он сам всё прощупает, на что хватило времени и духу. Это и для внутреннего заказчика (product owner, или как он там будет у вас зваться).

                                                                                                            > не отсутствие, а минимизация.

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

                                                                                                            > PS и это, когда нормально покрыто тестами, то для релиза и запускать-то необязательно: в тестах запустится и проверит. В том числе интерфейс GUI

                                                                                                            Если 1) можно покрыть автотестами весь GUI (практика показывает, что возможно не всегда), 2) вы ещё и 100% доверяете тестирующим средствам — а в случае GUI как раз их доля ошибок максимальна: они не люди, и видят иное. Реально приходится заметно выгибаться под облегчение такого тестирования — например, расставлять метки типа div id, a name и т.п., чтобы они надёжно опознавали конкретные элементы. Но уже этой расстановкой можно создать false positives, так что её тоже надо проверять.

                                                                                                              0
                                                                                                              Конвейеры никогда не работают сами по себе. Над ними ещё один или больше уровней

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


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

                                                                                                                0
                                                                                                                Если 1) можно покрыть автотестами весь GUI (практика показывает, что возможно не всегда),

                                                                                                                практика показывает что возможно всегда.

                                                                                                              0

                                                                                                              Я скоро как пять лет очень плотно участвую в разработке одного веб-приложения. У него достаточно сложная и разветвленная витрина.


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


                                                                                                              Не нужно обобщать.

                                                                                  0

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

                                                                                    +2

                                                                                    Тесты помимо основной функции — тестировать, ещё выполняют воспомогательную: тесты являются синопсисом/екзамлами "как использовать основной код"

                                                                                      0

                                                                                      Ага, особенно упомянутые вами тесты на функцию сортировки, например.


                                                                                      Как тесты на сортировку показывают, какие требования предъявляются к компаратору?

                                                                                        0
                                                                                        Например, примером кода компаратора для небанального случая (как 3-элементный кортеж, для старта).
                                                                                          0

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

                                                                                            0
                                                                                            > Из этого всё равно не следует, что компаратор должен удовлетворять тем или иным условиям.

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

                                                                                            > следует, что от компаратора для этого алгоритма сортировки требуется только тотальность

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

                                                                      Тестируемость кода — необходимое условие, но не достаточное

                                                                        0

                                                                        достаточно того что условие необходимое

                                                                      0
                                                                      Хм, попробуйте описать построение, например, стандартной quick sort с подобными требованиями TDD. Поэтапно, в последовательности «написали тест, уронили, сделали код, который лечит только этот тест и ничего больше… пошли к следующему тесту».
                                                                      Мне честно интересно: я до сих пор считал, что это невозможно. Но, может, вы осилите это невозможное? ;)
                                                                        0

                                                                        а зачем описывать примитивы, сорт или реверс списка.


                                                                        давайте нормальные задачи


                                                                        а если уж надо quick-sort то на начальном этапе — взять пропустить через sort


                                                                        • пустой массив
                                                                        • массив из одного элемента
                                                                        • и десяток руками написанных массивов из 3-5 элементов и убедиться что на выходе имеется то что ожидаем.

                                                                        затем если придёт фидбек "найден невалидный кейз" — добавлять этот кейз в тесты и фиксить проблему.

                                                                          0
                                                                          > а зачем описывать примитивы, сорт или реверс списка.

                                                                          Ну а что, qsort останется нетестированной? Как вы тогда докажете её корректность?
                                                                          И почему так сразу «примитив»? Это вполне серьёзная сложная задача с кучей тонкостей и особенностей реализации. И да, даже реверс списка можно тестировать (можно грустно и скучно, а можно так).

                                                                          > а если уж надо quick-sort то на начальном этапе — взять пропустить через sort

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

                                                                            пойдёт.


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


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


                                                                            затем если появятся проблемы — добавляем эти проблемы в тестовую кодобазу


                                                                            доказывать что сорт именно сортирует — не нужно.


                                                                            всё это по науке

                                                                            нафиг науку!
                                                                            бизнес ждёт результата с минимизированной, а не сведённой к нулю, вероятностью ошибки


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

                                                                              0
                                                                              > пойдёт.

                                                                              Может, и пойдёт. Но всё это не TDD, а обычное тестирование, даже если с test-first.
                                                                              Как раз такого я и ожидал (хотя надеялся на лучшее). Спасибо.
                                                                                +1

                                                                                давайте от целей пойдём и вернёмся к хронологии


                                                                                1. сперва люди просто писали программы
                                                                                2. потом кто-то придумал что круто их тестировать не просто так, а при помощи других программ — тестов
                                                                                3. потом пришли к тому что программы с тестами имеют в среднем лучшее качество чем программы без оных
                                                                                4. попытавшись пропагандировать "пишите тесты" натолкнулись на противодействие аудитории "не хотим"
                                                                                5. разработали "методику" внедрения "написания тестов" в разработку: ТДД причём не столько для разработчиков, сколько для руководителей "спрашивайте с подчинённых чтобы СПЕРВА писали тесты, потом код и это противодействие получится преодолеть"

                                                                                то есть первичная цель ТДД — именно приучить программиста писать тесты.
                                                                                а дальше если он их начал писать, входит во вкус (понимает что это меньше трудозатрат чем их не писать) и уже становится фиолетово: до их пишет или вместе. Или иногда после.
                                                                                так же становится отчасти фиолетово юнит-то тесты или не совсем юнит.


                                                                                итп


                                                                                вот первичная цель ТДД.
                                                                                Если считаете по другому — расскажите

                                                                              0
                                                                              И да, даже реверс списка можно тестировать (можно грустно и скучно, а можно так).

                                                                              Только по ссылке же не тесты.

                                                                            +1

                                                                            custom sort не надо тестировать; если мы не доверяем себе — зовем человека, который способен это сделать без тестов, а потом берем любую существующую медленную сортировку и сравниваем результаты.


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

                                                                              0
                                                                              А почему сразу речь про custom? Пусть в библиотеке штатной сортировки вообще нет. Если TDD универсален, то он должен работать и в таких случаях.
                                                                                +1

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


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

                                                                        +1
                                                                        Приведите пожалуйста пример КАК (!!!) TDD может умудриться ухудшить качество кода?

                                                                        Навскидку:


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

                                                                        Понятно, что это не TDD конкретно виновато, а общий подход к написанию тестов, но выглядит это так "мы внедряеем TDD", после чего качество кода портится

                                                                          0

                                                                          Вы передёргиваете и возводите 100% покрытия кода в абсолют. Не нужно писать тесты ради покрытия. Лично я не вижу смысла тестировать приватные методы. Они реально будут только мешать, а не помогать в поддержке.

                                                                            0

                                                                            Про 100% я не говорил ничего. Просто разные подходы к написанию самих тестов есть.

                                                                              0
                                                                              Метод методу рознь. Метод может быть весьма сложным, но никому не нужным за пределами класса и как-то работающим с приватными переменными — и тогда его надо и тестировать, и оставлять приватным.
                                                                              Ну а как это делать — уже от языка зависит. Начиная с `#define private public` :)
                                                                              +1
                                                                              организуем проброс зависимостей, чтобы их можно было мокать

                                                                              Э-э-э-э… А что, на последнем пленуме dependency injection развенчали и объявили гадостью?

                                                                                +1
                                                                                Формально реализовали DI, на практике интерфейс добавился в коде, который используется только один раз.

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

                                                                    +2
                                                                    Как TDD ложится на изменение требование в процессе самой разработки? Переписывать и код и тесты сразу?
                                                                      +3
                                                                      А сейчас что вы делаете?
                                                                        +1
                                                                        Ну, наверно, сейчас он разрабатывает, в процессе требования меняются, к концу разработки более-менее устаканиваются и после этого пишутся тесты. Или у вас всегда сразу есть полное и чёткое ТЗ?
                                                                          –4
                                                                          Или у вас всегда сразу есть полное и чёткое ТЗ?

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

                                                                          Я вообще плохо понимаю, как можно что-то писать без четкого. Сказали «напиши программу» и пишешь? А потом выясняется, что нужна была программа для расчета траектории, а не графический редактор.
                                                                            +2
                                                                            Я вообще плохо понимаю, как можно что-то писать без четкого. Сказали «напиши программу» и пишешь?
                                                                            Не «напиши программу», а «хотим, чтобы можно было делать то-то и то-то». И всё, берёшь и пишешь.
                                                                          0
                                                                          Ниже верно ответили. Тесты после того как требования станут стабильными.
                                                                          +2
                                                                          А что же проверит код на соответствие новым требованиям, как не переписанные под эти требования тесты?
                                                                            +2
                                                                            Тесты. Но потом(с).
                                                                            –1
                                                                            Переписывать код же легче, если есть тесты (юнит-тесты как минимум).
                                                                            +11
                                                                            Когда речь идет о чистом программирование — TDD — отличная методика. Как только дело касается программирования с «привлечением оборудования», становится гораздо труднее.
                                                                            Например, функция рендеринга через какой нибудь OpenGLES. Результат рендеринга оказывается на экране, и прямого доступа процессором в ту область видеопамяти просто нет (или чрезвычайно затруднен).
                                                                            Как написать тестирующую функцию?
                                                                            Что касается самого рендеринга, то он делается не процессором, а GPU и со стороны процессора очень трудно контролировать работу GPU. Даже измерить время работы команды, отданной в GPU не просто, так как команды просто складываются в FIFO GPU на исполнение.
                                                                              +1
                                                                              Как написать тестирующую функцию?

                                                                              Это не просто, но решения есть. Например, фреймворк gfx-rs использует инструмент под названием Warden: https://github.com/gfx-rs/gfx/tree/master/src/warden

                                                                                +5
                                                                                Жирный плюс этому комментарию.

                                                                                Приходится на работе писать код под аппаратные комплексы, которые мы делаем. Ситуация та же с точностью до 99,(9)%. Большая часть написанных алгоритмов (которые как раз и хотелось бы тестировать) не имеют единственно правильного ответа от слова совсем, а оставшаяся обвязка (которая не алгоритмы), работает с железом…
                                                                                  +3
                                                                                  Тоже работаю с железом (программирую под МК), тоже раньше так думал.
                                                                                  Пока не написал свои первые тесты. Нужно изменить подход к написанию такого софта, убрать так любимое эмбеддерами повсеместное прибитие кода гвоздями к железу.

                                                                                  Да, написать тест к модулю modbus, реализующему L1/L2 уровень, где нужно вычислять по аппаратным прерываниям аппаратными таймерами задержки в миллисекунды — скорее всего сложнее чем один раз это все отладить осциллографом и потом не трогать никогда.

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

                                                                                  Всю работу с uart/usb/светодиодами/eeprom нужно полностью абстрагировать и предоставлять возможность эмулировать их работу программно.
                                                                                  Проще говоря — побольше функционального программирования и все получится.
                                                                                0
                                                                                У TDD нет никаких преимуществ перед обычной разработкой

                                                                                Не могли бы Вы развернуто ответить про обычную разработку? Что это за разработка, которая не включает, как минимум manual-testing? А если она включает, то это, конечно, неполноценное TDD, но какой-то упрощённый вариант. Или я что-то не понимаю…?
                                                                                  +6
                                                                                  А если она включает, то это, конечно, неполноценное TDD,

                                                                                  Нет, не неполноценное, а вообще никакое не TDD. TDD — сначала пишется тест, а потом код. А если сначала пишем код, а потом потестируем, то это не ТДД, а та самая обычная разработка и есть.
                                                                                    +1
                                                                                    Почитал Википедию по TDD и прозрел.
                                                                                    TDD и обычная разработка одно и тоже, за исключение момента когда начинают писать тесты. Век живи — век учись.
                                                                                      +2
                                                                                      Почитал Википедию по TDD и прозрел.
                                                                                      TDD и обычная разработка одно и тоже, за исключение момента когда начинают писать тесты. Век живи — век учись.

                                                                                      Не совсем. TDD про сам итеративный процесс и некоторые ограничения в виде "сначала пишется код который проходит один тест, потом пишется следующий тест".


                                                                                      Просто написав все тесты до кода вы не получите TDD, это просто test first подход

                                                                                        +5

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


                                                                                        сначала пишется код который проходит один тест, потом пишется следующий тес

                                                                                        Более того, TDD не разрешает писать код, который имеет функционал сверх написанного теста. То есть нельзя держать в голове сразу 2-3 теста. Нельзя писать сразу оптимльный код. Нужно реализовывать код так, как если бы об остальных тестах вообще не было ничего известно. Это очень неудобно.

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

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

                                                                                    Насколько выразительной должна быть система типов, чтобы полностью избавится от юнит-тестов? Боюсь такого языка еще не изобрели.

                                                                                      –3
                                                                                      Хаскель изобрели весьма давно, и выразительности там только добавляется. А есть еще и менее зрелые (зато более лаконичные) языки в эту же сторону.
                                                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                                                          +1
                                                                                          Насколько выразительной должна быть система типов, чтобы полностью избавится от юнит-тестов?

                                                                                          Недавно была хорошая статья. Мсье 0xd34df00d знает толк :)

                                                                                            +1

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


                                                                                            Соответствующие языки изобрели где-то от 30 до 50 лет назад (и это не хаскель).

                                                                                              0

                                                                                              Знал что вы тут появитесь :)
                                                                                              Про языки с зависимыми типами я знаю, и трудно утверждать, что их можно широко использовать "для замены юнит-тестов".
                                                                                              А уж "более коротким и удобным путем" их использование назвать точно нельзя. Надеюсь, в светлом будущем все будет иначе.

                                                                                            +6
                                                                                            По вашему мнению, кроме ошибок связанных с динамической типизацией, больше ничего не существует и с помощью TDD не проверяется? Ну там, ошибки в алгоритмах, например? Или я что-то неверно понял?
                                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                +2
                                                                                                Вы меня немного не поняли. Все эти правильный типы это конечно хорошо. Но я вот, из своего опыта, с трудом могу вспомнить хотя бы пару проблем (как следствие => ошибок в продакшене, как следствие — желание/необходимости писать в будущем тесты) возникших из-за «а не передали ли диаметр вместо длины в функцию». Это если не говорить о том, что, ИМХО, в вашем выдуманном примере корректнее делать эту функцию методом класса или передавать в нее объект целиком.
                                                                                                Поэтому я и пытаюсь понять — у меня такой опыт нерелевантный, и во всем мире TDD используют для того чтобы ловить ошибки с неверным типом переменных, или вы с автором комментария немного лукавите, или у нас предметные области настолько разные.
                                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                    –1
                                                                                                    В питон включили строгую типизацию, почему?

                                                                                                    Что за выдумки? Никакой строгой типизации там не включали. Type hints != Строгая типизация

                                                                                                    0
                                                                                                    я теперь категорически против интроспеции / рефлексии, динамических импортов, динамического порождения кода типа new Function() или eval(), и стараюсь статически импортировать все модули
                                                                                                    Я давно это коллегам говорю, а на меня как на припадашного смотрят… видимо, это потому что коллеги — джависты(( сам язык весьма неплох, инфраструктура довольно удобна, но вот люди, занявшие эту сферу… вызывают непреодолимое желание возродить святую инквизицию (ну как минимум ту часть, где в одностороннем порядке приговаривали к публичной медленной и мучительной смерти)

                                                                                                    P.S. а что вы именно под «динамическим порождением кода» подразумеваете? мне вот очень не хватает этой функции в яве/го — зачем использовать рефлексию там, где можно на этапе компиляции нагенерить всё что нужно и сразу собрать в «никак не изменяемый в процессе выполнения» бинарь?!((

                                                                                                    P.P.S. в яве это вроде как можно, но я так и не смог понять как это правильно использовать… идеология настолько кривая, что никто и не пытается этим пользоваться — все юзают рефлекшины(( В го прикрутили сторонний *как-его-там-который-на-сях-используют*, но это выглядит малость убого: ИМХО кодогенерация должна являться частью языка (и, следовательно, компилятора), чтобы лаконично списываться в основной код и не нарушать «бритву оккама» (аналогия: сделать кофеварку с функцией капучинатора рациональнее, чем делать капучинатор отделльно ввиду того, что больше половины функционала у них дублируются)

                                                                                                    P.P.P.S. если не секрет — зачем вам понадобилось пилить свою СУБД? вопрос дружеский — я сам член гильдии велосипедостроителей))
                                                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                        0
                                                                                                        Ааа, вы про генерацию кода в рантайме… а я-то имел в виду на этапе компиляции :)
                                                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                            0
                                                                                                            и зачем тогда кодоген?
                                                                                                            В яве? Ну как минимум чтобы отлаживать было проще. Спринговая депенденси инжешин вызывает у меня изжогу (не от хорошей жизни я перешёл на яву)
                                                                                                            А вообще я больше имел в виду что оно нужно языкам без VM, типо Go/D — я это, скорее, как саму идею рассматриваю, нежели конкретную реализацию, которая «нужна здесь и сейчас»
                                                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                                              +1
                                                                                              А как типизацией проверить правильность функции вычисления площади круга?
                                                                                                0
                                                                                                Сформулировать в типах зависимость входных данных от выходных. Да, это де-факто означает запись всё той же формулы в типах.
                                                                                                  +1

                                                                                                  то есть программу два раза написать.
                                                                                                  при этом примитивные задачи вроде "площадь круга" или "разворот списка" выливаются в статьи с доказательствами, леммами и количеством кода в разы большем чем обычно требуется с учетом ТДД


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


                                                                                                  а ведь еще и сложные задачи программить приходится!

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

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

                                                                                                    Возьмите какой-нибудь действительно нетривиальный для тестирования случай, скажем, ГСЧ — и попробуйте обосновать, что написание тестов для этого как-то отлично от «программу два раза писать». Вернее, даже две разные программы, что еще сложнее.
                                                                                                      +1
                                                                                                      Писать тесты — это тоже «программу два раза писать»,

                                                                                                      нет. писать тесты — это писать две программы: основную и тестирующую


                                                                                                      а не один и тот же код два раза


                                                                                                      и типы покрывают далеко не всё что покрывают тесты. отсюда и скандалы по поводу "не буду больше писать для вас http-сервер".


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


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


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


                                                                                                      Возьмите какой-нибудь действительно нетривиальный для тестирования случай, скажем, ГСЧ — и попробуйте обосновать, что написание тестов для этого как-то отлично от «программу два раза писать».

                                                                                                      ГСЧ — редкая задача.


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


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


                                                                                                      а ГСЧ… жесткий "С" в этой аббривеатуре нужен мало кому. крипте. в 99% случаев достаточно внешнего ГСЧ и программист не занимается такими вещами.
                                                                                                      и даже если займётся — с тестами он её решит быстрее, пусть и с вероятностью, а не доказательством успеха.


                                                                                                      как-то так

                                                                                                        +3
                                                                                                        нет. писать тесты — это писать две программы: основную и тестирующую

                                                                                                        а не один и тот же код два раза

                                                                                                        Это еще хуже с точки зрения временных затрат.

                                                                                                        типами можно заменить самые примитивные тесты

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

                                                                                                        Про http сервер вам всё в более других комментариях уже объясняли, жаль, что вместо продуктивной беседы вы спрятались в домик и начали по кругу спорить о частностях.

                                                                                                        В общем виде юниттестов практически не бывает в реально жизни. Большинство тестов в той или иной мере интеграционные.

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

                                                                                                        ГСЧ — редкая задача.

                                                                                                        Http-сервер — редкая задача.
                                                                                                          0
                                                                                                          Это еще хуже с точки зрения временных затрат.

                                                                                                          только для очень маленьких проектов или проектов на начальном этапе.


                                                                                                          как только в проекте становится более 500 строк кода — временные затраты на его развитие с TDD остаются теми же, без TDD продолжают расти экспоненциально


                                                                                                          Про http сервер вам всё в более других комментариях уже объясняли, жаль, что вместо продуктивной беседы вы спрятались в домик и начали по кругу спорить о частностях.

                                                                                                          http сервер — простая задача.
                                                                                                          почему простая


                                                                                                          1. потому что средний джун справится
                                                                                                          2. потому что спецификация не меняется во времени

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

                                                                                                          просто термин "юнит тест" очень размытый.
                                                                                                          я же привёл пример этого размытия.


                                                                                                          если говорить о тестировании именно одного юнита (модуля/функции) то это юниттест
                                                                                                          но если он под собой ходит куда-то в более другие функции, БД, сервисы — это уже интеграционный (в той или иной степени) тест


                                                                                                          и грань очень зыбка


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

                                                                                                            +6
                                                                                                            как только в проекте становится более 500 строк кода — временные затраты на его развитие с TDD остаются теми же, без TDD продолжают расти экспоненциально

                                                                                                            Мой практический опыт работы с очень большими проектами, существовавшими без единого теста — говорит о том, что вы заблуждаетесь.
                                                                                                            Проект с автотестами развивать действительно дешевле (экономия на QA), но «экспоненциальные затраты», тем более временные — сказки апологетов незыблемости тестов.

                                                                                                            http сервер — простая задача.

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

                                                                                                            просто термин «юнит тест» очень размытый.

                                                                                                            Да нет, крайне конкретный. Как и большинство терминов. Размытый он только в вашей картине мироздания, другие люди делают моки и не называют тесты без моков юнит-тестами.
                                                                                                              0
                                                                                                              Проект с автотестами развивать действительно дешевле (экономия на QA), но «экспоненциальные затраты», тем более временные — сказки апологетов незыблемости тестов.

                                                                                                              они не экспоненциальные — пока разработчик у проекта один или двое.


                                                                                                              и то, они кажутся не экспоненциальными.
                                                                                                              на самом деле там чистая экспонента.


                                                                                                              кстати про большие проекты и сложность был очень красивый доклад на одном из РИТ++ лет 10 назад… сейчас найду....


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


                                                                                                                0

                                                                                                                Спасибо за видео!

                                                                                                              0
                                                                                                              как только в проекте становится более 500 строк кода — временные затраты на его развитие с TDD остаются теми же, без TDD продолжают расти экспоненциально

                                                                                                              Как только в проекте становится более 100 строк кода — временные затраты на его развитие с TDD [Type-driven development] остаются теми же, без TDD продолжают расти экспоненциально.


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

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


                                                                                                              Хотя, наверное, действительно, если писать перекладыватели жсонов из одного сокета в другой, то это всё и не видно.

                                                                                                                +1
                                                                                                                TDD [Type-driven development]

                                                                                                                с этим принципом не смогли простой http сервер написать.


                                                                                                                https://habr.com/ru/post/484436/


                                                                                                                так что эта Ваша переписанная на свой лад моя цитата — из серии анекдота "и Вы рассказывайте"

                                                                                                                  0
                                                                                                                  с этим принципом не смогли простой http сервер написать.

                                                                                                                  Хватит FUD распространять. Один конкретный чувак не смог выпилить из одного конкретного (своего) кода весь unsafe и при этом не смог игнорировать критику.


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

                                                                                                                    –1
                                                                                                                    Хватит FUD распространять. Один конкретный чувак не смог выпилить из одного конкретного (своего) кода весь unsafe и при этом не смог игнорировать критику.

                                                                                                                    не один чувак, а НИКТО не может
                                                                                                                    уже в простых задачах — куча мест появляется где не выпилить unsafe
                                                                                                                    а что говорить о сложных?


                                                                                                                    PS: в этом месте где-то просыпается Райс и долбает растомана своей теоремой!

                                                                                                                      0
                                                                                                                      не один чувак, а НИКТО не может

                                                                                                                      Не существует серверов, где unsafe используется не только для небезопасных примитивов вроде дёрганья ядра ОС?


                                                                                                                      PS: в этом месте где-то просыпается Райс и долбает растомана своей теоремой!

                                                                                                                      А, вы так эту теорему и не поняли. Ну, увы, что поделать. Пишите тесты.

                                                                                                                  0
                                                                                                                  Хотя, наверное, действительно, если писать перекладыватели жсонов из одного сокета в другой, то это всё и не видно.

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

                                                                                                                    +1

                                                                                                                    Будем считать, что мне очень повезло.

                                                                                                                      +1

                                                                                                                      дык радуйтесь


                                                                                                                      я ~15 лет с большим удовольствием проработал в НИИ. что мы только не делали. и в космосе есть вещи что мы делали и под землёй.
                                                                                                                      а потом пришлось уйти и заняться банальщиной.
                                                                                                                      json из сокета в сокет переложить.


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


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


                                                                                                                      Вам именно повезло!

                                                                                                              0
                                                                                                              нет. писать тесты — это писать две программы: основную и тестирующую

                                                                                                              а не один и тот же код два раза

                                                                                                              Так и в типах вы не делаете один и тот же код два раза, а пишете два разных кода.


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

                                                                                                              Осталось про это рассказать апологетам TDD.


                                                                                                              ГСЧ — редкая задача.
                                                                                                              а автоматизация например процесса на складе "взяли с полки и переложили на другую" — рядовая.

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

                                                                                                                0
                                                                                                                Осталось про это рассказать апологетам TDD.

                                                                                                                а аппологеты TDD как раз не держатся из последних сил за юниттесты
                                                                                                                а делают всякие тесты и интеграционные и системные


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

                                                                                                                в apt репозитарии сейчас по моему больше 100 тыс программ.
                                                                                                                сколько из них содержит внутри ГСЧ?
                                                                                                                пять? или даже семь?

                                                                                                                  +1
                                                                                                                  а аппологеты TDD как раз не держатся из последних сил за юниттесты

                                                                                                                  То есть, перед тем, как написать функцию, они аж интеграционный тест выписывают, который эту функцию будет тестировать?


                                                                                                                  в apt репозитарии сейчас по моему больше 100 тыс программ.
                                                                                                                  сколько из них содержит внутри ГСЧ?

                                                                                                                  А сколько из них автоматизируют процессы на складе?

                                                                                                                    0
                                                                                                                    То есть, перед тем, как написать функцию, они аж интеграционный тест выписывают, который эту функцию будет тестировать?

                                                                                                                    зачастую — да

                                                                                                                      +2

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

                                                                                                                        0

                                                                                                                        Вы опять путаете примитивные задачи с простыми.


                                                                                                                        в примитивной задаче — интеграционный тест конечно не нужен.
                                                                                                                        а вот если бы Вы этот массив бы ещё попутно держали бы в БД, поскольку его размер существенно превышает размеры RAM, то Вам бы пришлось писать именно интеграционный тест


                                                                                                                        и кстати, Ваш алгоритм что вы вчера там "усп