Оба выглядят достаточно хорошо. Я хотел бы понять, что каждая библиотека особенно хороша или отсутствует, особенно для тестирования веб-приложений.
Как сравнить Midje и Speclj?
Ответ 1
Я не использовал speclj, и я был первым автором Midje. Один из вопросов, о которых не упоминали другие, заключается в том, что Midje пытается использовать различия между функциональными и объектно-ориентированными языками.
Одно отличие - неизменность. Поскольку большинство функций зависят только от их входных данных, а не от содержащегося в них состояния, то утверждения о действиях, которые вы делаете о них, отличаются друг от друга, чем их объектно-ориентированные коллеги. В OO-тестировании вы приводите примеры формы: "учитывая эту историю и эти входы, этот метод создает такие-то и такие".
Казалось бы, примеры на функциональном языке были бы просто более простыми: "учитывая эти входы, эта функция возвращает такие и так". Но я не думаю, что это правильно. Я думаю, что другие функции в системе играют роль, аналогичную состоянию/истории: они - одна из вещей, которые вы пытаетесь получить интеллектуальный контроль. Функции и их отношения - это то, что вы хотите, чтобы тесты помогли вам четко охарактеризовать.
По этой причине Midje записывается в предположении, что сладкий процесс развития включает в себя:
- Что я хочу сказать об этой функции? В мире системы, какой хороший способ думать о том, что делает эта функция?
- В процессе выполнения этого, какие другие функции были бы полезны - захватили бы важную часть области --- и какие утверждения истинности я хочу сделать о них?
И затем, в типичном стиле макеты, вы развиваетесь примерно сверху вниз или снаружи, допуская неизбежную итерацию, когда вы оправитесь от ошибок или получите лучшие идеи.
Конечный результат должен быть большой кучей функций, с их взаимосвязями, задокументированными тестами или (как называет их Midje) "фактами" о функциях и функциях, от которых они зависят. Различные люди прокомментировали, что в Midje есть пролог/логическое программирование, и это не случайность. Как всегда, тесты являются примерами, но Midje пытается заставить их больше походить на утверждения правды. Это оправдание его единственной на самом деле инновационной особенностью, метаконстантами. Вот пример из них:
(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...))
В этом случае фактическая позиция не имеет отношения к тому, что верно в отношении функции right
, за исключением того, что она никогда не изменяется. Идея метаконстанта заключается в том, что это значение, о котором ничего не известно, кроме того, что явно указано в тесте. Слишком часто в тестах трудно сказать, какой существенный и какой случайный. Это имеет ряд плохих последствий: понимание, ремонтопригодность и т.д. Метаконстанты обеспечивают ясность. Если имеет значение, что значение представляет собой карту или запись, которая содержит значение 3
для ключа :a
, вы говорите это явно:
(fact
(full-name ..person..) => "Brian Marick"
(provided
..person.. =contains=> {:given-name "Brian", :family-name "Marick"}))
Этот тест является явным о том, что важно для людей, а также о том, что не имеет значения (ничего, кроме двух имен).
В математических выражениях Midje пытается позволить вам делать такие утверждения, как "для всех x, где x...", но все еще являясь тестовым инструментом, а не средством проверки теоремы.
Этот подход был вдохновлен "лондонским" макет-тяжелым TDD, описанным в Growing Object-Oriented Software, который является подход, который я обычно использую при написании кода Ruby. Но у него получилось совсем другое чувство, которое трудно описать. Но это ощущение, что требуется больше поддержки инструмента, чем просто with-redefs
.
Результат заключается в том, что Midje частично является попыткой найти стиль функционального TDD, который не просто порт OD TDD. Он также пытается стать инструментом общего назначения, но это полууниверситетское программное обеспечение. Как сказал Авраам Линкольн: "Те, кому это нравится, найдут такое, что им нравится".
Ответ 2
Самое большое преимущество использования 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)})
Вот как вы можете протестировать его в середине:
(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))
Этот пример - это просто быстрый взгляд на то, что вы можете сделать с серединой, но демонстрирует суть того, что хорошо. Здесь вы можете увидеть, что для выражения требуется очень мало посторонней сложности:
- то, что должна произвести функция (несмотря на то, что функция метки времени будет отличаться каждый раз, когда вы вызов функции),
- чтобы была вызвана функция timestamp и функция регистрации,
- что функция регистрации была вызвана только один раз,
- что функция регистрации получила ожидаемый первый аргумент и
- что вам все равно, какой второй аргумент он получил.
Главное, что я пытаюсь сделать с помощью этого примера, - это очень чистый и компактный способ выражения тестов сложного кода (а по комплексу я имею в виду, что он имеет встроенные части, которые можно разделить) в простых кусках, а не пытаться чтобы проверить все сразу. Тестирование всего сразу происходит, а именно в интеграционном тестировании.
Я, по общему признанию, предвзятый, потому что активно использую midje, тогда как я только смотрел на speclj, но я считаю, что speclj, вероятно, наиболее привлекателен для людей, которые использовали аналогичную библиотеку Ruby и находят этот способ мышления о тестах идеален на основе этого опыта. Это совершенно разумная причина выбора рамки тестирования, и, вероятно, есть и другие приятные вещи, которые, как мы надеемся, могут комментировать.
Ответ 3
Я бы определенно пошел с Speclj.
Speclj прост для интеграции и использования. Его синтаксис менее яркий, чем Midje's. Speclj основан на RSpec, чтобы дать вам все удобства, с которыми работают программисты Ruby, не теряя при этом отличия Clojure.
И автоперевод в Speclj велик.
lein spec -a
Как только вы это используете некоторое время, вы задаетесь вопросом, как вы когда-либо работали, когда вам приходилось вручную запускать тесты.
Mocking - это не проблема, поскольку вы можете просто использовать с-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))))))
Этот голой подход к насмешкам - это точка; нет неправильного направления.
Что касается тестирования веб-приложений, Speclj работает нормально. На самом деле поддержка Speclj встроена в Joodo.
Отказ от ответственности: я написал Speclj
Ответ 4
Я бы сказал, что Midje особенно хорош в создании DSL для выражения stubbing и насмешек. Если вы заботитесь о том, чтобы укусить и насмехаться, и хотите использовать его много, я бы выбрал Midje над Speclj, потому что у него есть абстракции для выражения тех типов тестов, которые являются более краткими, чем подход slagyr, предложенный в его ответе.
Другим вариантом, если вы хотите более легкий подход, является Conjure stubbing/mocking library, предназначенная для использования с clojure.test.
В тех случаях, когда Speclj shines очень похож на RSpec, включая "описать" и "он"... Midje может поддерживать нативные факты на самом деле, но не так элегантно, как Speclj.
отказ от ответственности: я являюсь автором Midje и Conjure.:)
Ответ 5
Я бы предложил Midje над Speclj
Для speclj я не думаю, что если он имеет хорошую поддержку для mocks, документация также выглядит редкой по сравнению с Midje.
Также лучше синтаксис для Midje:
(foo :bar) => :result compared to (should= (foo :bar) :result)