Add lib tests for bond (#524)
* Add lib-tests for bond * Mention bond and add instructions for adding libtests * Tweak lib test to detect exception that bb throws
This commit is contained in:
parent
097ced0f14
commit
901ea41f20
7 changed files with 214 additions and 5 deletions
3
deps.edn
3
deps.edn
|
|
@ -55,4 +55,5 @@
|
||||||
aero/aero {:mvn/version "1.1.6"}
|
aero/aero {:mvn/version "1.1.6"}
|
||||||
org.clojure/data.generators {:mvn/version "1.0.0"}
|
org.clojure/data.generators {:mvn/version "1.0.0"}
|
||||||
honeysql/honeysql {:mvn/version "1.0.444"}
|
honeysql/honeysql {:mvn/version "1.0.444"}
|
||||||
minimallist/minimallist {:mvn/version "0.0.6"}}}}}
|
minimallist/minimallist {:mvn/version "0.0.6"}
|
||||||
|
circleci/bond {:mvn/version "0.4.0"}}}}}
|
||||||
10
doc/dev.md
10
doc/dev.md
|
|
@ -41,6 +41,16 @@ Test the native version:
|
||||||
|
|
||||||
BABASHKA_TEST_ENV=native script/test
|
BABASHKA_TEST_ENV=native script/test
|
||||||
|
|
||||||
|
## Tests for Libraries
|
||||||
|
|
||||||
|
Babashka runs tests of libraries that are compatible with it through
|
||||||
|
`script/run_lib_tests`. To add tests for a new library, do the following:
|
||||||
|
|
||||||
|
* Add an entry for the library in `deps.edn` under the `:lib-tests` alias.
|
||||||
|
* Create a directory for the library in `test-resources/lib_tests/` and copy its tests to there.
|
||||||
|
* Add an entry in `run_all_libtests.clj` to run the added test namespaces.
|
||||||
|
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
See [build.md](build.md).
|
See [build.md](build.md).
|
||||||
|
|
|
||||||
|
|
@ -195,8 +195,8 @@ $ bb "(use 'doric.core) (println (table [:a :b :c] [{:a 1 :b 2 :c 3} {:a 4 :b 5
|
||||||
|
|
||||||
### [clojure.data.zip](https://github.com/clojure/data.zip)
|
### [clojure.data.zip](https://github.com/clojure/data.zip)
|
||||||
|
|
||||||
Utilities for clojure.zip, among other things a more fluent way to work
|
Utilities for clojure.zip, among other things a more fluent way to work
|
||||||
with xml.
|
with xml.
|
||||||
|
|
||||||
Small sample:
|
Small sample:
|
||||||
``` clojure
|
``` clojure
|
||||||
|
|
@ -249,6 +249,10 @@ Random data generators
|
||||||
|
|
||||||
Turn Clojure data structures into SQL
|
Turn Clojure data structures into SQL
|
||||||
|
|
||||||
|
### [bond](https://github.com/circleci/bond)
|
||||||
|
|
||||||
|
Spying and stubbing library, primarily intended for tests.
|
||||||
|
|
||||||
## Pods
|
## Pods
|
||||||
|
|
||||||
[Babashka pods](https://github.com/babashka/babashka.pods) are programs that can
|
[Babashka pods](https://github.com/babashka/babashka.pods) are programs that can
|
||||||
|
|
@ -322,7 +326,7 @@ A wee multi-threaded web server
|
||||||
|
|
||||||
### [covid19-babashka](https://github.com/agrison/covid19-babashka)
|
### [covid19-babashka](https://github.com/agrison/covid19-babashka)
|
||||||
|
|
||||||
A babashka script to obtain covid-19 related information.
|
A babashka script to obtain covid-19 related information.
|
||||||
|
|
||||||
### [bb-spotify](https://github.com/kolharsam/bb-spotify)
|
### [bb-spotify](https://github.com/kolharsam/bb-spotify)
|
||||||
|
|
||||||
|
|
@ -333,7 +337,7 @@ Contol your spotify player using babashka.
|
||||||
[Internal
|
[Internal
|
||||||
tooling](https://github.com/borkdude/babashka/issues/457#issuecomment-636739415)
|
tooling](https://github.com/borkdude/babashka/issues/457#issuecomment-636739415)
|
||||||
used by Lambda Island projects. Noteworthy: a [babashka-compatible hiccup
|
used by Lambda Island projects. Noteworthy: a [babashka-compatible hiccup
|
||||||
script](https://github.com/lambdaisland/open-source/blob/2cfde3dfb460e72f047bf94e6f5ec7f519c6d7a0/src/lioss/hiccup.clj).
|
script](https://github.com/lambdaisland/open-source/blob/2cfde3dfb460e72f047bf94e6f5ec7f519c6d7a0/src/lioss/hiccup.clj).
|
||||||
|
|
||||||
There's also
|
There's also
|
||||||
[subshell](https://github.com/lambdaisland/open-source/blob/master/src/lioss/subshell.clj)
|
[subshell](https://github.com/lambdaisland/open-source/blob/master/src/lioss/subshell.clj)
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,9 @@
|
||||||
|
|
||||||
(test-namespaces 'minimallist.core-test)
|
(test-namespaces 'minimallist.core-test)
|
||||||
|
|
||||||
|
;;;; bond
|
||||||
|
(test-namespaces 'bond.test.james)
|
||||||
|
|
||||||
;;;; final exit code
|
;;;; final exit code
|
||||||
|
|
||||||
(let [{:keys [:test :fail :error] :as m} @status]
|
(let [{:keys [:test :fail :error] :as m} @status]
|
||||||
|
|
|
||||||
51
test-resources/lib_tests/bond/test/assertions.cljc
Normal file
51
test-resources/lib_tests/bond/test/assertions.cljc
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
(ns bond.test.assertions
|
||||||
|
(:require #?(:clj [clojure.test :refer (deftest is testing)])
|
||||||
|
[bond.assertions :as assertions]
|
||||||
|
[bond.james :as bond :include-macros true]
|
||||||
|
[bond.test.target :as target])
|
||||||
|
#?(:cljs (:require-macros [cljs.test :refer (is deftest testing)])))
|
||||||
|
|
||||||
|
(deftest called?-works
|
||||||
|
(testing "a spy was called directly"
|
||||||
|
(bond/with-spy [target/foo]
|
||||||
|
(let [_ (target/foo 1)]
|
||||||
|
(is (assertions/called? target/foo)))))
|
||||||
|
|
||||||
|
(testing "a spy was called indirectly"
|
||||||
|
(bond/with-spy [target/foo]
|
||||||
|
(let [_ (target/foo-caller 1)]
|
||||||
|
(is (assertions/called? target/foo)))))
|
||||||
|
|
||||||
|
(testing "a spy was not called"
|
||||||
|
(bond/with-spy [target/foo]
|
||||||
|
(is (not (assertions/called? target/foo))))))
|
||||||
|
|
||||||
|
(deftest called-times?-works
|
||||||
|
(testing "the number of times a spy was called"
|
||||||
|
(bond/with-spy [target/foo]
|
||||||
|
(let [_ (target/foo-caller 1)]
|
||||||
|
(is (assertions/called-times? target/foo 1 )))
|
||||||
|
(let [_ (target/foo 2)]
|
||||||
|
(is (assertions/called-times? target/foo 2)))))
|
||||||
|
|
||||||
|
(testing "the number of times a spy was not called"
|
||||||
|
(bond/with-spy [target/foo]
|
||||||
|
(let [_ (target/foo-caller 1)]
|
||||||
|
(is (not (assertions/called-times? target/foo 2))))
|
||||||
|
(let [_ (target/foo-caller 2)]
|
||||||
|
(is (not (assertions/called-times? target/foo 1)))))))
|
||||||
|
|
||||||
|
(deftest called-with-args?-works
|
||||||
|
(testing "an assertion for calling a spy with args"
|
||||||
|
(bond/with-spy [target/foo]
|
||||||
|
(let [_ (target/foo-caller 1)]
|
||||||
|
(is (assertions/called-with-args? target/foo [[1]]))
|
||||||
|
(is (not (assertions/called-with-args? target/foo [[2]])))
|
||||||
|
(is (not (assertions/called-with-args? target/bar [[1]])))
|
||||||
|
(is (not (assertions/called-with-args? target/foo [[1 2]]))))))
|
||||||
|
|
||||||
|
(testing "an assertion for calling a spy multiple times with args"
|
||||||
|
(bond/with-spy [target/foo]
|
||||||
|
(let [_ (do (target/foo-caller 1)
|
||||||
|
(target/foo-caller 2))]
|
||||||
|
(is (assertions/called-with-args? target/foo [[1] [2]]))))))
|
||||||
108
test-resources/lib_tests/bond/test/james.cljc
Normal file
108
test-resources/lib_tests/bond/test/james.cljc
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
(ns bond.test.james
|
||||||
|
"Copy of https://github.com/circleci/bond/blob/6e044e6b4ea034c2e7b7c0f835976770341a5f7b/test/bond/test/james.cljc
|
||||||
|
with :include-macros removed because it's not supported by bb. Also modified spy-logs-args-and-results to
|
||||||
|
throw exception that bb throws."
|
||||||
|
(:require #?(:clj [clojure.test :refer (deftest is testing)])
|
||||||
|
[bond.james :as bond]
|
||||||
|
[bond.test.target :as target])
|
||||||
|
#?(:cljs (:require-macros [cljs.test :refer (is deftest testing)])))
|
||||||
|
|
||||||
|
(deftest spy-logs-args-and-results
|
||||||
|
(bond/with-spy [target/foo]
|
||||||
|
(is (= 2 (target/foo 1)))
|
||||||
|
(is (= 4 (target/foo 2)))
|
||||||
|
(is (= [{:args [1] :return 2}
|
||||||
|
{:args [2] :return 4}]
|
||||||
|
(bond/calls target/foo)))
|
||||||
|
;; cljs doesn't throw ArityException
|
||||||
|
#?(:clj (let [exception (is (thrown? Exception (target/foo 3 4)))]
|
||||||
|
(is (= {:args [3 4] :throw exception}
|
||||||
|
(-> target/foo bond/calls last)))))))
|
||||||
|
|
||||||
|
(deftest spy-can-spy-private-fns
|
||||||
|
(bond/with-spy [target/private-foo]
|
||||||
|
(is (= 4 (#'target/private-foo 2)))
|
||||||
|
(is (= 6 (#'target/private-foo 3)))
|
||||||
|
(is (= [{:args [2] :return 4}
|
||||||
|
{:args [3] :return 6}]
|
||||||
|
(bond/calls #'target/private-foo)))))
|
||||||
|
|
||||||
|
(deftest stub-works
|
||||||
|
(is (= ""
|
||||||
|
(with-out-str
|
||||||
|
(bond/with-stub [target/bar]
|
||||||
|
(target/bar 3))))))
|
||||||
|
|
||||||
|
(deftest stub-works-with-private-fn
|
||||||
|
(testing "without replacement"
|
||||||
|
(bond/with-stub [target/private-foo]
|
||||||
|
(is (nil? (#'target/private-foo 3)))
|
||||||
|
(is (= [3] (-> #'target/private-foo bond/calls first :args)))))
|
||||||
|
(testing "with replacement"
|
||||||
|
(bond/with-stub [[target/private-foo (fn [x] (* x x))]]
|
||||||
|
(is (= 9 (#'target/private-foo 3)))
|
||||||
|
(is (= [3] (-> #'target/private-foo bond/calls first :args))))))
|
||||||
|
|
||||||
|
(deftest stub-with-replacement-works
|
||||||
|
(bond/with-stub [target/foo
|
||||||
|
[target/bar #(str "arg is " %)]]
|
||||||
|
(testing "stubbing works"
|
||||||
|
(is (nil? (target/foo 4)))
|
||||||
|
(is (= "arg is 3" (target/bar 3))))
|
||||||
|
(testing "spying works"
|
||||||
|
(is (= [4] (-> target/foo bond/calls first :args)))
|
||||||
|
(is (= [3] (-> target/bar bond/calls first :args))))))
|
||||||
|
|
||||||
|
|
||||||
|
(deftest iterator-style-stubbing-works
|
||||||
|
(bond/with-stub [target/foo
|
||||||
|
[target/bar [#(str "first arg is " %)
|
||||||
|
#(str "second arg is " %)
|
||||||
|
#(str "third arg is " %)]]]
|
||||||
|
(testing "stubbing works"
|
||||||
|
(is (nil? (target/foo 4)))
|
||||||
|
(is (= "first arg is 3" (target/bar 3)))
|
||||||
|
(is (= "second arg is 4" (target/bar 4)))
|
||||||
|
(is (= "third arg is 5" (target/bar 5))))
|
||||||
|
(testing "spying works"
|
||||||
|
(is (= [4] (-> target/foo bond/calls first :args)))
|
||||||
|
(is (= [3] (-> target/bar bond/calls first :args)))
|
||||||
|
(is (= [4] (-> target/bar bond/calls second :args)))
|
||||||
|
(is (= [5] (-> target/bar bond/calls last :args))))))
|
||||||
|
|
||||||
|
(deftest stub!-complains-loudly-if-there-is-no-arglists
|
||||||
|
(is (thrown? #?(:clj IllegalArgumentException :cljs js/Error)
|
||||||
|
(bond/with-stub! [[target/without-arglists (constantly 42)]]
|
||||||
|
(is false)))))
|
||||||
|
|
||||||
|
(deftest stub!-throws-arity-exception
|
||||||
|
(bond/with-stub! [[target/foo (constantly 9)]]
|
||||||
|
(is (= 9 (target/foo 12)))
|
||||||
|
(is (= [{:args [12] :return 9}] (bond/calls target/foo))))
|
||||||
|
(bond/with-stub! [target/bar
|
||||||
|
target/quuk
|
||||||
|
[target/quux (fn [_ _ & x] x)]]
|
||||||
|
(is (thrown? #?(:clj clojure.lang.ArityException :cljs js/Error)
|
||||||
|
(target/bar 1 2)))
|
||||||
|
(is (thrown? #?(:clj clojure.lang.ArityException :cljs js/Error)
|
||||||
|
(target/quuk 1)))
|
||||||
|
(is (= [6 5] (target/quux 8 7 6 5)))))
|
||||||
|
|
||||||
|
(deftest spying-entire-namespaces-works
|
||||||
|
(bond/with-spy-ns [bond.test.target]
|
||||||
|
(target/foo 1)
|
||||||
|
(target/foo 2)
|
||||||
|
(is (= [{:args [1] :return 2}
|
||||||
|
{:args [2] :return 4}]
|
||||||
|
(bond/calls target/foo)))
|
||||||
|
(is (= 0 (-> target/bar bond/calls count)))))
|
||||||
|
|
||||||
|
(deftest stubbing-entire-namespaces-works
|
||||||
|
(testing "without replacements"
|
||||||
|
(bond/with-stub-ns [bond.test.target]
|
||||||
|
(is (nil? (target/foo 10)))
|
||||||
|
(is (= [10] (-> target/foo bond/calls first :args)))))
|
||||||
|
(testing "with replacements"
|
||||||
|
(bond/with-stub-ns [[bond.test.target (constantly 3)]]
|
||||||
|
(is (= 3 (target/foo 10)))
|
||||||
|
(is (= [10] (-> target/foo bond/calls first :args))))))
|
||||||
32
test-resources/lib_tests/bond/test/target.cljc
Normal file
32
test-resources/lib_tests/bond/test/target.cljc
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
(ns bond.test.target)
|
||||||
|
|
||||||
|
(defn foo
|
||||||
|
[x]
|
||||||
|
(* 2 x))
|
||||||
|
|
||||||
|
(defn- private-foo
|
||||||
|
[x]
|
||||||
|
(* 2 x))
|
||||||
|
|
||||||
|
(defn foo-caller [x]
|
||||||
|
(foo x))
|
||||||
|
|
||||||
|
(defn bar
|
||||||
|
[x]
|
||||||
|
(println "bar!") (* 2 x))
|
||||||
|
|
||||||
|
(defn quux
|
||||||
|
[a b & c]
|
||||||
|
c)
|
||||||
|
|
||||||
|
(defn quuk
|
||||||
|
[a b & c]
|
||||||
|
c)
|
||||||
|
|
||||||
|
(defmacro baz
|
||||||
|
[x]
|
||||||
|
`(* ~x 2))
|
||||||
|
|
||||||
|
(def without-arglists
|
||||||
|
(fn [x]
|
||||||
|
(* 2 x)))
|
||||||
Loading…
Reference in a new issue