Помогут ли модульные тесты Citigroup избежать этой дорогой ошибки?

86

Я читал об этом snafu: ошибка программирования стоит Citigroup $ 7 млн ​​после того, как допустимые транзакции ошибочно принимались за тестовые данные в течение 15 лет .

Когда система была представлена ​​в середине 1990-х годов, программный код отфильтровывал все транзакции, которым были присвоены трехзначные коды ветвей от 089 до 100, и использовал эти префиксы для целей тестирования.

Но в 1998 году компания начала использовать буквенно-цифровые отраслевые коды по мере расширения своего бизнеса. Среди них были коды 10B, 10C и т. Д., Которые система рассматривала как находящиеся в пределах исключенного диапазона, и поэтому их транзакции были удалены из любых отчетов, отправленных в SEC.

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

Кроме того, моей первой реакцией было «Модульные тесты помогли бы здесь» ... но будут ли они?

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

Мэтт Эванс
источник
17
Кажется, они также пропустили интеграционный тест, который проверил количество транзакций, экспортированных в SEC. Если вы создадите функцию экспорта, это будет разумной проверкой.
Люк Франкен
31
Автор статьи, похоже, не разбирается в модульном тестировании. Некоторые утверждения просто нелепы ( «модульные тесты вряд ли протестируют более одной триллионной функциональности любого данного метода» ), другие могут снизить вероятность получения регрессий ( «посмотрите на тесты, которые никогда не заканчивались в течение года, и рассмотрите возможность выбросить их " ). Или предложения типа «превратить модульные тесты в утверждения» , которые должны заменить неудачные тесты для исключений времени выполнения?
Groo
25
@gnat Я не читал внешнюю ссылку, и все же нашел этот вопрос осмысленным
Jeutnarg
23
Что бы это ни стоило, я в значительной степени не согласен со всем в «Почему большинство модульных тестов - отходы». Я бы написал опровержение, но это поле слишком мало, чтобы его содержать.
Роберт Харви

Ответы:

19

Вы действительно спрашиваете: «Помогли ли здесь модульные тесты?», Или вы спрашиваете: «Могли ли здесь помочь какие-либо тесты?».

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

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

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

Я не вижу никакого определения или документации задействованных интерфейсов, но может случиться так, что модульные тесты не могли обнаружить ошибку, потому что модуль не был неисправен . Если подразделению разрешено предполагать, что идентификаторы ветвей состоят только из цифр, и разработчики никогда не принимали решения о том, что должен делать код, если это не так, то они не должнынаписать модульный тест для обеспечения определенного поведения в случае нецифровых идентификаторов, потому что тест отклонил бы гипотетическую допустимую реализацию модуля, который правильно обрабатывал буквенно-цифровые идентификаторы ветвей, и вы обычно не хотите писать модульный тест, который препятствует действительному будущие реализации и расширения. Или, может быть, один документ, написанный 40 лет назад, неявно определил (с помощью некоторого лексикографического диапазона в необработанном EBCDIC, вместо более удобного для человека правила сопоставления), что 10B является идентификатором теста, потому что в действительности он находится между 089 и 100. Но тогда 15 лет назад кто-то решил использовать его в качестве реального идентификатора, поэтому «ошибка» не заключается в блоке, который правильно реализует исходное определение: он заключается в процессе, который не заметил, что 10B определен как тестовый идентификатор и, следовательно, не должен назначаться ветви. То же самое произошло бы в ASCII, если вы определили 089-100 в качестве диапазона тестирования, а затем ввели идентификатор 10 $ или 1,0. Просто так получается, что в EBCDIC цифры идут после букв.

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

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

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

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

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

Стив Джессоп
источник
Утверждения хороши!
3
@nocomprende: как было у Рейгана, «доверяй, но проверяй».
Стив Джессоп
1
Я также собирался сказать "Юнит тесты плохо!" но я думал, что большинство людей упустят ссылку на « Скотный двор» и начнут на самом деле критиковать меня, вместо того, чтобы думать о том, что я говорю (ответные толчки неэффективны), но я этого не говорил. Может быть, человек, который умнее и имеет большую эрудицию, может сделать это.
2
«Все тесты проходят, но некоторые тесты проходят БОЛЬШЕ, чем другие!»
Грэм
1
тестирование это красная сельдь. Эти парни просто не знали, как был определен «код филиала». Это было бы похоже на то, что Почтовое отделение США не знает, что оно изменило определение почтового индекса, когда добавило 4 цифры.
радаробоб
120

Модульные тесты могли бы обнаружить, что коды ветвей 10B и 10C были ошибочно классифицированы как «тестирующие ветви», но я считаю маловероятным, что тесты для этой классификации ветвей были бы достаточно обширными, чтобы уловить эту ошибку.

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

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

Барт ван Инген Шенау
источник
80
+1 Модульные тесты никогда не смогут компенсировать плохие дизайнерские решения (например, тестирование микширования и реальных данных)
Jeutnarg
5
Хотя лучше избегать смешивания тестовых данных с реальными данными, может быть сложно проверить производственную систему, если для этого требуется изменить реальные данные. Например, это плохая идея для проверки банковской системы путем изменения итогов банковских счетов в производстве. Использование диапазонов кода для обозначения значения проблематично. Более явный атрибут записей, вероятно, был бы лучшим выбором.
JimmyJames
4
@ Я думаю, что существует неявное предположение о том, что существует уровень сложности или требование надежности, когда тестирование действующей развернутой производственной системы считается целесообразным или необходимым. (Подумайте, сколько может пойти не так из-за неправильной переменной конфигурации.) Я мог видеть, что это относится к крупной финансовой организации.
jpmc26
4
@ Воу, я не говорю о тестировании. Я говорю о проверке системы. В реальной производственной системе есть много способов, которыми она может потерпеть неудачу, не имея ничего общего с кодом. Если вы запускаете новую банковскую систему в производство, у вас может быть проблема в БД или сети и т. Д., Которая препятствует применению транзакций к учетным записям. Я никогда не работал в банке, но я почти уверен, что ему не стоит начинать изменять реальные счета с помощью фальшивых транзакций. Так что вам остается либо создавать фальшивые аккаунты, либо ждать и молиться.
JimmyJames
12
@JimmyJames В здравоохранении часто периодически копируют производственную базу данных в тестовую среду, чтобы выполнить тестирование данных, максимально приближенных к реальным; Я думаю, что банк может сделать то же самое.
dj18
75

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

Бизнес-правила изменились.

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

Так что нет, юнит тесты не поймали бы это.

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

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

gnasher729
источник
2
Возможно ли иметь разные команды, в которых одна работает над кодом, а другая - над «модульными» тестами? Как это вообще возможно? ... Я все время делаю рефакторинг своего кода.
Серхио
2
@ Sergio с одной точки зрения: рефакторинг изменений внутренних компонентов при сохранении поведения - поэтому, если тест написан таким образом, что тестирует поведение, не полагаясь на внутренние компоненты, он не нуждается в обновлении.
Daenyth
1
Я видел это много раз. Программное обеспечение работает без каких-либо претензий, а затем внезапно пользователи взрываются жалобами на то, что оно больше не работает и постепенно перестало работать в течение многих лет. Вот что происходит, когда вы решаете пойти и изменить свои внутренние процедуры, не следуя стандартному процессу уведомления ...
Брайан Кноблаух
42
«Бизнес-правила изменились» - критическое замечание. Модульные тесты подтверждают, что вы реализовали логику, которую, как вы думали, реализовали , а не то, что ваша логика была правильной .
Райан Кавано
5
Если я прав в отношении того, что произошло, вряд ли будут написаны юнит-тесты, чтобы поймать это. Основным принципом выбора тестов является проверка некоторых «хороших» случаев, некоторых «плохих» случаев и случаев, заключающих в себе любые границы. В этом случае вы должны проверить «099», «100» и «101». Так как «10B» был покрыт тестами «отклонить не числа» в старой системе, и больше 101 (и это подтверждается тестированием) в новой системе, нет никаких причин для его тестирования - кроме того, что в EBCDIC, "10B" сортирует между "099" и "100".
Марк
29

Нет. Это одна из больших проблем с модульным тестированием: они вводят вас в заблуждение о безопасности.

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

Мейсон Уилер
источник
17
Мой отец обычно спрашивал меня: почему ты не подумал о том, о чем не думал? (Только он обычно вводил в заблуждение, говоря: «Если ты не знаешь, спроси !»). Но откуда мне знать, что я не знаю?
7
«Это означает, что части вашего проекта, о которых вы сознательно думали и писали тесты, работают так, как вы сознательно думали, что они будут». Совершенно верно. Эта информация неоценима, если вы проводите рефакторинг или если что-то в системе меняется, что нарушает ваши предположения. Разработчики, которые погружены в ложное чувство безопасности, просто не понимают ограничений модульного тестирования, но это не делает модульное тестирование бесполезным инструментом.
Роберт Харви
12
@MasonWheeler: Как и вы, автор считает, что модульное тестирование должно как-то доказать, что ваша программа работает. Это не так. Позвольте мне повторить это: модульное тестирование не доказывает, что ваша программа работает. Модульное тестирование доказывает, что ваши методы выполняют ваш контракт на тестирование, и это все, что он делает. Остальная часть бумаги падает, потому что она опирается на эту единственную неверную предпосылку.
Роберт Харви
5
Естественно, разработчики, которые имеют такое ложное убеждение, будут разочарованы, когда модульное тестирование полностью провалит их, но это вина разработчика, а не модульного тестирования, и это не умаляет истинную ценность, которую обеспечивает модульное тестирование.
Роберт Харви
5
o_O @ твое первое предложение. Модульные тесты дают вам ложное чувство безопасности, а кодирование, как если бы вы держали руки на руле, дает ложное чувство безопасности во время вождения.
Джехлин
10

Нет, не обязательно

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

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

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

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

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

gbjbaanb
источник
Пятно на. И главная (единственная?) Проблема с юнит-тестами. Спасло меня формулировка моего собственного ответа, поскольку я сказал бы точно то же самое (но, вероятно, хуже!) :)
Гонки Легкости на орбите
8

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

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

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

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

