如何测试已编译的函数?

时间:2019-02-24 17:26:33

标签: common-lisp

我有一个函数do-something和一个函数my-function形式:

(defun my-function ((object object))
  (if (do-something)
    5
    6))

do-somethingmy-functionmy-package包中。

my-package/tests包中,我要执行以下操作:

(deftest "Test my-function"
  (flet ((my-package::do-something ()
           t))
    (assert-is (my-package::my-function) 5))

  (flet ((my-package::do-something ()
           nil))
    (assert-is (my-package::my-function) 6)))

目标是测试my-function的行为是否正确,我想将其保留为一个函数(而不是宏),并且不通过args注入函数。在C语言中,我可能会弄乱链接器。

每次我想运行所有更新的代码和测试时,我都会在REPL中执行以下操作:

(ql:quickload :my-system)
(asdf:test-sytem :my-system/tests)

但是似乎它可以编译my-function,所以即使我在测试文件中的flet函数上执行了do-something,行为也不会改变。

我想以编程方式测试my-function,有没有办法做到这一点?

1 个答案:

答案 0 :(得分:1)

flet(或labels)定义的函数具有词法范围,即。例如,它们仅存在于flet主体中。它不会影响动态环境。

没有对动态重新绑定函数的显式支持,但是您可以使用如下代码:

(defmacro with-rebound-fun ((name args &body fun-body) &body body)
  (let ((saved (gensym)))
    `(let ((,saved (symbol-function ',name)))
       (setf (symbol-function ',name) (lambda ,args ,@fun-body))
       (unwind-protect (progn ,@body)
         (setf (symbol-function ',name) ,saved)))))

虽然这有点骇人听闻,但它可能会破坏一些实现可能会重新定义功能的假设。特别是,该符号可能会携带有关该功能的其他元信息,并且不会被更改。内联原始函数的地方也将不起作用。