Должны ли быть модульные тесты для сложных регулярных выражений?

34

Должен ли я написать модульные тесты для сложных регулярных выражений в моем приложении?

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

РЕДАКТИРОВАТЬ:

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

Но в качестве внутренних компонентов регулярные выражения имеют несколько особых характеристик:

  1. Одиночное регулярное выражение может быть действительно сложным, не будучи отдельным модулем.
  2. Регулярные выражения отображают входные данные без каких-либо побочных эффектов и, следовательно, действительно легко проверить отдельно.
Lii
источник
12
«сами они редко являются частью интерфейса какого-либо устройства». - если ваши классы имеют интересный код, скрытый глубоко под интерфейсом, разбейте ваши классы. Это пример того, как размышления о Тесс могут улучшить дизайн.
Натан Купер
3
Тот же вопрос в более общем виде: какие внутренние компоненты должны быть проверены модулем? См. Programmers.stackexchange.com/questions/16732/…
Док Браун
Сорта связаны, см. Regex101. У них есть раздел для написания модульных тестов для вашего регулярного выражения. Например: regex101.com/r/tR3mJ2/2
Дэвид говорит восстановить Monica
3
Отказ от ответственности - этот комментарий является моим скромным мнением: 1 Прежде всего, я считаю, что сложные регулярные выражения являются чистым злом - также см. Blog.codinghorror.com/… 2 Реальная ценность тестирования таких выражений возникает, когда вы тестируете их на большой базе данных реальных данные blog.codinghorror.com/testing-with-the-force 3 У меня странное ощущение, что эти тесты не являются единичными тестами в точности
Борис Треухов

Ответы:

101

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

JacquesB
источник
25
+1, хотя если регулярное выражение является достаточно сложным , что это вопрос, то, вероятно , имеет смысл , чтобы переместить его в «обертке» блок с соответствующими методами ( isValid, parse, tryParse, или этажеркой, в зависимости , как именно он используется), так что клиентский код не должен знать, что он в настоящее время реализован с использованием регулярных выражений. Затем модуль-обертка будет иметь подробные тесты, которые - опять же - не должны будут знать текущую реализацию. Эти тесты, конечно, де-факто тестируют регулярное выражение, но не зависят от реализации.
Руах
1
Reg ex - это программа, хотя и на специализированном и очень лаконичном языке. Таким образом, тестирование подходит для нетривиальных выражений ... И, конечно, должен быть проверен код, который вызывает выражение, что может неявно проверять зарезервированное.
Кешлам
6
@ruakh Хорошо сказано. Преимущество класса-обертки для регулярного выражения в том, что вы можете аккуратно заменить его обычным кодом, если это станет необходимым. Код со сложным вводом / выводом всегда должен проходить модульное тестирование, потому что без него очень трудно отлаживаться. Если вам нужно обратиться к документации, чтобы понять эффекты кода, он должен иметь модульные тесты. Если это просто быстрое отображение 1: 1, как преобразование типов, то проблем нет. Регулярные выражения преодолевают этот момент, требуя документов очень быстро.
Aaron3468
4
@Lii: регулярные выражения не заслуживают особого отношения. В этом случае регулярное выражение является единицей, поэтому мы проверяем ее.
JacquesB
1
@ruakh Я собирался написать ответ на этот счет. Я согласен, что использование регулярных выражений является деталью реализации. Важно то, что вещи проверяются, когда они должны, и не проверяются, когда они должны. Проверьте FooValidatorего входы и выходы, и вы не будете беспокоиться о том, как это делается. ++
RubberDuck
21

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

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

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

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

изогнутый
источник
3

Регулярные выражения - это код вместе с остальной частью вашего приложения. Вы должны проверить, что код в целом выполняет то, что вы ожидаете. Это имеет несколько целей:

  • Тестовая документация. Это ясно демонстрирует, что вам нужно сделать код. Если это проверено, это важно.
  • Будущие сопровождающие могут быть уверены, что, если они изменят его, тесты будут гарантировать, что поведение не изменится.

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

Турбьерн Равн Андерсен
источник
1

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

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

Сара
источник
3
Эмпирическое правило, которое я осознал; если мне нужны документы для написания и проверки кода, то мне понадобится модульное тестирование. Они избавили меня от многих головных болей, отлова нулевых указателей, отсутствия типов и неправильного вывода. Они также дают конечному пользователю возможность восстанавливать ваш код по спецификации с минимальными усилиями, когда он неизбежно ломается.
Aaron3468,
-1

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

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

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

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

Кристиаан
источник
« Когда вы меняете кусок SQL, вы, вероятно, запускаете его через некоторый клиент SQL вручную, чтобы посмотреть, дает ли он то, что вы ожидаете». Но этот вид ответа на вопрос по-другому ... Если мне нужно или я думаю, что это полезно для проверим регулярные выражения вручную, тогда я должен вместо этого сделать модульный тест. Именно это и делает решение сложным!
Лий
Это действительно зависит. То, что вы хотите, чтобы ваши юнит-тесты - это способность вносить изменения. Как часто вы меняете конкретное регулярное выражение? Если ответ часто, то непременно создайте для него тест.
Кристиан
8
При прочих равных условиях лучше иметь автоматический тест, чем «ручной тест».
Роберт Харви
1
Почему бы вам не протестировать регулярное выражение с помощью автоматизации?
Тони Эннис
1
Это часть метода, и все, что я пытался сказать, это то, что нет необходимости специально проверять регулярное выражение, если вы уже тестировали этот метод. Но если вы это сделаете, вам, вероятно, лучше выделить регулярное выражение в отдельную функцию, которую вы тестируете изолированно.
Кристиан
-5

Если вам нужно спросить, ответ - да.

Предположим, что приходит какой-то FNG и думает, что он может «улучшить» ваше регулярное выражение. Теперь он FNG, поэтому автоматически идиот. Именно тот человек, который никогда не должен трогать ваш драгоценный код ни при каких обстоятельствах! Но, возможно, он имеет отношение к PHB или что-то, так что вы ничего не можете сделать.

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

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

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

Остин Гастингс
источник
3
что такое ФНГ? Это не кажется мне плохим ответом, но отсутствует определение для FNG (googlin для него просто дает результаты, которые не связаны, так что, возможно, этот ответ был просто отклонен из-за FNG?)
GameDeveloper
1
Я подозреваю, что Google взял вас в нужное место. ;-) ( en.wikipedia.org/wiki/FNG_syndrome )
Остин Гастингс
Если вы не абсолютный гений программирования, найдутся более опытные программисты, которые будут думать о том, что вы делаете, как если бы вы смотрели на нового парня. Вы можете подумать о том, чтобы быть более скромным.
Турбьерн Равн Андерсен