Существуют ли технические причины, по которым Ruby DSL, такой как RSpec, нельзя переписать на Python? - PullRequest
21 голосов
/ 16 августа 2011

В следующем разделе более подробно, но в основном кто-то заявил, что написанный на Ruby DSL RSpec не может быть переписан на Python. Это правда? Если так, то почему?

Я хочу лучше понять технические различия между Ruby и Python.

Обновление: почему я задаю этот вопрос?

В обсуждении , убегающем от RSpec , есть некоторые утверждения, что "невозможно" воссоздать RSpec в Python. Я пытался сделать вопрос немного шире в надежде узнать больше о технических различиях между Ruby и Python. Оглядываясь назад, возможно, мне следовало бы сузить область вопроса, чтобы просто спросить, действительно ли невозможно воссоздать RSpec в Python, и если да, то почему.

Ниже приведены лишь несколько цитат из обсуждения , убегающего от обсуждения RSpec .

Начальный вопрос

В течение последних нескольких недель я много думал о RSpec и почему нет четкого, однозначного ответа, когда кто-то спрашивает:

"Я ищу Python-эквивалент RSpec. Где я могу найти такой вещь? "

Вероятно, наиболее распространенным (и понятным) ответом является синтаксис Python не допустил бы такого, тогда как в Ruby это возможно.

Первый ответ на первый вопрос

Не совсем синтаксис. Rspec monkeypatches каждый объект внутри его область действия, вставляя методы «следует» и «следует_ не». Ты можешь сделать что-то в python, но вы не можете monkeypatch встроенные типы.

Другой ответ

Как вы предлагаете, это невозможно. Mote и PySpec - просто модные способы назвать ваши тесты: слабые реализации одного крошечного угла RSpec. Mote использует ужасную магию сеттрасов; PySpec добавляет кучу не относящийся к области шум. Ни один даже не поддерживает произвольный контекст строки. RSpec более лаконичен, более выразителен, устраняет шум и это вполне разумная вещь для сборки в Ruby.

Последний пункт важен: не только RSpec возможен в Рубин; это на самом деле идиоматично.

Ответы [ 5 ]

10 голосов
/ 24 августа 2011

Если бы мне пришлось указать на одну большую трудность при создании Python RSpec, это было бы отсутствие хорошего синтаксиса в Python для создания анонимных функций (как в JavaScript) или блоков (как в Ruby). Единственный вариант для программиста на Python - это использовать лямбда-выражения, что совсем не так, потому что лямбда-выражения принимают только одно выражение. Блоки do ... end, используемые в RSpec, должны быть записаны как функция перед вызовом describe и 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 .

Подводя итог: ИМХО самым сложным барьером для DSL в Python является отсутствие гибкого синтаксиса для создания анонимных функций. И это не ошибка *: Python в любом случае не любит тщательно изучать свой синтаксис - считается, что он делает код менее понятным во вселенной Python. Если вам нужен новый синтаксис в Python, советуем вам написать свой собственный язык, или, по крайней мере, так я чувствую.

* Или, может быть, я должен признаться, что мне не хватает анонимных функций. Тем не менее, я признаю, что их будет сложно реализовать элегантно, учитывая семантические отступы Python.

5 голосов
/ 13 марта 2012

Я попытался реализовать что-то вроде rspec в Python.

Я получил это:

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

источник: https://gist.github.com/2029866

(мысли?)

РЕДАКТИРОВАТЬ: Мой ответ на ваш вопрос заключается в том, что отсутствие анонимных блоков не позволяет переписать Ruby DSL, такой как RSpec, в Python, но вы можете получить близкое приближение, используя операторы.

5 голосов
/ 24 августа 2011

Одной из сильных сторон Ruby является создание DSL.Однако причины, по которым это трудно сделать в python, можно обойти.Например, вы можете легко создать подкласс встроенных типов, например:

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

Если бы я собирался создать DSL в python, я бы использовал pyparsing или Parsley и что-то похожее за кулисами, оптимизирующее синтаксис проблемы, а не язык реализации.

2 голосов
/ 14 июня 2016

Смешивая Mamba и Expect, я думаю, вы можете очень близко понять, что такое RSpec для Rails ...
https://github.com/nestorsalceda/mamba
https://github.com/jaimegildesagredo/expects

Кроме того, я думаю, что Spectre должен совпадатьВаши ожидания от тестирования:
https://github.com/jmvrbanac/Specter
http://specter.readthedocs.io/en/latest/writing_tests/index.html

1 голос
/ 08 августа 2012

Я думаю, это то, что вы ищете.Да, мы сделали «невозможное» в python «уверен» - это служебный пояс для выразительных тестов Python, созданный Габриэлем Фалькао

...