Midje和Speclj如何比较?

cli*_*zin 10 clojure

两者看起来都相当不错.我想了解每个库特别擅长或缺乏的内容,特别是对于Web应用程序的测试.

Bri*_*ick 17

我没有使用speclj,我是Midje的第一作者.其他人没有提到的一点是,Midje试图利用功能语言和面向对象语言之间的差异.

一个区别是不变性.因为大多数函数仅依赖于它们的输入,而不依赖于包含的状态,所以你对它们所做的真实陈述与它们面向对象的对应物的感觉不同.在OO测试中,您可以创建表单示例:"给定此历史记录和这些输入,此方法会产生这样的结果."

似乎函数式语言中的例子只是更简单的例子:"给定这些输入,这个函数会返回这样的东西".但我不认为这是对的.我认为系统中的其他功能起着类似于状态/历史的作用:它们是你试图获得智力控制的东西之一.函数及其关系是您希望测试帮助您清楚思考的事情.

出于这个原因,Midje是在一个甜蜜的开发过程涉及说:

  • 我对这个功能有什么看法?在系统的世界中,有什么好的方法来考虑这个功能的作用?
  • 在这样做的过程中,还有哪些其他功能 - 将捕获域的一个重要部分 - 以及我想对它们做出哪些真实陈述?

然后,在典型的嘲讽风格中,你会大致自上而下或从外到内发展,允许在你从错误中恢复或有更好的想法时进行不可避免的迭代.

最终的结果是成为一大堆功能,它们的相互关系由测试记录,或者(如Midje所称)是关于功能和它们所依赖的功能的"事实".不同的人评论说,Midje有一个Prolog /逻辑编程的感觉,这不是一个意外.和往常一样,测试就是例子,但是Midje试图让它们更像真实的陈述.这是其唯一真正的创新功能,即metaconstants的理由.这是他们的一个例子:

(fact "right changes the direction, but not the position"
  (right (snapshot north ...position...)) => (snapshot west ...position...)
  (right (snapshot east ...position...)) => (snapshot north ...position...)
  (right (snapshot south ...position...)) => (snapshot east ...position...)
  (right (snapshot west ...position...)) => (snapshot south ...position...))
Run Code Online (Sandbox Code Playgroud)

在这种情况下,实际位置与函数的真实性无关right,除了它永远不会改变.一个metaconstant的想法是,除了在测试中明确说明的内容之外,它是一个值,除此之外什么都不知道.经常在测试中,很难说出什么是必要的,什么是偶然的.这有很多不好的影响:理解,可维护性等.主要信息提供清晰度.如果值是包含3key 值的map或记录很重要:a,那么请明确说明:

(fact
  (full-name ..person..) => "Brian Marick"
  (provided
     ..person.. =contains=> {:given-name "Brian", :family-name "Marick"}))
Run Code Online (Sandbox Code Playgroud)

这个测试是明确约约的人什么事情---也明确什么并不重要(什么,但两个人的名字).

在数学术语中,Midje试图让你做出像"for all x where x ..."这样的陈述,同时仍然是一个测试工具,而不是一个定理证明者.

这种方法的灵感来自于" 成长面向对象软件"中描述的"伦敦风格"模拟繁重的TDD ,这种方法通常用于编写Ruby代码.但事实证明,这种感觉有着截然不同的感觉.但这种感觉需要更多的工具支持而不仅仅是with-redefs.

结果是,Midje试图找到一种功能性TDD,而不仅仅是OO TDD的一个端口.它也试图成为一种通用工具,但它是半固定的软件.正如亚伯拉罕·林肯所说:"那些喜欢这类事情的人会发现这是他们喜欢的事情."


rpl*_*evy 8

使用Midje的最大好处是它可以提供有针对性的抽象测试,而无需测试所有零件,这些零件往往会拖累整个世界.

如果你有一个函数涉及调用辅助函数来生成时间戳,将某些东西放在数据库或消息队列中,发出API请求,缓存某些东西,记录某些东西等,你想知道发生了这些涉及世界的函数调用(有时它们发生了多少次,但是实际执行它们与你正在测试的函数无关,被调用的函数通常应该进行自己的单元测试.

假设你的代码中有这个:


(defn timestamp [] (System/currentTimeMillis))

(defn important-message [x y] (log/warnf "Really important message about %s." x))

(defn contrived [x & y]
  (important-message x y)
  {:x x :timestamp (timestamp)})
Run Code Online (Sandbox Code Playgroud)

以下是如何用midje测试它的方法:


(ns foo.core-test
  (:require [midje.sweet :refer :all]
            [foo.core :as base]))

(fact
 (base/contrived 100) => {:x 100 :timestamp 1350526304739}
 (provided (base/timestamp) => 1350526304739
           (base/important-message 100 irrelevant) => anything :times 1))
Run Code Online (Sandbox Code Playgroud)

这个例子只是您可以快速了解您可以使用midje做什么,但展示了它擅长的本质.在这里,您可以看到表达需要的外部复杂性非常少:

  1. 函数应该产生什么(尽管每次调用函数时,时间戳函数会产生什么不同),
  2. 调用时间戳函数和日志记录函数,
  3. 记录功能只被调用一次,
  4. 记录函数收到了预期的第一个参数,和
  5. 你不关心它收到的第二个论点是什么.

我试图用这个例子做的主要观点是,它是一种非常干净和紧凑的方式来表达复杂代码的测试(并且复杂的意思是它具有可以分离的嵌入部分),而不是试图测试一切一次全部.一次测试所有内容都有其地位,即集成测试.

我被认为是有偏见的,因为我积极地使用midje,而我只看了speclj,但我的感觉是speclj可能对那些使用类似的Ruby库并且发现这种思考测试理想的方式最有吸引力,基于此经验.这是选择测试框架的一个完全可靠的理由,并且可能还有其他很好的事情,希望其他人可以评论.


sla*_*gyr 8

我肯定会和Speclj一起去.

Speclj易于集成和使用.它的语法不像Midje那样华丽.Speclj基于RSpec,为您提供Ruby程序员习惯的所有配置,同时不会丢失Clojure的特性.

Speclj的赛车运动员很棒.

lein spec -a
Run Code Online (Sandbox Code Playgroud)

一旦你使用了一段时间,你会想知道当你不得不手动运行测试时你是如何完成工作的.

模拟是一个非问题,因为你可以简单地使用with-redefs.@ rplevy在Speclj中的例子看起来像这样.

(ns foo.core-spec
  (:require [speclj.core :refer :all ]
            [foo.core :as base]))

(describe "Core"
  (it "contrives 100"
    (let [message-params (atom nil)]
      (with-redefs [base/timestamp (fn [] 1350526304739)
                    base/important-message #(reset! message-params [%1 %2])]
        (should= {:x 100 :timestamp 1350526304739} (base/contrived 100))
        (should= 100 (first @message-params))))))
Run Code Online (Sandbox Code Playgroud)

这种愚蠢的嘲弄方法是至关重要的; 没有误导.

至于测试网络应用程序,Speclj工作正常.事实上,Speclj支持是构建到Joodo中的.

免责声明:我写过Speclj


Ans*_*shu 1

我建议使用 Midje 而不是 Speclj
对于 speclj,我不认为它对模拟有很好的支持,与 Midje 相比,文档看起来也很稀疏。

Midje 的语法也更好:

(foo :bar) => :result compared to (should= (foo :bar) :result)
Run Code Online (Sandbox Code Playgroud)

  • 我不确定 midje 语法客观上更好。我不太喜欢人造中缀风格。 (2认同)