简体   繁体   English

在 leiningen 插件中使用动态变量绑定

[英]Using a dynamic variable binding in a leiningen plugin

I've got a lein plugin that manually runs my clojure.test code.我有一个手动运行我的 clojure.test 代码的 lein 插件。 It declares a dynamic variable baseuri that I wish to access from within my tests.它声明了一个我希望从我的测试中访问的动态变量baseuri I'll strip out and change the code to get straight to the point.我将删除并更改代码以切入正题。 Here, inside of my plugin, I have a config file that creates the dynamic baseuri variable and sets it to a blank string.在这里,在我的插件内部,我有一个配置文件,用于创建动态baseuri变量并将其设置为空字符串。

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

A task from within the plugin sets the dynamic baseuri variable and runs tests with clojure.test:插件中的任务设置动态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)
  ))

And inside of my clojure.test I try to use the baseuri variable but the binding doesn't hold.在我的 clojure.test 内部,我尝试使用 baseuri 变量,但绑定不成立。 It's value is what I originally declared baseuri to be (an empty string)它的值是我最初声明的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

I've edited the code to show in a basic manner how the clojure.test cases are run.我已经编辑了代码,以基本方式显示 clojure.test 用例是如何运行的。 I simply pass in the namespace I want to be run to the clojure.test/run-tests method.我只是将我想要运行的命名空间传递给clojure.test/run-tests方法。

I agree that clojure.test implementation is not optimal when it comes to parameterising your tests.我同意clojure.test实现在参数化测试方面不是最佳的。

I am not sure why your binding form doesn't work - I have checked the code in clojure.test and I cannot see what could be wrong.我不确定为什么您的binding表单不起作用 - 我已经检查了clojure.test的代码,但我看不出有什么问题。 I would check if:我会检查是否:

  • the tests get executed in the same thread as the binding is established (maybe you could add logging the thread name/id in your plugin and in your tests)测试在建立binding的同一线程中执行(也许您可以在插件和测试中添加记录线程名称/ID)

  • different class loaders causing that your plugin namespace and its global dynamic variable is actually loaded and defined twice不同的类加载器导致你的插件命名空间和它的全局动态变量实际上被加载和定义了两次

I have one more idea (and I really don't want to criticise your solution, just trying to find alternative solutions :)): your problem is to pass a global configuration options to your code under test from external sources like test scripts configuration.我还有一个想法(我真的不想批评您的解决方案,只是试图找到替代解决方案:)):您的问题是将全局配置选项从外部源(如测试脚本配置)传递给您的被测代码。 Have you thought about passing them as environment variables?你有没有想过将它们作为环境变量传递? You could easily read them using (System/getenv "baseuri") or environ .您可以使用(System/getenv "baseuri")environ轻松读取它们。

Maybe you have a dynamic var for very specific reasons, but, as you do not state so explicitly, I take a shot here.也许出于非常具体的原因,您有一个动态变量,但是,由于您没有明确说明,我在这里试一试。

Avoid dynamic rebinding of vars.避免动态重新绑定变量。 At its best case, avoid global state at all, instead redefine your functions to take the baseuri as a parameter.在最好的情况下,完全避免全局状态,而是重新定义您的函数以将 baseuri 作为参数。
Or refactor your application to not have the need for static vars at all, like you have it right now.或者重构您的应用程序,完全不需要静态变量,就像您现在拥有的那样。

EDIT My guess is that your functions:编辑我的猜测是你的功能:

(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))

are not connected in any way.没有以任何方式连接。 At least I dont see how they should be.至少我不明白他们应该如何。 You are running a test and print some other var without rebinding it.您正在运行测试并打印一些其他 var 而不重新绑定它。
Maybe you could add a link to a repo to a minimal reproducable testcase to understand it better?也许您可以将存储库的链接添加到最小的可重现测试用例以更好地理解它?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM