Я начинаю использовать common test
как свою тестовую структуру в erlang.Как проверить обработку ошибок в общем тесте?
Предположим, что у меня есть функция, которую я ожидаю принять только положительные числа, и она должна ударить в любом другом случае.
positive_number(X) when > 0 -> {positive, X}.
и я хочу, чтобы проверить, что
positive_number(-5).
не будет успешно завершена.
Как проверить это поведение? В других языках я бы сказал, что тестовый пример ожидает некоторой ошибки или исключения и терпит неудачу, если он работает под тестом, не вызывает ошибок для недопустимого недопустимого параметра. Как это сделать с общим тестом?
Update:
я могу заставить его работать с
test_credit_invalid_input(_) ->
InvalidArgument = -1,
try mypackage:positive_number(InvalidArgument) of
_ -> ct:fail(not_failing_as_expected)
catch
error:function_clause -> ok
end.
, но я думаю, что это слишком многословным, я хотел бы что-то вроде:
assert_error(mypackage:positive_number, [-1], error:function_clause)
I при условии, что общий тест имеет это в некотором месте, и мне не хватает надлежащего знания структуры, которая заставляет меня принимать такое подробное решение.
Update: Вдохновленный ответ Майкла я создал следующую функцию:
assert_fail(Fun, Args, ExceptionType, ExceptionValue, Reason) ->
try apply(Fun, Args) of
_ -> ct:fail(Reason)
catch
ExceptionType:ExceptionValue -> ok
end.
и мой тест стал:
test_credit_invalid_input(_) ->
InvalidArgument = -1,
assert_fail(fun mypackage:positive_number/1,
[InvalidArgument],
error,
function_clause,
failed_to_catch_invalid_argument).
, но я думаю, что он просто работает, потому что это немного более читаемым, чтобы иметь вызов assert_fail
, чем имеющий try....catch
в каждом тестовом случае.
Я все еще думаю, что в Common Test должна существовать какая-то лучшая реализация, IMO - это уродливое повторение, чтобы этот тестовый шаблон неоднократно реализовывался в каждом проекте.
Это решение работает, но дает более запутанное сообщение об ошибке при неудачах тестирования моего предыдущего решения. Мне понравилась идея вспомогательной функции. –
@JonasFagundes Вы можете включить макросы EUnit и использовать их только под общим тестом. –
@JonasFagundes Действительно ли запутанное сообщение об ошибке имеет значение? Я знаю, что трассировка стека Erlang не особенно хороша, но главным образом потому, что Erlang функционирует, вы будете знать, какая функция не удалась, где и почему из нее ... где, как если бы вы использовали try catch, как в вашем вопросе, вы фактически выбрасываете все эту информацию и заменить ее «not_failing_as_expected». Я понимаю ваше желание сделать это до некоторой степени, но я думаю, что это действительно неправильный путь. Я добавлю это к ответу, чтобы было ясно, не могу сделать это в комментарии на самом деле. – Michael