Жюль
источник
1
Я думаю, что более нормально называть это тестирование на основе свойств, и, конечно, с такой же вероятностью можно написать тест на основе свойств, который все равно будет проходить с учетом этого изменения (хотя я думаю, что вы с большей вероятностью напишите тест, который может его найти)
JK.
5

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

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

Вы можете только разумно обнаружить эту проблему с помощью:

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

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

Класс Скелетон
источник
2

Утверждение, встроенное во время выполнения, могло бы помочь; например:

  1. Создать функцию как bool isTestOnly(string branchCode) { ... }
  2. Используйте эту функцию, чтобы решить, какие отчеты отфильтровать
  3. Повторно используйте эту функцию в утверждении, в коде создания ветви, чтобы проверить или подтвердить, что ветвь не (не может быть) создана с использованием этого типа кода ветви‼
  4. Включите это утверждение в режиме реального времени (а не «оптимизируйте, за исключением версии кода, предназначенной только для отладки»)‼

Смотрите также:

ChrisW
источник
2

Вывод из этого - Fail Fast .

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

  • 089 - 100 => тестовая ветвь
  • 10B, 10C => тестовая ветвь
  • <088 => предположительно реальные ветви
  • > 100 => предположительно реальные ветви

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

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

bool IsTest(string strPrefix) {
    int iPrefix;
    if(int.TryParse(strPrefix, out iPrefix))
        return iPrefix >= 89 && iPrefix <= 100;
    return true; //here is the problem
}

