How to output successful tests from `lein test`? - unit-testing

Using clojure.test, when running lein test, the default settings only print out the number of assertions, like "Ran 12 tests containing 19 assertions," the details for failed tests, and the namespaces tested. I would like an output of the successful tests as well, so I can see what tests were actually run. Frameworks like Mocha in JS have this behavior by default.
For instance, if the following test passed:
(deftest aTest
(testing "Simple test"
(is (= 1 1))))
I would like an output like (formatting is arbitrary):
Testing <namespace>
Passed: aTest -> Simple test
Ideally, the passed test would also be color coded.
I looked at a few libraries, including lein-test-refresh and humane-test-output, but didn't see what I needed. The other option looks like to rewrite the report function in clojure.test, but I'd like to avoid that if possible.

I think you'll have to write it yourself. If you would like an example of how to leverage the existing deftest into a custom macro, here is an example from the Tupelo library that automatically picks a "name" for the deftest group based on the line number:
(defmacro dotest [& body]
(let [test-name-sym (symbol (str "dotest-line-" (:line (meta &form))))]
`(clojure.test/deftest ~test-name-sym ~#body)))
(dotest
(is (= 5 (+ 2 3)))) ; works!
You could just add in a println and voila!

I remember, the Eftest library provides nice colored output when running tests, you may take a look.
Also, the standard clojure.test framework supports adding your own reports. Check the Test report library for the reference.
Probably, when running the tests from your editor or IDE, it could provide the colored output. Here is my Cider-powered Emacs screenshot with the failure report:

I have searched multiple times for an answer to this question, so here is a complete solution building on #ivan-grishaev's hint using Test Report:
Test Report hooks into clojure.test to provide custom reporters that are then being run with every event occuring through a test run. Those events are passed as maps called "messages". The minimal example just appliesclojure.pprint/pprint to the messages, but this only gets you so far. Here is a bit more code to give you a feel how to write custom reporters. The indenting-reporter indents test namespaces, deftests and testing vars, and lists them all independent of test outcome.
Create a file like this in your project:
(ns my.own.test-reporter
(:require [clojure.pprint :refer [pprint]]
[clojure.test :as ct]
[clojure.core.match :refer [match]]))
(defn simple-reporter [msg]
(pprint msg))
(defn indenting-reporter [msg]
(match (:type msg)
:begin-test-ns (println (str "Testing " (:ns msg) "\n"))
:begin-test-var (println (str " " (-> msg :var meta :name)))
:pass (do (println (str " " (-> msg :context first) " :pass"))
(ct/inc-report-counter :pass))
:fail (do (println (str " " (-> msg :context first) " :fail"))
(ct/inc-report-counter :fail))
:error (do (println (str " " (-> msg :context first) " :error"))
(ct/inc-report-counter :error))
:end-test-ns (println)
:end-test-var ()
:summary (pprint msg)
:else (pprint msg)))
and then use it in the :test profile of your project.clj:
:injections [(require '[my.own.test-reporter :as tr])]
:test-report {:reporters [tr/indenting-reporter]}
You could now go on an add color to the outputs.

Related

In Clojure, how to unit test an async Pedestal interceptor?

I have an async Pedestal interceptor I want to test:
(def my-interceptor
(io.pedestal.interceptor/interceptor
{:name :my-interceptor
:enter (fn [context]
(as/go
(do
(Thread/sleep 1000)
(assoc context :answer 42))))}))
I first tried a naïve test:
(deftest my-test
(is (= 42
(:answer (io.pedestal.interceptor.chain/execute {} [my-interceptor])))))
This doesn’t work because chain/execute returns nil when it has async interceptors. I tried another solution adding the test in an interceptor just after the tested one:
(deftest my-test
(io.pedestal.interceptor.chain/execute
{}
[my-interceptor
(io.pedestal.interceptor/interceptor
{:name :test
:enter (fn [context]
(is (= 41 (:answer context))) ; should fail
context)})]))
However this doesn’t work because the test terminates before the test is executed, and thus succeeds… even if the test fails a second after:
Ran 1 test containing 0 assertions.
No failures.
FAIL in (my-test) (somefile_test.clj:49)
expected: (= 41 (:answer context))
actual: (not (= 41 42))
In practice my tests suite (using Kaocha) fails because there’s a deftest with no assertion in it.
Given that chain/execute returns nil and not a chan, I can’t wrap it in a as/<!! to block until it terminates.
At this point I’m stuck. Is there anything I can do to test that kind of interceptors?
How about this approach?
(require '[clojure.test :as test])
(require '[clojure.core.async :as async)
(test/deftest async-test []
(let [c (async/chan)]
(future (println "Running mah interceptors") (async/>!! c :done))
(test/is (= :done (async/<!! c)))
(async/close! c)))
That runs the actual interceptor code in a separate thread. Test code just needs to post something to the c when it is done.

Clojure - tests with components strategy

I am implementing an app using Stuart Sierra component. As he states in the README :
Having a coherent way to set up and tear down all the state associated
with an application enables rapid development cycles without
restarting the JVM. It can also make unit tests faster and more
independent, since the cost of creating and starting a system is low
enough that every test can create a new instance of the system.
What would be the preferred strategy here ? Something similar to JUnit oneTimeSetUp / oneTimeTearDown , or really between each test (similar to setUp / tearDown) ?
And if between each test, is there a simple way to start/stop a system for all tests (before and after) without repeating the code every time ?
Edit : sample code to show what I mean
(defn test-component-lifecycle [f]
(println "Setting up test-system")
(let [s (system/new-test-system)]
(f s) ;; I cannot pass an argument here ( https://github.com/clojure/clojure/blob/master/src/clj/clojure/test.clj#L718 ), so how can I pass a system in parameters of a test ?
(println "Stopping test-system")
(component/stop s)))
(use-fixtures :once test-component-lifecycle)
Note : I am talking about unit-testing here.
I would write a macro, which takes a system-map and starts all components before running tests and stop all components after testing.
For example:
(ns de.hh.new-test
(:require [clojure.test :refer :all]
[com.stuartsierra.component :as component]))
;;; Macro to start and stop component
(defmacro with-started-components [bindings & body]
`(let [~(bindings 0) (component/start ~(bindings 1))]
(try
(let* ~(destructure (vec (drop 2 bindings)))
~#body)
(catch Exception e1#)
(finally
(component/stop ~(bindings 0))))))
;; Test Component
(defprotocol Action
(do-it [self]))
(defrecord TestComponent [state]
component/Lifecycle
(start [self]
(println "====> start")
(assoc self :state (atom state)))
(stop [self]
(println "====> stop"))
Action
(do-it [self]
(println "====> do action")
#(:state self)))
;: TEST
(deftest ^:focused component-test
(with-started-components
[system (component/system-map :test-component (->TestComponent"startup-state"))
test-component (:test-component system)]
(is (= "startup-state" (do-it test-component)))))
Running Test you should see the out put like this
====> start
====> do action
====> stop
Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

Clojure avoid repetition on tests

In my tests I need repeat this a block of tests for each function. In this case I'm testing bad-request function, the things that need change between each test is the bad-request call, code, and error.
(deftest t-bad-request
...
(testing "with data"
(equal (merge error code message DATA) (bad-request MESSAGE DATA)))
(testing "without message and with data"
(equal (merge error code DATA) (bad-request nil, DATA))))
What is the "correct way" to resolve it in clojure? macros?
Yes, I think macros is the way to do this in clojure. Taking your code and doing some liberal assumptions about bad-request, error and the other stuff, I made up the following example:
(require '[clojure.test :refer [deftest testing is]])
; dummy implementations, here will be your real bad-request & error
(defn bad-request [& more] more)
(def error {:status :error})
(defmacro deftest-request [name code message MESSAGE DATA & body]
`(deftest ~name
(testing "with data"
(is (= (merge error ~code ~message ~DATA) (bad-request ~MESSAGE ~DATA))))
(testing "with data"
(is (= (merge error ~code ~message ~DATA) (bad-request ~MESSAGE ~DATA))))
~#body))
; Some messages will only be tested about bad requests
(deftest-request some-request-test
{:code 401} {:message "hello"} "HELO" {:data "WORLD"})
; Other messages can have more tests at the end of a deftest-request
(deftest-request some-complex-request-test
{:code 829} {:message "a-complex-message"} "IM COMPLEX" {:data "VERY COMPLEX"}
(testing "request returns something interesting"
(is (= "I'm cool" (run-request {:message "a-complex-message"})))))
deftest-request will run the two common bad-request tests, and any additional form passed to it.
Of course you should consider the tradeoffs of using this approach versus plain old tests... In most cases it's more clear to have plain old tests... But if you have a lot of similar tests and/or a complex test preparation, a macro can be of help.
A good example of applying this technique is in the sqlingvo test suite

Reusing a stub/redef across a speclj context

I'm writing tests for a Clojure app using Speclj. I'm accustomed in BDD to do things like this:
context "some context"
stub my-function :return true
it "has behavior one"
should true my-function
it "has behavior two"
should_not false my-function
But in Speclj I can't seem to find an example of how to share the stub across the characteristics, so I'm currently stuck writing code like this:
(describe "this"
(context "that"
(it "accepts nil"
(with-redefs [called-fn (constantly nil)]
(should= nil (my-fn nil)))))
(it "accepts 1"
(with-redefs [called-fn (constantly nil)]
(should= 100 (my-fn 1))))))
(I realize this is a somewhat contrived example and arguably those assertions could all go under one characteristic, but let's suppose for now that I have good reason to write the code like this.)
I want, however, to just have to stub called-fn once, but moving this up out of the its raises errors because the real called-fn gets called instead of my redef.
Is there a way to reuse redefs (or use Speclj stubs) in Speclj so I'm not stuck pushing them all down inside the characteristics?
You can use the around macro to accomplish this.
Here's an example spec:
(ns sample.core-spec
(:require [speclj.core :refer :all]
[sample.core :refer :all]))
(describe "a test"
(it "returns output from fn-a"
(should= 1 (fn-b)))
(describe "using with-redef"
(around [it] (with-redefs [fn-a (fn [] 2)] (it)))
(it "returns the output from redefined function"
(should= 2 (fn-b)))))
Source:
(ns sample.core)
(defn fn-a []
1)
(defn fn-b []
(fn-a))

How to print test names in Leiningen?

I would like to print each of my leiningen test methods as they are running. I have a lein tests file that is relatively simple:
(defn myfixture [b]
(do
(println "start")
(b)
(println "end")
)
)
(deftest test1 [] .....
I want to see "test1" print out at the repl when I run the tests. Is there a simple way to print the method name (either by calling a method of b in myfixture, or, in the invocation of "lein test")?
You can get the name of a function like this:
(defn function-name [f]
(:name (meta f)))
(defn my-func []
(println "Hello, world!"))
(let [f my-func]
(function-name f))
;=> my-func
I don't know if the facility that you are looking for exists in the regular clojure.test but midje has some pretty extensive fixture facilities, this link is maybe worth checking out.