David J.
David J.

Reputation: 32715

Run one Clojure test (not all tests in a namespace), with fixtures, from the REPL

How do I run one test (not a whole namespace) from the Clojure REPL?

I've tried calling the function directly, e.g. (the-ns/the-test) but I need fixtures to run first. So I want to find a way to start the tests from clojure.test.

This is close but not a match for what I want to do: https://stackoverflow.com/a/24337705/109618

I don't see any mention of how to do it from the clojure.test API.

Upvotes: 32

Views: 10783

Answers (5)

orestis
orestis

Reputation: 17200

It's 2025, and the answer is clojure.test/run-test, or clojure.test/run-test-var like so:

(defn my-fixture [f]
  ;; do things
  ;; invoke test
  (f)
  ;; cleanup things
  )

(clojure.test/use-fixtures :once my-fixture)

(deftest my-test 
 (is (= 1 2)))

(clojure.test/run-test my-test)

;; or

(clojure.test/run-test-var #'my-test)

Upvotes: 0

Ray H
Ray H

Reputation: 333

A nice alternative to clojure.test (if you're OK adding additional dependencies is eftest). This library is an alternative runner (it is compatible with clojure.test). It has flexible tests selectors (i.e. by folder, by namespace, by var).

In a REPL, you're able to execute something like this:

(require '[eftest.runner :refer [find-tests run-tests]])

(run-tests (find-tests #'foo.bar/baz))

See https://github.com/weavejester/eftest

Upvotes: 2

Atty
Atty

Reputation: 801

To run a single test in a namespace:

lein test :only namespace_name/testname

To run a all tests in one namespace

lein test :only namespace_name

Upvotes: 6

Alex Miller
Alex Miller

Reputation: 70239

There was a new function added in Clojure 1.6 to support this. clojure.test/test-vars will run one or more test vars with fixtures.

I think something like this should work:

(clojure.test/test-vars [#'the-ns/the-test])

Upvotes: 46

optevo
optevo

Reputation: 2104

If you don't mind not running fixtures, you could do the following before you call run-tests:

(defn test-ns-hook []
  (my-test))

To remove the hook, you can do

(ns-unmap *ns* 'test-ns-hook)

If you still need your fixtures and want to stay with one test namespace, you could add an ns-unmap to remove all the tests/fixtures you don't want to run from the namespace before running your tests modelled on something like:

(doseq [v (keys (ns-publics 'my-ns))]
  (let [vs (str v)]
    (if (.startsWith vs "test-") (ns-unmap 'my-ns v))))

It might be easier to work with multiple namespaces, one of which contains all your tests and fixtures and in other namespace(s) refer to the tests and fixtures you want to run from you main test namespace. You could then use ns to switch to a specific test namespace or pass run-tests the namespace(s) you want to test:

(ns test-main
  (:require [clojure.test :refer :all]))

(deftest addition
  (is (= 4 (+ 2 2)))
  (is (= 7 (+ 3 4))))

(deftest subtraction
  (is (= 1 (- 4 3)))
  (is (= 3 (- 7 4))))

(run-tests)
;Runs all the tests

(ns test-specific
(:require [clojure.test :refer :all]
          [test-main :refer :all]))

(deftest arithmetic
  (subtraction))

(run-tests)
;Just runs the tests you want

Upvotes: 5

Related Questions