1

所以,我试图熟悉 ERT,Emacs 中的单元测试包。我想测试使用gensym. 我可以确保 gensym 生成具有相同名称的符号,但它们不是相同的符号,这会导致失败。以下是为您提供更好主意的代码:

(ert-deftest i-test-repreat ()
  "Tests the expansion of i-iterate macro, repeat driver."
  (require 'i-iterate)
  (should
   (equal
    (macroexpand '(++ (repeat 100) (message "")))
    '(let* ((--0 0)) ;; `--0' is a result of a custom-made `gensym'
       (while (< --0 100)
         (incf --0)
         (message "")) nil))))

这是失败消息:

(list-elt 1
  (list-elt 0
    (list-elt 0
      (different-symbols-with-the-same-name --0 --0))))

很公平,它是一个不同的符号,但预计会如此。我怎样才能让它成功?

编辑

到目前为止,这是我能想到的:

(defun i/test-equals-ignore-gensym (a b)
  "Tests trees A and B for equality, but considers symbols
equal if their names are equal (this allows symbols generated
by `i-gensym' to pass)."
  (or (equal a b)
      (cond
       ((and (null a) (null b)) t)
       ((and (consp a) (consp b))
        (and (i/test-equals-ignore-gensym (car a) (car b))
             (i/test-equals-ignore-gensym (cdr a) (cdr b))))
       ((and (symbolp a) (symbolp b))
        (string= (symbol-name a) (symbol-name b)))
       ((and (atom a) (atom b)) (eql a b))
       (t nil))))

(defun i/test-explainer-equal (a b)
  "Explains why `i/test-equals-ignore-gensym' failed."
  ;; TODO: Write our own explanation, this will trigger when
  ;; necessary, but will not always display the correct message.
  (ert--explain-equal-rec a b))
(put 'i/test-equals-ignore-gensym
     'ert-explainer 'i/test-explainer-equal)

(ert-deftest i-test-repreat ()
  "Tests the expansion of i-iterate macro, repeat driver."
  (require 'i-iterate)
  (should
   (i/test-equals-ignore-gensym
    (macroexpand '(++ (repeat 100) (message "")))
    '(let* ((--0 0))
       (while (< --0 100)
         (incf --0)
         (message "")) nil))))

但如果有更好的方法,我会更高兴。

4

3 回答 3

1

您可以以不同的方式解决问题:不要检查代码是否是您期望的代码,而只需检查代码是否按照您的预期运行。即运行(++ ...)表达式并检查输出。

顺便说一句,您想要对这些代码块进行的比较称为“相等模 alpha 转换”或只是alpha 等价

于 2012-11-27T14:02:22.810 回答
0

您可以将实际名称与symbol-name.

于 2012-11-26T17:36:59.693 回答
0

如果您make-symbol在您的定制中使用gensym,替换为对您make-symbolintern帮助。所以,

(flet ((make-symbol (&optional prefix) (intern prefix)))
  (macroexpand '(++ (repeat 100) (message ""))))

生成带有内部符号的类似代码--0。这足以避免您的问题。

于 2014-11-14T17:44:52.687 回答