是否有技术原因像RSpec这样的Ruby DSL无法在Python中重写?

时间:2011-08-16 14:31:04

标签: python ruby rspec dsl

下面的部分详细介绍,但基本上有人说用Ruby编写的DSL RSpec无法在Python中重写。真的吗?如果是这样,为什么?

我想更好地理解Ruby和Python之间的技术差异。

更新:我为什么要问这个问题?

Running away from RSpec讨论中有一些关于在Python中重新创建RSpec“不可能”的陈述。我试图让问题更广泛,希望学习更多Ruby和Python之间的技术差异。事后看来,也许我应该收紧问题的范围,只是询问是否真的无法在Python中重新创建RSpec,如果是这样的话。

以下是Running away from RSpec讨论中的一些引用。

初步问题

  

在过去几周里,我一直在思考很多关于RSpec的问题以及当有人问起时为什么没有明确的答案:

     
    

“我正在寻找相当于RSpec的Python。我在哪里可以找到这样的     东西吗?“

  
     

最常见(也可理解)的答案可能是Python语法   不允许这样的事情,而在Ruby中它是可能的。

对初始问题的第一反应

  

语法不完全正确。 Rspec monkeypatches其中的每个对象   范围,插入方法“should”和“should_not”。你可以做   在python中的东西,但你不能monkeypatch内置类型。

另一个回复

  

如你所知,这是不可能的。 Mote和PySpec只是一种奇特的方式   命名测试:RSpec的一个小角落的弱实现。   Mote使用了可怕的settrace魔法; PySpec增加了一堆   与域无关的噪声。甚至都不支持任意上下文   字符串。 RSpec更简洁,更具表现力,消除噪音,和   在Ruby中构建是完全合理的。

     

最后一点很重要:不仅仅是RSpec是可能的   红宝石;它实际上是惯用的。

5 个答案:

答案 0 :(得分:10)

如果我必须指出创建Python RSpec的一个很大的困难,那就是在Python中缺少一个用于创建匿名函数(如在JavaScript中)或块(如在Ruby中)的良好语法。 Python程序员的唯一选择是使用lambdas,这根本不是一个选项,因为lambdas只接受一个表达式。在调用do ... enddescribe之前,必须将RSpec中使用的it块写为函数,如下例所示:

def should_do_stuff():
    # ...
it("should do stuff", should_do_stuff)

不那么性感吧?

创建should方法存在一些困难,但我敢打赌这会是一个较小的问题。实际上,人们甚至不需要使用这种不寻常的语法 - 您可以使用Jasmine语法获得类似的结果(可能更好,取决于您的口味),这可以通过简单的方式实现。

也就是说,我觉得Python语法更专注于有效地表示通常的程序组件,如类,函数,变量等。它不适合扩展。我认为,一个好的Python程序是我可以看到对象,函数和变量的程序,我理解这些元素中的每一个都做了什么。 Ruby程序员OTOH似乎寻求更像散文的风格,其中为新问题定义了新语言。这也是一种很好的做事方式,但不是一种Pythonic方式。 Python很适合表示算法,而不是散文。

有时这是一个严苛的限制。例如,如何使用BDD?好吧,在Python中推动这些限制的通常方法是有效地编写自己的DSL,但它应该真的是另一种语言。这就是Pyccuracy,例如:BDD的另一种语言。更主流的例子是doctest。 (实际上,如果我要编写一些BDD Python库,我会根据doctest编写它。)Python DSL的另一个例子是Twill。另一个例子是reStructuredText,在Sphinx中使用。

总结:恕我直言,Python中DSL最难的障碍是缺乏创建匿名函数的灵活语法。这不是一个错误*:Python不喜欢无论如何都要大量探索它的语法 - 它被认为在Python世界中使代码不那么清晰。如果您想在Python中使用新语法,建议您编写自己的语言,或者至少这是我的感受。

*或许它是 - 我必须承认我错过了匿名功能。但是,我认识到,鉴于Python语义缩进,它们很难优雅地实现。

答案 1 :(得分:5)

Ruby的一个优势在于创建DSL。然而,在python中遇到困难的原因可以回避。例如,您可以轻松地对内置类型进行子类化,例如:

>>> class myint(int):  pass
>>> i = myint(5)
>>> i
5

如果我要在python中创建一个DSL,我会使用pyparsingParsley以及类似上面的内容,优化问题的语法,而不是实现语言。< / p>

答案 2 :(得分:5)

我开始尝试在Python中实现类似rspec的东西。

我明白了:

with It('should pass') as test:
    test.should_be_equal(1, 1)

来源:https://gist.github.com/2029866

(想法?)

编辑:我对你的问题的回答是,缺少匿名块会阻止像RSpec这样的Ruby DSL在Python中重写,但你可以使用with语句得到一个近似值。

答案 3 :(得分:2)

通过混合Mamba和Expects,我认为你可以非常接近RSpec对Rails的看法......
https://github.com/nestorsalceda/mamba
https://github.com/jaimegildesagredo/expects

另外,我认为幽灵应该符合你的期望和测试:
https://github.com/jmvrbanac/Specter
http://specter.readthedocs.io/en/latest/writing_tests/index.html

答案 4 :(得分:1)

我认为这就是你要找的东西。是的,我们在python中做了“不可能的” "sure"是一个用于表达蟒蛇测试的实用带,由GabrielFalcão创建