【问题标题】:Using a dynamic variable binding in a leiningen plugin在 leiningen 插件中使用动态变量绑定
【发布时间】:2016-04-21 15:38:48
【问题描述】:

我有一个 lein 插件,可以手动运行我的 clojure.test 代码。它声明了一个动态变量baseuri,我希望从我的测试中访问它。我将删除并更改代码以直截了当。在这里,在我的插件内部,我有一个配置文件,它创建动态 baseuri 变量并将其设置为空白字符串。

;; myplugin
;; src/myplugin/config.clj
(ns leiningen.myplugin.config)    
(def ^:dynamic baseuri "")

插件中的任务设置动态baseuri 变量并使用clojure.test 运行测试:

;; src/myplugin/runtests.clj
(ns leiningen.myplugin.runtests
      (:require [leiningen.myplugin.config :as config]
                [clojure.test]
                [e2e.sometest]))

(defn run [project]
  (binding [config/baseuri "https://google.com/"]
    (println config/baseuri) ;; <-- prints google url
    ;; run clojure.test test cases from e2e.sometest namespace
    ;; This will call the `sampletest` test case
    (clojure.test/run-tests e2e.sometest)
  ))

在我的 clojure.test 中,我尝试使用 baseuri 变量,但绑定不成立。它的值是我最初声明 baseuri 的值(一个空字符串)

;; tests/e2e/sometest.clj
(ns e2e.sometest
  (:require [leiningen.myplugin.config :as config]))

(deftest sampletest
  (println config/baseuri))  ;; <-- Prints an empty string instead of google url

我已经编辑了代码,以基本方式显示 clojure.test 用例是如何运行的。我只是将我想要运行的命名空间传递给clojure.test/run-tests 方法。

【问题讨论】:

  • 你能告诉我们用什么代码代替你的评论;; runs clojure.test code here吗?
  • 我编辑了答案以显示 clojure.test 测试用例如何运行。

标签: plugins clojure leiningen clojure.test


【解决方案1】:

我同意 clojure.test 在参数化测试时不是最佳实现。

我不知道为什么您的binding 表单不起作用 - 我检查了clojure.test 中的代码,但看不出有什么问题。我会检查:

  • 测试在与binding 建立的同一线程中执行(也许您可以在插件和测试中添加记录线程名称/ID)

  • 不同的类加载器导致您的插件命名空间及其全局动态变量实际上被加载和定义了两次

我还有一个想法(我真的不想批评您的解决方案,只是想寻找替代解决方案:)):您的问题是从外部来源(如 test)将全局配置选项传递给您的测试代码脚本配置。您是否考虑过将它们作为环境变量传递?您可以使用(System/getenv "baseuri")environ 轻松阅读它们。

【讨论】:

  • 感谢您在问题中提供更多背景和详细信息。我已经编辑了我的答案。如果您觉得我之前的回答没有同情心,我很抱歉,我只是想提供帮助。
  • 你是对的。在我的project.clj 文件中,我已将插件添加到:plugins 映射键。此外,为了能够 (require) 应用程序中的插件配置,我还必须在 :dependencies 映射键中声明插件。因此,正如您所想的那样,它被加载了两次。感谢 Piotrek 抽出宝贵的时间。非常非常感谢。
【解决方案2】:

也许您有一个动态 var 出于非常具体的原因,但是,由于您没有明确说明,我在这里试一试。

避免动态重新绑定变量。在最好的情况下,完全避免全局状态,而是重新定义函数以将 baseuri 作为参数。
或者重构您的应用程序,使其完全不需要静态变量,就像您现在拥有的那样。

编辑我的猜测是你的功能:

(defn run [project]
  (binding [config/baseuri "https://google.com/"]
    (println config/baseuri) ;; <-- prints google url
    ;; runs clojure.test code here …
  ))

(deftest sampletest
  (println config/baseuri))

没有以任何方式连接。至少我不明白他们应该如何。您正在运行测试并打印其他一些 var 而无需重新绑定它。
也许您可以添加一个指向最小可重现测试用例的存储库的链接以更好地理解它?

【讨论】:

  • 嘿,我同意。不幸的是,由于clojure.test 的巨大限制,它根本不可能将参数传递给用deftest 编写的测试。我发现clojure.test 很少允许函数式编程将我的双手绑在背后。如果deftest 允许我设置参数。
  • 很难说。仍然: 1. 重新配置您的应用程序,它看起来不对 2. binding 仅在其本地范围内重新绑定,一旦您离开bindingscope baseuri 将再次成为""
猜你喜欢
  • 1970-01-01
  • 2020-04-28
  • 2022-12-17
  • 2013-07-08
  • 2018-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多