We're writing unit tests for our code in Clojure using clojure.test.
Some of our tests ignore the API and purposely break the code, in order to serve as documentation for latent deficiencies in the code.
However, we want to distinguish between failures of these tests, and failures of normal tests.
We haven't seen any suggestions in the clojure.test documentation -- only (is (thrown? ...)), which of course doesn't do what we need.
Any suggestions? Basically, we're looking for something like (is (not <condition>)), except that the test framework should record an expected failure -- something like this.
I have made tests throw an exception when they 'fail' like this, and then used thrown? to test if the exception arrives as expected. There very well may exist a more elegant way, but this gets the job done.
As #andy said you can rebind report function.
(defmacro should-fail [body]
`(let [report-type# (atom nil)]
(binding [clojure.test/report #(reset! report-type# (:type %))]
~body)
(testing "should fail"
(is (= #report-type# :fail )))))
And use this macro like this:
(should-fail (is (= 1 2)))
That will be successful passing test.
Rebind the report function as documented in clojure.test. From there you can change how the 'failure' is handled and reported on.
A little late to the party, I know, but if you're using Leiningen you could use test selectors to exclude expected failures from the "normal" build. In your project.clj:
:test-selectors {:default #(not :expected-failure %)
:expected-failure :expected-failure}
Then write your test as:
(deftest ^:expected-failure test-with-expected-failure ...)
Calling lein test will run only those tests without the :expected-failure metadata. Calling lein test :expected-failure will run your expected failure tests. Maybe not quite what you were hoping for, but IMHO better than having to use thrown? all over the place. At least this way expected failures are explicitly documented in the code and won't interfere with the build.
Related
The with-redefs function appears to be just what is needed to mock/stub out dependencies in clojure tests. I'm using clojure.test [1.10.1]
Initially it gave me a lot of grief, where the new bindings were not applied when I ran the test. Finally I got the following setup to work as expected. The dependencies are required from other namespaces
(ns abc
(:require [anotherns.id-gen-mock :as mock])
(deftest test-buy
(testing "Appends trade to the trades log"
(let [mock (atom {})]
(with-redefs [id-gen/get-next-id mock/get-next-id
save-trade (fn [t] (reset! mock {:trade t}))]
... test code
))))
Now I realized, that the mocks can be common to all my tests, so I moved it up like so.
(with-redefs [id-gen/get-next-id mock/get-next-id
save-trade identity]
(deftest test-holdings
(testing "after 1 buy"
... test code
Now the new bindings are not used, the real dependencies are invoked - failing the test.
I see some posts on SO mentioning something about "direct linking" but I couldn't really fathom why it works in Case1 but not in Case2. If I move with-redefs back under the deftest form, it works again.
According to the docstring (https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/with-redefs), with-redefs restores the original value after executing the body. In the given case, the body defines a test. With-redefs thus governs the tests' definition, but not their execution. When the tests execute, any reference to get-next-id resolves that symbol to its current value, which by that time will be the real one, not the mock. (This follows logically: if case No.1 holds, and the docstring holds, then case No.2 could not hold.)
For reasons already mentioned in comments, with-redefs is not usually a tool of first choice. Clojure offers more robust techniques, e.g., make higher-order subsystems and use fixtures to configure them for testing.
I'm new on coding. My first lang is Clojure. And it's my first question on stackoverflow.
I wrote a Clj code, tested all functions on lein(Emacs/Cider) and I want to compile for testing. But Java methods returned this error message :
(on terminal in project folder):
aaron#debian:~/img-process$ lein check
Reflection warning, img_process/core.clj:25:30 - reference to field getWidth can't be resolved.
(and getHeight, getRGB, setRGB, java.io.File, javax.imeageio.ImageIO, java.lang.String)
Why lein can not see Java elements ?
How can I compile this ?
Thank you.
project.clj
https://github.com/harununal/clj-x-ray-coloring/blob/master/project.clj
core clj :
https://github.com/harununal/clj-x-ray-coloring/tree/master/src/img_process
If Clojure cannot imply the type of a Java object, it falls back on reflection for interop which is much slower. If you use:
(set! *warn-on-reflection* true)
Then you'll see these warnings at the REPL too. If you type hint your methods, then Clojure can see the types and emit much better code. e.g.
(defn get-img-coords
[^BufferedImage img]
(for [y (range (.getHeight img))
x (range (.getWidth img))]
[x y]))
Note that lein check isn't a compiler - it's the lein equivalent of a light linter, perhaps, checking for these warnings and others.
I've set up small project:
project.clj:
(defproject testing-compilation "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.8.0"]]
;; this is important!
:aot :all)
src/core.clj
(ns testing-compilation.core)
(def x (do
(println "Print during compilation?")
1))
Then when I do lein compile in project directory I'm seeing output from a print:
$ lein compile
Compiling testing-compilation.core
Print during compilation?
My question is: why clojure evaluates top level forms during AOT compilation? Shouldn't they be evaluated at program startup?
For reference, Common Lisp doesn't evaluate forms by default and provides ability to tune this behaviour. Anything similar in Clojure? If nothing, does Clojure documentation explicitly state such behaviour?
UPD: Forms are evaluated at startup as well.
After specifying a main namespace and writing main function that prints Hello, world!, I did this:
$ lein uberjar
Compiling testing-compilation.core
Print during compilation?
Created testing-compilation-0.1.0-SNAPSHOT.jar
Created testing-compilation-0.1.0-SNAPSHOT-standalone.jar
$ java -jar target/testing-compilation-0.1.0-SNAPSHOT-standalone.jar
Print during compilation?
Hello world!
The first part of the AOT process is to find the file containing the main namespace and load it by evaluating every expression from top to bottom.
Some of these expressions will be require expressions that will have the effect of loading other namespaces, which recursively load yet more namespaces.
Other will be defn expressions that will have the effect of firing up the compiler and producing class files. One class file is produced for each function.
Other expressions may do some calculation and then do things that produce class files, so it's important to give them a chance to run. Here's a made up example:
user> (let [precomputed-value (reduce + (range 5))]
(defn funfunfun [x]
(+ x precomputed-value)))
#'user/funfunfun
user> (funfunfun 4)
14
It is possible to design a lisp that would not evaluate top level forms at start or, as you mention, make it optional. In the case of Clojure it was decided to keep a single evaluation strategy across both AOT and "non AOT" loading so programs always run the same regardless of how they are compiled. These are personal design choices made by others so I can't speak to their motivations here.
I found the following code in enlive:
net.cgrand.enlive-html=> (source node-selector?)
(defn node-selector? [selector]
(not (fragment-selector? selector)))
and thought about refactoring it to the following code:
(def node-selector? (complement fragment-selector?))
How can I validate the completeness of the refactoring so all cases are properly handled with the change?
cough tests cough and thinking hard.
You have to ensure that the arguments and results domains haven't changed (special care when dealing with truthy values).
In this case the change seems innocuous BUT you lose something: doc doesn't document the arglist anymore.
Another subtle consequence: when you redefine fragment-selector?, node-selector? still refers to the old fragment-selector?.
Is there an idiomatic way to get available namespaces that can be used?
(all-ns) returns only already used namespaces. (Package/getPackages) returns all Java packages available for import, but only those Clojure namespaces that are already used.
Then I stumbled upon this post, but it uses some classpath magic.
So I want to get something like ('clojure.core 'clojure.set ... 'clojure.contrib.accumulators 'clojure.contrib.condition ...) if I have the clojure.jar and contrib.jar on my classpath, but I haven't used anything yet.
You will need to do "classpath magic". Since there is no kind of registry, you have to walk the classpath and look in every clojure source file to determine what namespaces are available. (In case the files are not AOT compiled. Otherwise you'll need a different heuristic.)
I think the function used in the linked post is the best way to go: clojure.contrib.find-namespaces/find-namespaces-on-classpath.
Deprecated since Clojure 1.3.0; use now clojure.tools.namespace.find/find-namespaces and clojure.java.classpath/classpath from http://github.com/clojure/java.classpath
I have found bultitude to be a great tool for doing this.
Example:
user=> (require '[bultitude.core :as b])
nil
user=> (take 10 (b/namespaces-on-classpath))
(bultitude.core-test bultitude.core clojure.data clojure.string clojure.test clojure.xml clojure.inspector clojure.repl clojure.set clojure.test.junit)
user=> (b/namespaces-on-classpath :prefix "bultitude")
(bultitude.core-test bultitude.core)