У меня есть функция, которая должна принимать ленивую последовательность и возвращать нереализованную ленивую последовательность. Теперь я хочу написать модульный тест (кстати, test-is), чтобы убедиться, что результатом является нереализованная ленивая последовательность.
как провести юнит-тест на лень
Ответы (2)
user=> (instance? clojure.lang.LazySeq (map + [1 2 3 4] [1 2 3 4]))
true
Если у вас есть много вещей для тестирования, возможно, это упростит это:
(defmacro is-lazy? [x] `(is (instance? clojure.lang.LazySeq ~x)))
user=> (is-lazy? 1)
FAIL in clojure.lang.PersistentList$EmptyList@1 (NO_SOURCE_FILE:7)
expected: (clojure.core/instance? clojure.lang.LazySeq 1)
actual: (not (clojure.core/instance? clojure.lang.LazySeq 1))
false
user=> (is-lazy? (map + [1 2 3 4] [1 2 3 4]))
true
Начиная с Clojure 1.3, есть также функция realized?
: «Возвращает true, если значение было создано для обещания, задержки, будущей или ленивой последовательности».
realized?
(добавленная в версии 1.3) будет обрабатывать все незавершенные дела. Примечательно (понял? (повторить вкл. 10)) => правда. Я предполагаю, что правильно называть это ленивой последовательностью, но первый элемент должен быть реализован, потому что он передается в качестве аргумента, поэтому избежать этого невозможно. Я думаю, что тестирование возвращаемого типа соответствует целям вопроса и менее навязчиво, чем альтернатива.
- person Timothy Pratley; 04.02.2016
(defn is-lazy [x] (is (instance? clojure.lang.LazySeq x))
не будет работать так же?
- person bfontaine; 13.09.2016
(is-lazy? (vec (map inc (range 10))))
в качестве макроса сообщит expected: (clojure.core/instance? clojure.lang.LazySeq (vec (map inc (range 10))))
, но функция покажет [1 2 3 4 5 6 7 8 9 10]
... просто вопрос предпочтений.
- person Timothy Pratley; 13.09.2016
Используйте функцию с побочным эффектом (скажем, запись в ссылку) в качестве функции генератора последовательности в вашем тестовом примере. Если побочный эффект никогда не возникает, это означает, что последовательность остается нереализованной... как только последовательность будет реализована, будет вызвана функция.
Во-первых, настройте его следующим образом:
(def effect-count (ref 0))
(defn test-fn [x]
(do
(dosync (alter effect-count inc))
x))
Затем запустите свою функцию. Я просто использую карту, здесь:
(def result (map test-fn (range 1 10)))
Проверьте, запускался ли test-fn:
(if (= 0 @effect-count)
(println "Test passed!")
(println "Test failed!"))
Поскольку мы знаем, что карта ленива, она всегда должна работать на этом этапе. Теперь принудительно вычислите последовательность:
(dorun result)
И снова проверьте значение счетчика эффектов. На этот раз мы ДЕЙСТВИТЕЛЬНО ожидаем, что побочный эффект сработает. А, это так...
user=>@effect-count
9