2012-03-05 2 views
2

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

Таким образом, выход может составлять 20 строк.

Как бы вы пишете тест юнита? Запустил бы синтаксический анализатор, проверив результат вручную, и если это будет правильно, отбросьте результат в модульный тест в качестве правильного ответа?

Или это просто безумие, и мне нужно сделать что-то по-другому?

ответ

4

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

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

Попробуйте разбить внутренние работы на более мелкие методы и протестировать их. Попробуйте проверить результат с меньшими результатами (например, если вход A приводит к выходу Y, а вход B приводит к выходу Z, тогда напишите тест на то, будет ли вход AB выводиться на выходе YZ или каким бы ни был соответствующий результат).

+0

Парсер рекурсивный спуск.Поэтому, если parse() вызывает a() b() и c(), вы рекомендуете, чтобы я вместо этого предпочитал тестировать эти методы, или то, что они вызывают и т. Д. И т. Д. Я не согласен с этим. Но что тогда будет более высоким уровнем тестирования, где я, конечно, тестирую публичные интерфейсы? –

2

Это совершенно правильный тест, но не обязательно единичный тест. Это связано с тем, что он является интеграционным тестом или регрессионным тестом:

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

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

  1. Если вы не будете осторожны, ваши тесты окажутся довольно хрупкими. Например, ваш вывод может содержать неожиданные символы (пробелы, cr/lf и кодирование - это особая проблема, если вы смешиваете машины unix и windows). Это делает тестирование немного сложнее, потому что вам нужно «очистить» результат анализатора.

  2. Это боль, чтобы иметь 20 строк текста в вашем классе junit java вместе с входом. Таким образом, вы столкнулись с выбором наличия текста в java, помещением их в отдельный файл. В большинстве случаев я считаю, что отдельные файлы проще управлять, а методы - это одна строка, которая берет файл, обрабатывает его и сравнивает его с ссылочным файлом.

  3. Поскольку вы проводите интеграционные тесты, было бы труднее определить причину, если у вас есть неудачный тест.

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

Смежные вопросы