На английском языке, если строка является числом и находится между 89 и 100, это тест. Если это не число, это тест. В противном случае это не тест.

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

assert.isFalse(IsTest("088"))
assert.isTrue(IsTest("089"))
assert.isTrue(IsTest("095"))
assert.isTrue(IsTest("100"))
assert.isFalse(IsTest("101"))
assert.isTrue(IsTest("10B")) // <--- business rule change

Модульный тест показывает, что «10B» следует рассматривать как тестовую ветвь. Пользователь @ gnasher729 выше говорит, что изменились бизнес-правила, и это показывает последнее утверждение выше. В какой-то момент это утверждение должно было переключиться на isFalse, но этого не произошло. Модульные тесты запускаются во время разработки и сборки, но потом ни в коем случае.


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

// Alternative A
bool TryGetIsTest(string strPrefix, out bool isTest) {
    int iPrefix;
    if(int.TryParse(strPrefix, out iPrefix)) {
        isTest = iPrefix >= 89 && iPrefix <= 100;
        return true;
    }
    isTest = true; //this is just some value that won't be read
    return false;
}

Для тех, кто не знает C #, возвращаемое значение указывает, смог ли код проанализировать префикс из заданной строки. Если возвращаемое значение равно true, вызывающий код может использовать переменную isTest out, чтобы проверить, является ли префикс ветви префиксом теста. Если возвращаемое значение равно false, вызывающий код должен сообщить, что данный префикс не ожидается, а переменная isTest out не имеет смысла и должна игнорироваться.

Если вы согласны с исключениями, вы можете сделать это:

// Alternative B
bool IsTest(string strPrefix) {
    int iPrefix = int.Parse(strPrefix);
    return iPrefix >= 89 && iPrefix <= 100;
}

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

user2023861
источник
1

Так много ответов и даже ни одной цитаты Дейкстры:

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

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

BЈовић
источник
-1

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

Учтите, вы написали bool IsTestData(string branchCode)функцию.

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

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

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

Ewan
источник
1
Это не помогло бы - функция не была изменена, и тест не начал бы терпеть неудачу, учитывая те же самые тестовые данные. Кто-то должен был бы подумать об изменении теста, чтобы он не прошел, но если бы он подумал об этом, он, вероятно, подумал бы и об изменении функции.
Халк
(Или, может быть, я что-то упускаю, так как я не уверен, что вы имеете в виду под «проверкой параметров»)
Халк
Функция будет вынуждена генерировать исключение для нецелочисленных строк, чтобы пройти простой модульный тест случая края. Следовательно, производственный код выдаст ошибку, если вы начнете использовать буквенно-цифровые коды веток без специального программирования для них
Ewan
Но разве функция не использовала бы какую-либо функцию IsValidBranchCodeдля выполнения этой проверки? И эта функция, вероятно, была бы изменена без необходимости изменять IsTestData? Так что, если вы тестируете только «хорошие данные», тест не помог бы. Для того, чтобы начать сбои, тест граничного случая должен был бы включать в себя некоторый теперь действующий код ветвления (а не просто некоторые еще недействительные).
Халк
1
Если проверка находится в IsValidCode, так что функция проходит без своей собственной явной проверки, то да, ее можно пропустить, но тогда у нас будет дополнительный набор еще большего количества тестов, фиктивных Валидаторов и т. Д., Даже больше шансов для конкретного «это Тестовые числа »
Эван