netch80: (Default)
[personal profile] netch80
В обоснование test-drived design (TDD) постоянно приводят соображения, что без предварительного теста невозможно понять, рабочий ли тест вообще. Например, тут, дословно: "Сначала тест должен упасть. Это тест теста. Если тест не упал, я не могу быть уверен, что он упадет, когда надо."

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

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

Например, если я проверяю в тесте приход определённого сообщения на шину, то очевидным вариантом сломать тест является не подписаться на шину или подписаться не на тот тип сообщения. Если в настройках должно стоять, какой выходной тег, то вариант поломки - заменить генерируемый тег. Если я проверяю, что выключение объекта привело к нотификации "ой, он выключился", то мы "забываем" выключить эмулятор объекта. И так далее. Для Unix я проверяю это установкой TEST_OPTIONS в окружении перед основным make теста, для других сред потребуется выбрать что-то соответствующее по вкусу.

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

Как читающие это уже поняли, я против TDD как тотального подхода, потому что TDD как подход - фактически обман, когда административные тезисы выдаются за технические. Требование "покажите, что ваш тест действительно работает" используется для маскировки требования не похерить само построение теста по обоснованиям недостатка времени, отсутствия необходимости проверять и тому подобному, а также для того, чтобы менеджмент получил формальные признаки готовности кода. Но так как всё покрыть тестами нельзя в принципе, (а 5% тестов покрывают 95% ошибок), то TDD изначально формально и практически некорректен. А вот behavior-driven development (тут или тут) при правильном подходе уже этим не страдает, но не по внутренним причинам, а потому, что определение "поведения" ограничивает тем, что действительно важно (а не несущественные особенности реализации).

Date: 2011-02-04 07:57 am (UTC)
vitus_wagner: My photo 2005 (Default)
From: [personal profile] vitus_wagner
На самом деле любой тотальный подход - это плохо. Ибо суха теория, мой друг, а древо жизни пышно зелениеет.

Date: 2011-02-04 08:32 am (UTC)
From: [identity profile] gds.livejournal.com
к счастью, у меня были похожие мысли о TDD, только не так грамотно сформулированные. Но, по итогу, TDD не использую, и теперь чётко вижу, почему это правильно.

Profile

netch80: (Default)
netch80

January 2026

S M T W T F S
    1 23
45678910
11121314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 2nd, 2026 06:51 pm
Powered by Dreamwidth Studios