0.5.15 docs





    Mar 7, 2017

    David Kazlauskas


    Index of all namespaces

    « Project + dependencies

    Slothtest - simple automatic testing solution



    A add-key-to-dissoc-wrap add-node-index add-test-expr api-v1-to-v2 approve-next-breakage atom?

    B *breakage* build-node-index

    C call-last-capture capture-function curr-test-struct current-ordering-map

    D *diffcmd* default-ns-decl default-struct defdesc defsuite delete-next-breakage delete-node diff-cmd diff-next-breakage diff-two-structs dissoc-expression dissoc-in dissoc-next-expression dissoc-wrap drop-nils-from-map drop-specification

    E ensure-correct-class-name ensure-correct-namespace-name ensure-correct-suite-name eval-or-execpt expand-spec expand-spec-sq expect-spec expr-of-dissoc-wrap

    G gen-ns-decl gen-test-def-v2 generic-symb-check generic-symb-with-dots-check group-up-tests

    I if-replace is-symbol-dissoc-wrap

    K keys-for-dissoc-wrap

    L *lastcapture* last-capture last-capture-still-valid

    M map-recursive-type-preserve

    N *notestns* next-breakage next-expression next-expression-value node-eval-equality notestns ns-resolve-list

    P ppr pull-namespaces

    R read-curr-test-src read-project-name-from-lein remove-functions remove-spec remove-test-expr rename-symbol render-is-clauses render-suites render-testing-node require-expression-dependencies rjames

    S save-last-capture save-last-capture-eval save-spec save-spec-sq save-specification save-struct single-node-eval skip-next-breakage slothtest-class slothtest-ns sort-result-expr struct-to-source-v2 structure-test symbol-set

    T *testfileclass* temp-file test-path test-suite testfileclass testing-desc try-skip-next-breakage two-nl-join

    U underscores-instead-dashes update-breakage update-node update-node-by-expr upgrade-test-struct

    V v1-node-to-v2 view-last-capture

    W wrap-struct-diff-error

    The README below is fetched from the published project artifact. Some relative links may be broken.


    Clojars Project

    Is this you?


    Then you’ve found a perfect testing solution for clojure!

    We tend to do a lot of testing in clojure when we evaluate repl expressions. Now you have power to save your evaluated repl commands without doing anything.


    Say, you want to ensure that (+ 1 2) is always 3 but you don’t want to write test. How to do that?

    Evaluate expression:

    (+ 1 2)

    If you like the result simply evaluate it with :

    (ns mynamespace.core
      (:require [slothtest.core :refer :all]))
    (save-spec (+ 1 2))

    This will evaluate (+ 1 2) and save the result in source test/mynamespace/autogen_test.clj. Of course, it is a good idea to only test pure functions with sloth test.

    You did not even have to specify the result. However, if you wanted you could:

    (ns mynamespace.core
      (:require [slothtest.core :refer :all]))
    (expect-spec (+ 1 2) 3)

    What about duplicates?

    If you evaluate (+ 1 2) list multiple times the last one will be saved. (+ 1 2) is saved as a simple list, therefore, has unique key in the hash map.

    Removing expression

    If something got stale and you don’t want to open test generation file remove it with:

    (remove-spec (+ 1 2))

    Symbols don’t have to exist, so, if function is gone, you can just remove typing non-existant expression.

    Syntax quoted tests

    If you need evaluate expression with local variables it could be done like so:

      `(for [~'i [1 2 3]] (* 2 ~'i)))

    This will save result as (2 4 6). However, avoid using # notation for locals as these will always be unique and will not be replaced on multiple evaluations.


    Default test namespace is read from project.clj (as project name), however, it may be changed with:

    (slothtest-ns somenamespace)

    Test class name

    Default test source name is “autogen_test”, this can be changed with

    (slothtest-class someclassname)

    Breakage viewer

    Starting with slothtest 0.3.0 breakage viewer is added. Say you break some tests and want to review where. You don’t have to leave repl. You can just run:


    If repl returns anything above 0, some breakage was introduced.

    To see the next expression of what broke call:


    You can diff it with:


    This calls external diff command to differentiate output as text. Default diff command might be replaced with environment variable:

    # default
    export SLOTHTEST_DIFFCMD="diff -y '%1$s' '%2$s'"
    # using python cdiff tool, copy temporary files as sloth.a and sloth.b and view it as colored diff
    # then you can watch sloth.diff in the next window seeing colored output.
    # BY THE WAY, If someone knows how to make vim-fireplace plugin show ansi-colored text in evaluation output
    # please tell me.
    export SLOTHTEST_DIFFCMD="cp '%1\$s' ./sloth.a && cp '%2\$s' ./sloth.b && diff -u '%1\$s' '%2\$s' | cdiff -c always -s -w 50 | tee ./sloth.diff"

    To get all the data about next breakage call:


    Say you have decided if breakage is appropriate. Now you have three choices: - Skip breakage - will skip it, and will move to the next one, it will appear again calling update-breakage - Try skip breakage - run next breakage test again and if it succeeds skip it - Approve breakage - agree with it and update the test result - Delete breakage - delete the entire test that broke



    Try to skip breakage if the test passes gain:






    Capture expression in flight

    Ever had some deep nested code and would like to take a snapshot of a function call with arguments in specific time and specific place? Now you can do that. Simply wrap any expression in your code with capture-function and view it later, if you like the result - save it.

    ; seamless: program flow is uninterrupted
    ; and result saved.
      (* 3
        (capture-function (+ (- 3 2) 2))))

    View the results:

    ; view last result
    (is (= (last-capture) {:inputs (clojure.core/+ 1 2), :outputs 3}))
    ; pretty print last result
    ; Check if calling function again with
    ; same parameters still yields the same result
    ; Call last capture and return the result
    ; Save last capture to test suite.
    ; Optional test suite name and specification
    ; description arguments are supported.
    (save-last-capture :suite "some_suite")

    Selecting test suite name and specification description

    Default test suite name will be “autogen” and default description will be “Autogenerated”. Someone might want to split these up, make test suite name descriptive. They can do so with:

    (save-spec (+ 1 2) :suite "some_valid_symbol" :description "This tests basic arithmetic")

    Renaming symbol in tests automatically

    Feared of renaming a function? Rename them in tests with one call to rename-symbol

    ; find every symbol in tests to 'some.namespace/foo
    ; and replace it with 'some.namespace/bar
    (rename-symbol 'some.namespace/foo 'some.namespace/bar)

    Nested unwanted values in map

    From time to time test maps have some indeterministic values, like random numbers. They can be removed simply by dissociating next expression when updating breakages. More than one key can be dissociated from a map.

    ; expression with random number
    (save-spec {:a 1 :b {:c (rand-int 100)}})
    ; update breakage - chances are, this function is breaking when run again
    ; dissociate the key that you want to remove in map (multiple keys can be added)
    (dissoc-next-expression :b :c)
    ; once it is good enough approve the breakage

    Removing compiled pesky functions

    Sometimes expression contains compiled clojure functions that cannot be serialized back when reading. You can wrap any expression with remove-functions function and every single instance of a compiled function will be replaced by a :COMPILED_FUNCTION keyword recursively.

    ; saved as '(:a :b [:c :d {:e :COMPILED_FUNCTION}])
    (save-spec (remove-functions '(:a :b [:c :d {:e +}])))

    Happy time spent developing instead of writing tedious repetitive tests!