Technology moves fast! ⚡ Don't get left behind.🚶 Subscribe to our mailing list to keep up with latest and greatest in open source projects! 🏆


Subscribe to our mailing list

test.check

QuickCheck for Clojure

Subscribe to updates I use test.check


Statistics on test.check

Number of watchers on Github 811
Number of open issues 0
Main language Clojure
Average time to merge a PR about 20 hours
Open pull requests 1+
Closed pull requests 13+
Last commit over 1 year ago
Repo Created over 5 years ago
Repo Last Updated over 1 year ago
Size 1.07 MB
Organization / Authorclojure
Contributors22
Page Updated
Do you use test.check? Leave a review!
View test.check activity
View on github
Fresh, new opensource launches 🚀🚀🚀
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating test.check for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

test.check

test.check is a Clojure property-based testing tool inspired by QuickCheck. The core idea of test.check is that instead of enumerating expected input and output for unit tests, you write properties about your function that should hold true for all inputs. This lets you write concise, powerful tests.

Releases and Dependency Information

Release notes for each version are available in CHANGELOG.markdown. Remember that prior to version 0.5.7, test.check was called simple-check.

As of version 0.9.0, test.check requires Clojure >= 1.7.0.

Please note a breaking change for ClojureScript in the 0.8.* releases.

Latest Version

Leiningen

[org.clojure/test.check "0.10.0-alpha2"]

Maven

<dependency>
  <groupId>org.clojure</groupId>
  <artifactId>test.check</artifactId>
  <version>0.10.0-alpha2</version>
</dependency>

Stable Version

Leiningen

[org.clojure/test.check "0.9.0"]

Maven

<dependency>
  <groupId>org.clojure</groupId>
  <artifactId>test.check</artifactId>
  <version>0.9.0</version>
</dependency>

If you'd like to try a SNAPSHOT version, add the sonatype repository to your project.

Documentation

Useful libraries

Examples

Let's say we're testing a sort function. We want to check that that our sort function is idempotent, that is, applying sort twice should be equivalent to applying it once: (= (sort a) (sort (sort a))). Let's write a quick test to make sure this is the case:

(require '[clojure.test.check :as tc])
(require '[clojure.test.check.generators :as gen])
(require '[clojure.test.check.properties :as prop])

(def sort-idempotent-prop
  (prop/for-all [v (gen/vector gen/int)]
    (= (sort v) (sort (sort v)))))

(tc/quick-check 100 sort-idempotent-prop)
;; => {:result true, :num-tests 100, :seed 1382488326530}

In prose, this test reads: for all vectors of integers, v, sorting v is equal to sorting v twice.

What happens if our test fails? test.check will try and find 'smaller' inputs that still fail. This process is called shrinking. Let's see it in action:

(def prop-sorted-first-less-than-last
  (prop/for-all [v (gen/not-empty (gen/vector gen/int))]
    (let [s (sort v)]
      (< (first s) (last s)))))

(tc/quick-check 100 prop-sorted-first-less-than-last)
;; => {:result false, :failing-size 0, :num-tests 1, :fail [[3]],
       :shrunk {:total-nodes-visited 5, :depth 2, :result false,
                :smallest [[0]]}}

This test claims that the first element of a sorted vector should be less-than the last. Of course, this isn't true: the test fails with input [3], which gets shrunk down to [0], as seen in the output above. As your test functions require more sophisticated input, shrinking becomes critical to being able to understand exactly why a random test failed. To see how powerful shrinking is, let's come up with a contrived example: a function that fails if it's passed a sequence that contains the number 42:

(def prop-no-42
  (prop/for-all [v (gen/vector gen/int)]
    (not (some #{42} v))))

(tc/quick-check 100 prop-no-42)
;; => {:result false,
       :failing-size 45,
       :num-tests 46,
       :fail [[10 1 28 40 11 -33 42 -42 39 -13 13 -44 -36 11 27 -42 4 21 -39]],
       :shrunk {:total-nodes-visited 38,
                :depth 18,
                :result false,
                :smallest [[42]]}}

We see that the test failed on a rather large vector, as seen in the :fail key. But then test.check was able to shrink the input down to [42], as seen in the keys [:shrunk :smallest].

To learn more, check out the documentation links.

clojure.test Integration

The macro clojure.test.check.clojure-test/defspec allows you to succinctly write properties that run under the clojure.test runner, for example:

(defspec first-element-is-min-after-sorting ;; the name of the test
         100 ;; the number of iterations for test.check to test
         (prop/for-all [v (gen/not-empty (gen/vector gen/int))]
           (= (apply min v)
              (first (sort v)))))

ClojureScript

ClojureScript support was added in version 0.7.0.

The first test.check example needs only minor modifications for ClojureScript:

(ns cljs.user
  (:require [clojure.test.check :as tc]
            [clojure.test.check.generators :as gen]
            [clojure.test.check.properties :as prop :include-macros true]))

(def sort-idempotent-prop
  (prop/for-all [v (gen/vector gen/int)]
    (= (sort v) (sort (sort v)))))

(tc/quick-check 100 sort-idempotent-prop)
;; => {:result true, :num-tests 100, :seed 1382488326530}

The remaining examples need no further changes. Integrating with cljs.test is via the clojure.test.check.clojure-test/defspec macro, in the same fashion as integration with clojure.test on the jvm.

Developer Information

We can not accept pull requests. Please see CONTRIBUTING.md for details.

Links

Tests

test.check runs in both jvm-clojure and clojurescript, so testing comprehensively requires several steps:

  • Run lein test to run the JVM tests (requires Leiningen)
  • Run lein cljsbuild once to run the ClojureScript tests (also requires node.js)
  • To run the same tests in a web browser, open (after running the above command) test-runners/run_tests_dev.html and test-runners/run_tests_adv.html and watch the javascript console for output
  • Run script/test-self-host to run the self-hosted ClojureScript tests (also requires node.js)

See also

Other implementations

Papers

simple-check

test.check used to be called simple-check.

See migrating from simple-check.

Contributing

YourKit

YourKit

YourKit is kindly supporting test.check and other open source projects with its full-featured Java Profiler. YourKit, LLC is the creator of innovative and intelligent tools for profiling Java and .NET applications. Take a look at YourKit's leading software products:

License

Copyright 2014 Rich Hickey, Reid Draper and contributors

Distributed under the Eclipse Public License, the same as Clojure.

test.check open pull requests (View All Pulls)
  • updating copyright year
test.check questions on Stackoverflow (View All Questions)
  • test.check generate tree with different node types
  • How do I create a test.check generator for a sequence of actions in a constrained order?
  • How to generate UUIDs that can work with test.check in Clojure
  • How do you generate collections with a specific property (like stddev) using test.check
  • test.check: let-style behaviour in 'properties/for-all'
  • Generating sorted data with test.check
  • Generating structured maps with test.check
  • combining test.check and clojure test
test.check list of languages used
Other projects in Clojure