没有花费精力实际克隆JUnit或其他东西,我正在抛出一些实用程序函数来帮助测试一些SML代码。我确实知道QCheck,但它也不能做到这一点,也不是我想要的。 (但如果你知道另一个SML自动测试框架,请说出来。)
我希望能够断言某些函数会抛出异常,例如,给定一个函数
fun broken x = raise Fail
我希望能够写出类似
的内容throws ("ERROR: function is not broken enough!", fn () => broken 1, Fail)
如果给定的函数不引发预期的异常,则抛出错误。
我尝试编写类似throws
的{{1}}函数,如下所示:
(string * exn * (unit -> unit)) -> unit
但这会产生一堆编译时错误,显然是因为ML 没有定义异常的平等:
fun throws (msg, e, func) = func ()
handle e' => if e = e'
then ()
else raise ERROR (SOME msg)
作为一种解决方法,我怀疑我可以重用我现有的sexp-tests.sml:54.31-57.49 Error: types of rules don't agree [equality type required]
earlier rule(s): ''Z -> unit
this rule: exn -> 'Y
in rule:
exn => raise exn
sexp-tests.sml:54.31-57.49 Error: handler domain is not exn [equality type required]
handler domain: ''Z
in expression:
func ()
handle
e' => if e = e' then () else raise (ERROR <exp>)
| exn => raise exn
函数:
assert
但它更多的是思考和打字。
那么,有没有办法在SML中编写assert ((broken 1; false) handle Fail => true | _ => false)
函数?
答案 0 :(得分:8)
以下功能应该有效:
exception ERROR of string option;
fun throwError msg = raise ERROR (SOME msg);
fun throws (msg, func, e) =
(func (); throwError msg) handle e' =>
if exnName e = exnName e'
then ()
else raise throwError msg
这使用函数exnName,它将异常的名称作为字符串,并将其用于比较。
更重要的是,它还处理了根本没有抛出异常的情况,并且也给出了错误。
或者,如果您只需要一个布尔值,指示是否抛出了异常,您可以使用:
fun bthrows (func, e) = (func (); false) handle e' => exnName e = exnName e'
请注意,对于Fail的情况,您实际上必须创建一个失败异常的实例,例如:
throws ("ERROR: Oh no!", fn () => test 5, Fail "")
或者,您可以使用例外的名称,以获得更清晰的一般情况:
fun throws (msg, func, e) =
(func (); throwError msg) handle e' =>
if e = exnName e'
then ()
else raise throwError msg
fun bthrows (func, e) = (func (); false) handle e' => e = exnName e'
然后像这样使用它:
throws ("ERROR: Oh no!", fn () => test 5, "Fail")