修改 `cake test` 以控制堆栈跟踪深度(Clojure)

4
我希望修改cake test,使其使用不同的值作为*stack-trace-depth*内置定义仅为:
(deftask test #{compile}
  "Run project tests."
  "Specify which tests to run as arguments like: namespace, namespace/function, or :tag"
  (run-project-tests))

理想情况下,我希望能够通过命令行参数--depth=n来指定值,类似于这样的方式:
(binding [*stack-trace-depth* (if (*opts* :depth)
                                  (read-string (*opts* :depth)))]
         (run-project-tests))

我需要什么代码才能让这个工作?


根据反馈:将以下内容放入tasks.clj文件中

(undeftask test)
(deftask test #{compile}
  (.bindRoot #'*stack-trace-depth* 5)
  (println "Defining task: *stack-trace-depth* is" *stack-trace-depth* "in" (Thread/currentThread))
  (run-project-tests))

产生以下输出:

Loading test/cake_test/core.clj:

  Loading tests: *stack-trace-depth* is nil in #<Thread[thread-13,5,main]>

$ cake test

  Defining task: *stack-trace-depth* is 5 in #<Thread[Thread-18,5,main]>
  In test: *stack-trace-depth* is nil in #<Thread[Thread-16,5,main]>

  Testing cake-testing.core

  FAIL in (test-stack-trace-depth) (core.clj:8)
  expected: (= *stack-trace-depth* 5)     
  actual: (not (= nil 5))

  Ran 1 tests containing 1 assertions.
  1 failures, 0 errors.
  ----
  Finished in 0.011865 seconds.

(测试代码在Gist上。)

2个回答

3

(更新:放弃了原来的答案,这里是一个看起来可行的解决方案。)

我从您的Gist中获取了示例项目,并进行了以下更改:

  1. rm tasks.clj

  2. Added the following code to project.clj below the defproject form:

    (use '[bake.find-namespaces :only [find-namespaces-in-dir]]
         '[cake.tasks.test :only [test-opts]])
    
    
    (undeftask test)
    (deftask test #{compile}
      (bake (:use bake.test
                  [bake.core :only [with-context]]
                  [clojure.test :only [*stack-trace-depth*]])
        [namespaces (find-namespaces-in-dir (java.io.File. "test"))
         opts       (test-opts)]
        (with-context :test
          (binding [*stack-trace-depth* 5]
            (run-project-tests namespaces opts)))))
    
  3. Created a new file, test/cake_testing/core_test.clj with the following contents:

    (ns cake-testing.core-test
      (:use clojure.test))
    
    
    (deftest correct-stack-trace-depth?
      (is (= *stack-trace-depth* 5)))
    

此时,一切似乎都正常 -- cake test 命令的输出结果如预期。

Testing cake-testing.core-test

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.
----
Finished in 0.033200374 seconds.

此外,添加一个故意引发异常的“测试”会导致打印出一个简洁明了的堆栈跟踪。

谢谢,但似乎测试仍然看不到更新后的值。我已经在问题中添加了一些测试输出。 - Jeremy
新版本(在自定义版本的“test”任务中内联*stack-trace-depth*设置版本的cake.tasks.test/run-project-tests的结果)似乎对我有效。现在是时候深入研究Cake并了解它为什么有效,因为我似乎还无法理解代码库。不过它看起来非常酷,感谢让我感兴趣! :-) - Michał Marczyk
我以为我已经设置好了,可以收到关于蛋糕问题的通知,看来不是这样! :) 无论如何,这是一个很好的想法,有人有兴趣将其提交为主要补丁吗? - lancepantz
1
@lancepantz:我很乐意提供一个补丁/拉取请求。我猜如果这个功能能够被放在默认的“test”任务中,那么应该可以通过在“defproject”表单中添加一个额外的开关来覆盖默认值吧?(:test-stack-trace-depth或其他什么东西?)真正的解决方案要么是使任务(或至少某些特定任务,如“test”)可配置以将某些变量绑定到某些值,要么是使上下文(我还没有完全理解)能够设置变量。我认为这样做会很有趣,但至少要等到星期五才有时间进行休闲编码。 - Michał Marczyk

2
我可以把这个内容翻译成中文。这是一个关于IT技术的问题。以下是需要翻译的内容:

我能够将这个内容放在与project.clj文件位于同一级别的task.clj文件中。当我运行cake test --depth=5时,我可以看到打印出“使用stack-trace-depth = 5运行测试”的信息。希望这可以帮助到你。

(ns tasks
  (:use cake cake.core cake.tasks.test
        [clojure.test :only [*stack-trace-depth*]]))

(undeftask test)
(deftask test #{compile}
  "Run tests"
  (binding [*stack-trace-depth* (if (*opts* :depth)
                                     (read-string (first (*opts* :depth))))]
    (println "Running tests with *stack-trace-depth* = " *stack-trace-depth*)
    (run-project-tests)))

谢谢,这很有帮助。不幸的是,当我运行测试时,它们将clojure.test/*stack-trace-depth*的值视为nil,所以仍然缺少一些东西。 :/ - Jeremy
1
看起来你是对的。我已经在cake源代码中研究了一段时间,似乎run-project-tests最终会创建一个新的上下文来运行用户测试。我猜想你需要能够在该上下文中绑定*stack-trace-depth*。我尝试了一些操作,但无法找到一个好的解决方案,但我认为将这个功能添加到cake中应该很简单。祝你好运。 - Jake McCrary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接