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

欢迎!有关此操作的更多信息,请参阅关于页面。

0
Spec

目前,“{{instrument}}”和“{{uninstrument}}”非常适合进行测试和开发的无条件插入。我还想为特定的一块代码运行“instrument”。例如,我想有一个带有某些存根或某些覆盖的测试。目前,我需要插入和删除“instrument”,我更希望有一个“with-instrument”宏,它为我执行明显的try/finally块。

3 个答案

0

评论者:alexmiller

(就像大多数事情一样),显而易见的事情并不那么容易办到。 :)

调用instrument有几种方式:

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

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

您提到了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#)))))

`

这并不完美,但已经足够有效了。

关于结束时会发生什么的问题是很好的。理想情况下,带内省的操作将具有类似于栈的语义,其中内省将返回到其之前的状态。这是否可以通过规范来实现?

0
...