2024 Clojure 状态调查! 分享您的想法。

欢迎!请参阅 关于 页面,了解更多关于如何使用本站的信息。

0 票投
Spec

目前,{{instrument}} 和 {{unstrument}} 对无条件的测试和开发仪器化非常出色。我还想为特定的代码片段运行 instrument。例如,我想进行一个带有某些存根或某些覆盖的测试。当前,我需要执行 instrument 和 uninstrument;我更倾向于有一个可以为我执行明显的 try/finally 块的 with-instrument 宏。

3 答案

0 票投

评论者:alexmiller

(就像大多数事情一样),明显的事情并不总是那么明显。 :)

调用 instrument 有几种方式

  • (instrument)
  • (instrument sym)
  • (instrument (link: syms))
  • (instrument sym opts)
  • (instrument (link: syms) opts)

这里的数字是可变的。同样,在其他 with-style 宏中,通常 "body" 也通常是可变的。这两个可变的解析是模糊的。

您提到了 opts 映射,所以我认为您希望将其作为一个选项。因此,您可以将参数缩小到:(link: sym-or-syms opts & body)。不确定您是否引入了一些您在常见情况下不需要的东西,从而破坏了宏的有用性。

(with-instrument `my-fun {my-opts ...} (test-something))

将展开为

`
(do
(instrument user/my-fun {my-opts ...})
(try

(test-something)
(finally
  (unstrument user/my-fun))))

`

也许可以考虑如何更多地考虑到已经仪器化的因素。您是否取消仪器化,还是尝试将仪器化返回到之前的状态(其中某些东西可能已经仪器化)?

0 票投

评论者:dsg

以下是我一直使用的实现,这不一定是非要用的一种,但我认为它有助于解决关于参数的某些模糊性。

`
(defmacro with-instrumentation
[args & body]
`(let [[arg1# arg2#] ~args

     [sym-or-syms# opts#] (cond
                            (nil? arg1#) [(stest/instrumentable-syms) arg2#]
                            (map? arg1#) [(stest/instrumentable-syms) arg1#]
                            :default     [arg1# arg2#])]
 (try
   (stest/instrument sym-or-syms# opts#)
   ~@body
   (finally
     (stest/unstrument sym-or-syms#)))))

`

它不够完美,但已经足够让我得心应手。

关于结束时会发生什么的疑问非常中肯。理想情况下,with-instrumentation 应该具有类似栈的语义,即插桩后能够返回到其之前的状态。这是否可以使用规范完成?

0 票投
参考: https://clojure.atlassian.net/browse/CLJ-2015(由 lvh 报告)
...