Exception 在SML中,如何断言抛出了特定的异常?

Exception 在SML中,如何断言抛出了特定的异常?,exception,testing,equality,sml,Exception,Testing,Equality,Sml,在不进行实际克隆JUnit之类的工作的情况下,我集成了一些实用函数来帮助测试一些SML代码。我确实知道QCheck,但它也不能做这一件事,也不是我通常想要的。(但如果您知道另一个SML自动化测试框架,请大声说出来。) 我希望能够断言某些函数将抛出异常,例如,给定一个函数 fun broken x = raise Fail 我希望能写一些像这样的东西 throws ("ERROR: function is not broken enough!", fn () => broken 1, Fa

在不进行实际克隆JUnit之类的工作的情况下,我集成了一些实用函数来帮助测试一些SML代码。我确实知道QCheck,但它也不能做这一件事,也不是我通常想要的。(但如果您知道另一个SML自动化测试框架,请大声说出来。)

我希望能够断言某些函数将抛出异常,例如,给定一个函数

fun broken x = raise Fail
我希望能写一些像这样的东西

throws ("ERROR: function is not broken enough!", fn () => broken 1, Fail)
如果给定的函数没有引发预期的异常,则让它抛出一个错误

我试图编写一个类型为
(string*exn*(unit->unit))->unit的
throws
函数,如下所示:

  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
但这需要更多的思考和打字


那么,有没有办法在SML中编写
抛出
函数?

以下函数应该可以工作:

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
这将使用函数,该函数将异常的名称作为字符串获取,并将其用于比较

更重要的是,它还处理根本不引发异常的情况,并给出了一个错误

或者,如果您只需要一个布尔值,指示是否引发了异常,则可以使用:

fun bthrows (func, e) = (func (); false) handle e' => exnName e = exnName e'
请注意,对于失败的情况,实际上必须创建失败异常的实例,例如:

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")
throws ("ERROR: Oh no!", fn () => test 5, "Fail")