Coder Social home page Coder Social logo

clojure-expectations / clojure-test Goto Github PK

View Code? Open in Web Editor NEW
122.0 6.0 7.0 338 KB

A clojure.test-compatible version of the classic Expectations testing library.

Home Page: https://cljdoc.org/d/com.github.seancorfield/expectations/CURRENT

License: Eclipse Public License 1.0

Clojure 99.80% Dockerfile 0.20%

clojure-test's Introduction

clojure.test for Expectations Open in Gitpod

A clojure.test-compatible version of the classic Expectations testing library.

Where?

Clojars cljdoc badge Slack Join Slack

Try it out:

clj -Sdeps '{:deps {com.github.seancorfield/expectations {:mvn/version "RELEASE"}}}'

What?

This library provides a more expressive way to write tests than clojure.test, while still being fully compatible with clojure.test and all its tooling.

While clojure.test provides basic assertions using (is (= ... ...)) and (is (thrown? ... ...)), Expectations additionally supports predicates, regular expressions, Specs, and collection-based tests.

You can either "mix'n'match" clojure.test and expectations.clojure.test features in your tests, using deftest from clojure.test or defexpect from this library to wrap your tests, or you can use expectations.clojure.test on its own, since it exposes equivalents to all of the top-level clojure.test functions and macros for dealing with fixtures and running tests.

The following are equivalent:

(deftest my-test-1
  (is (= 2 (+ 1 1)))
  (is (thrown? ArithmeticException (/ 1 0))))

(defexpect my-test-2
  (expect 2 (+ 1 1))
  (expect ArithmeticException (/ 1 0)))

But you can also do things like:

(defexpect my-test-3
  (expect even? (+ 1 1))
  (expect #"foo" "It's foobar!")
  (expect ::adult-age 42)) ; ::adult-age is a Spec

See the example REPL session below for more details.

This library has no dependencies, other than clojure.test itself, and should be compatible with all existing clojure.test-based tooling in editors and command-line tools.

Works with Clojure 1.9 and later.

Works in self-hosted ClojureScript (specifically, planck). See Getting Started with ClojureScript for details.

Example REPL Session

What follows is an example REPL session showing some of what this library provides. For more detailed documentation, start with Getting Started and work your way through the sections listed there.

(ns my.cool.project-test
  (:require [clojure.spec.alpha :as s]
            [clojure.test :refer [deftest is]]
            [expectations.clojure.test
             :refer [defexpect expect expecting
                     approximately between between' functionally
                     side-effects]]))

;; mix'n'match libraries:

(deftest mixed
  (is (= 2 (+ 1 1)))
  (expect even? (+ 1 1)))

;; simple equality tests:

(defexpect equality
  (expect 1 (* 1 1))
  (expect "foo" (str "f" "oo")))

;; the expected outcome can be a regular expression:

(defexpect regex-1
  (expect #"foo" "It's foobar!"))

;; since that has only a single expectation, it can be written more succinctly:

(defexpect regex-2 #"foo" "It's foobar!")

;; the expected outcome can be an exception type:

(defexpect divide-by-zero ArithmeticException (/ 12 0))

;; the expected outcome can be a predicate:

(defexpect no-elements empty? (list))

;; the expected outcome can be a type:

(defexpect named String (name :foo))

;; the expected outcome can be a Spec:

(s/def ::value (s/and pos-int? #(< % 100)))
(defexpect small-value
  (expect ::value (* 13 4)))

;; if the actual value is a collection, the expected outcome can be an element or subset "in" that collection:

(defexpect collections
  (expect {:foo 1} (in {:foo 1 :cat 4}))
  (expect :foo (in #{:foo :bar}))
  (expect :foo (in [:bar :foo])))

;; just like clojure.test's testing macro to label groups of tests
;; you can use expecting to label groups of expectations (this uses
;; some of more advanced features listed below):

(defexpect grouped-behavior
  (expecting "numeric behavior"
    (expect (more-of {:keys [a b]}
                     even? a
                     odd?  b)
            {:a (* 2 13) :b (* 3 13)})
    (expect pos? (* -3 -5)))
  (expecting "string behavior"
    (expect (more #"foo" "foobar" #(clojure.string/starts-with? % "f"))
            (str "f" "oobar"))
    (expect #"foo"
            (from-each [s ["l" "d" "bar"]]
              (str "foo" s)))))

Just like deftest, the defexpect macro creates a function that contains the test(s). You can run each function individually:

user=> (equality)
nil

If the test passes, nothing is printed, and nil is returned. Let's look at a failing test:

user=> (defexpect inequality (* 2 21) (+ 13 13 13))
#'user/inequality
user=> (inequality)

FAIL in (inequality) (.../README.md:117)
expected: (=? (* 2 21) (+ 13 13 13))
  actual: (not (=? 42 39))
nil

The output is produced by clojure.test's standard reporting functionality. The =? operator is an extension to clojure.test's assert-expr multimethod that allows for Expectations style of predicate-or-equality testing (based on whether the "expected" expression resolves to a function or some other value):

user=> (defexpect not-at-all-odd odd? (+ 1 1))
#'user/not-at-all-odd
user=> (not-at-all-odd)

FAIL in (not-at-all-odd) (.../README.md:133)
expected: (=? odd? (+ 1 1))
  actual: (not (odd? 2))
nil

Here we see the predicate (odd?) being applied in the "actual" result from clojure.test.

Just like the is macro, expect can take an optional failure message as the third argument:

user=> (defexpect failure-msg
         (expect even? (+ 1 1 1) "It's uneven!"))
#'user/failure-msg
user=> (failure-msg)

FAIL in (failure-msg) (.../README.md:149)
It's uneven!
expected: (=? even? (+ 1 1 1))
  actual: (not (even? 3))
nil

Why?

TL;DR: Because I liked the "Classic" Expectations library but didn't like having to use custom, Expectations-specific tooling.

Why not just use clojure.test?

clojure.test is a great library for writing tests in Clojure. It's simple, it's built-in, and it's widely supported by the Clojure ecosystem. However, it only provides basic assertions and doesn't support some of the more advanced testing features that Expectations does.

Why not just use the "Classic" Expectations library?

Given the streamlined simplicity of Expectations, you might wonder why you would want to migrate your Expectations test suite to clojure.test-style named tests? The short answer is tooling! Whilst Expectations has well-maintained, stable plugins for Leiningen and Boot, as well as an Emacs mode, the reality is that Clojure tooling is constantly evolving and most of those tools -- such as the excellent CIDER, Cursive, Calva (for VS Code), and Cognitect's test-runner -- are going to focus on Clojure's built-in testing library first. Support for the original form of Expectations, using unnamed tests, is non-existent in Cursive, and can be problematic in other editors and tooling.

A whole ecosystem of tooling has grown up around clojure.test and to take advantage of that with Expectations, we either need to develop compatible extensions to each and every tool or we need Expectations to be compatible with clojure.test.

One of the big obstacles for that compatibility is that, by default, Expectations generates "random" function names for test code (the function names are based on the hashcode of the text form of the expect body), which means the test name changes whenever the text of the test changes. To address that, the new expectations.clojure.test namespace introduces named expectations via the defexpect macro (mimicking clojure.test's deftest macro). Whilst this goes against the Test Names philosophy that Expectations was created with, it buys us a lot in terms of tooling support!

Compatibility with "Classic" Expectations

expectations.clojure.test supports the following features from the "Classic" Expectations library so far:

  • simple equality test
  • simple predicate test
  • spec test (using a keyword that identifies a spec)
  • class test -- see named above
  • exception test -- see divide-by-zero above
  • regex test -- see regex-1 and regex-2 above
  • (expect expected-expr (from-each [a values] (actual-expr a)))
  • (expect expected-expr (in actual-expr)) -- see collections above
  • (expect (more-of destructuring e1 a1 e2 a2 ...) actual-expr)
  • (expect (more-> e1 a1 e2 a2 ...) actual-expr) -- where actual-expr is threaded into each a1, a2, ... expression
  • (expect (more e1 e2 ...) actual-expr)
  • (expect expected-expr (side-effects [fn1 fn2 ...] actual-expr))

Read the Expectations documentation for more details of these features.

Differences from "Classic" Expectations

Aside from the obvious difference of providing names for tests -- essential for compatibility with clojure.test-based tooling -- here are the other differences to be aware of:

  • You use standard clojure.test-based tooling -- lein test, boot test, and Cognitect's test-runner -- instead of the Expectations-specific tooling.
  • Because of that, tests run when you decide, not at JVM shutdown (which is the default with Expectations).
  • If you have Paul Stadig's Humane Test Output on your classpath, it will be activated and failures reported by =? will be compatible with it, providing better reporting.
  • Instead of the in-context, before-run, after-run machinery of Expectations, you can just use clojure.test's fixtures machinery (use-fixtures). As of 2.0.0, use-fixtures is exposed directly via expectations.clojure.test so you don't need to require clojure.test.
  • Instead of Expectations' concept of "focused" test, you can use metadata on tests and tell your test runner to "select" tests as needed (e.g., Leiningen's "test selectors", Boot's "filters", and test-runner's -i/-e options).
  • freeze-time, redef-state, and warn-on-iref-updates are not (yet) implemented.
  • The undocumented CustomPred protocol is not implemented -- you can use plain is and extend clojure.test's assert-expr multimethod if you need that level of control.

Test & Development

To test, run clj -X:test (tests against Clojure 1.9).

Multi-version testing:

for v in 1.9 1.10 1.11 1.12
do
  clojure -X:test:$v
done

You can also run the tests with Humane Test Output enabled but you need to exclude the negative tests because they assume things about the test report data that HTO modifies:

for v in 1.9 1.10 1.11 1.12
do
  clojure -X:test:$v:humane :excludes '[:negative]'
done

ClojureScript testing

The ClojureScript version requires self-hosted ClojureScript (specifically, planck). Once you have planck -h working, you can run the ClojureScript tests with:

clojure -M:cljs-runner -e :negative

You can run the negative tests as well if you modify one line of test.cljc, see the comments below the line containing (def humane-test-output?.

ClojureScript REPL

It can be handy to try things in a REPL. You can run a REPL for ClojureScript by doing:

$ planck --compile-opts planckopts.edn -c `clojure -Spath -A:humane` -r
ClojureScript 1.10.520
cljs.user=> (require '[expectations.clojure.test :refer-macros [defexpect expect]])
nil
cljs.user=> (defexpect a (expect number? 1))
#'cljs.user/a
cljs.user=> (a)
nil
cljs.user=> (defexpect a (expect number? :b))
#'cljs.user/a
cljs.user=> (a)

FAIL in (a) (run_block@file:44:173)


expected: (=? number? :b)
  actual: (not (number? :b))
nil
cljs.user=>

This will set you up with defexpect and expect. Add others as required.

License & Copyright

Copyright © 2018-2024 Sean Corfield, all rights reserved.

Distributed under the Eclipse Public License version 1.0.

clojure-test's People

Contributors

kkinnear avatar seancorfield avatar tvedeane avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

clojure-test's Issues

Usage report on 2.0.0-alpha2

Hello!

I just recently noticed that you moved to 2.0.0-alpha2. I tried it with the zprint tests, and it works great for both cli and cljs:

√ projects/zprint % lein with-profile expectations test
Retrieving com/github/seancorfield/expectations/2.0.0-alpha2/expectations-2.0.0-alpha2.pom from clojars
Retrieving com/github/seancorfield/expectations/2.0.0-alpha2/expectations-2.0.0-alpha2.jar from clojars

lein test zprint.config-test

lein test zprint.core-test

lein test zprint.finish-test

lein test zprint.guide-test

lein test zprint.main-test

lein test zprint.range-test

lein test zprint.rewrite-test

lein test zprint.spec-test

lein test zprint.zprint-test

lein test zprint.zutil-test

Ran 10 tests containing 1383 assertions.
0 failures, 0 errors.
√ projects/zprint % clj -A:cljs-runner
WARNING: Use of :main-opts with -A is deprecated. Use -M instead.

Testing zprint.config-test

Testing zprint.core-test

Testing zprint.finish-test

Testing zprint.guide-test

Testing zprint.main-test

Testing zprint.range-test

Testing zprint.rewrite-test

Testing zprint.spec-test

Testing zprint.zprint-test

Testing zprint.zutil-test

Ran 9 tests containing 1291 assertions.
0 failures, 0 errors.

Thanks for moving things forward! I'll upgrade zprint to use 2.0.0-alpha2 now.

Cheers -- Kim

Improve side-effects docs

Make it clear that it is intended to replace "dumb mocks" only and if you need a "smart mock", use with-redefs.

Perhaps show what it is equivalent to?

Also, make clear that you can use to mock a specific result value, not map to another function to call.

defexpect with a single expression should behave like deftest

Currently, a defexpect whose body is one or two expressions with no embedded expect is treated as shorthand for an expect with those expressions. That's fine for two expressions:

(defexpect my-name (expected-expr) (actual-expr))
;; becomes
(defexpect my-name (expect (expected-expr) (actual-expr)))

But for a single expression, this means a difference of behavior compared to deftest:

(defexpect my-name (actual-expr))
;; becomes
(defexpect my-name (expect (actual-expr)))
;; which is treated as
(deftest my-name (is (actual-expr)))

But a single expression in the body of a deftest is just "odd" and behaves like a regular function:

(deftest my-name (actual-expr))

That just runs the code as-is, no assertions. I think the single-bodied defexpect above should behave the same way (perhaps with a warning on macroexpansion).

Support ClojureScript?

I don't do cljs at all so I've no idea what is needed here, nor how to ensure tests run for the cljs version so contributions are welcome!

Create proper clj-kondo hooks for various macros

more-of, more->, maybe others.

The following works for more->:

(ns hooks.expectations.clojure.test.more-thread
  (:require [clj-kondo.hooks-api :as api]))

(defn more-> [{:keys [node]}]
  (let [tail (rest (:children node))
        rewritten
        (api/list-node
         (list*
          (api/token-node 'cond->)
          (api/token-node 'nil)
          tail))]
    {:node rewritten}))

more / more-> cause multiple evaluation; more-of does not

Downloading: com/bhauman/rebel-readline/maven-metadata.xml from clojars
[Rebel readline] Type :repl/help for online help info
user=> (require '[expectations.clojure.test :refer :all])
nil
user=> (def c (atom 0))
#'user/c
user=> (defn f [] (swap! c inc))
#'user/f
user=> (expect (more-of a number? a number? a number? a) (f))
true
user=> @c
1
user=> (expect (more number? number? number?) (f))
true
user=> @c
4
user=> (expect (more-> number? identity number? identity number? identity) (f))
true
user=> @c
7
user=> 

Maybe document with-test?

clojure.test/with-test allows tests to be defined around a function definition. I've never seen anyone do this but it does work with expectations too:

(with-test 
  (defn foobar [x] 
    (* 2 x)) 
  (expect 4 (foobar 2)) 
  (expect even? (foobar 13)))
(foobar 1) ;=> 2
(test-vars [#'foobar]) ; runs the tests

Improve failure case for in collection

Currently, this prints an inequality failure for each non-matching element (which could be huge) and the failure message is ignored.

Also, the failed expression is not well-reported.

Tests having exactly two assertions fails when at least one of the assertions is a 'thrown?' assertion

Repository with code.

$ ./bin/kaocha 
[(.)(..F..F..F..F)(.............)]

FAIL in core-case2-test/foo-test (core_case2_test.clj:8)
(t/expecting "returns :b when :b" (t/expect :b (c/foo :b)))

Expected:
  #<java.lang.IllegalArgumentException@5f92e5eb java.lang.IllegalArgumentException: input is :a>
Actual:
  -#<java.lang.IllegalArgumentException@5f92e5eb java.lang.IllegalArgumentException: input is :a>
  +true

FAIL in core-case2-test/foo-test--another-order (core_case2_test.clj:15)
(t/expecting "throws when :a" (t/expect IllegalArgumentException (c/foo :a)))

Expected:
  true
Actual:
  -true
  +#<java.lang.IllegalArgumentException@335cbcbd java.lang.IllegalArgumentException: input is :a>

FAIL in core-case2-test/foo-test--two-thrown (core_case2_test.clj:22)
(t/expecting "throws when :a" (t/expect IllegalArgumentException (c/foo :a)))

Expected:
  #<java.lang.IllegalArgumentException@64c79b69 java.lang.IllegalArgumentException: input is :a>
Actual:
  -#<java.lang.IllegalArgumentException@64c79b69 java.lang.IllegalArgumentException: input is :a>
  +#<java.lang.IllegalArgumentException@a94c8e3 java.lang.IllegalArgumentException: input is :a>

FAIL in core-case2-test/foo-test--wo-expecting (core_case2_test.clj:29)
(t/expect :b (c/foo :b))

Expected:
  #<java.lang.IllegalArgumentException@54ee423f java.lang.IllegalArgumentException: input is :a>
Actual:
  -#<java.lang.IllegalArgumentException@54ee423f java.lang.IllegalArgumentException: input is :a>
  +true
9 tests, 26 assertions, 4 failures.

clj-kondo hook for the single test version of defexpect

The single test version of defexpect with an expected string can throw spurious errors, tho I think this is a clj-kondo issue and not an expectations issue.

(defexpect missing-body-in-when-test
  "Missing body in when"
  (:message (check-str "(when true)")))

"Missing body in when" is labeled as a "missing docstring" currently, due to the :lint-as rule tying defexpect to deftest.

Originally posted by @NoahTheDuke in #29 (comment)

defexpect 3-arg fails with alternate assertions

Hey Sean!

I have a macro that creates some set-up and then calls expect on the results:

(defmacro expect-match
  ([expected s] `(expect-match ~expected ~s nil))
  ([expected s config]
   `(let [diagnostics# (check-all ~s ~config)]
      (expect (~'match? ~expected diagnostics#)))))

This works perfectly when I put it in defexpect calls, except when I put two of them in a row with no other calls:

(ns noahtheduke.splint.expectations-test
  (:require
   [expectations.clojure.test :refer [defexpect]]
   [noahtheduke.splint.test-helpers :refer [expect-match]]))

(defexpect example-test
  (expect-match nil "#_:splint/disable (+ x 1)")
  (expect-match nil "(+ 1 x)"))

If they both pass, then it says there's 3 passing tests, and if one of them fails, it shows two failures, the second being the mismatch between the first assertion and the second assertion:

Testing noahtheduke.splint.expectations-test

FAIL in (example-test) (NO_SOURCE_FILE:8)
expected: (match? nil diagnostics__28464__auto__)
  actual: (mismatch
 (expected nil)
 (actual ({...})))


FAIL in (example-test) (NO_SOURCE_FILE:6)
(expect-match nil "(+ 1 x)")

expected: (=? (expect-match nil "#_:splint/disable (+ x 1)") (expect-match nil "(+ 1 x)"))
  actual: (not (=? true false))

Ran 1 tests containing 3 assertions.
2 failures, 0 errors.
{:test 1, :pass 1, :fail 2, :error 0, :type :summary}

Is there a way to avoid this behavior besides using plain deftest? I don't mind doing that, but it's nice when I can :require the one library instead of both (having to pay attention to when I have exactly two assertions in a form).

Improve README (add "why", clarify "what")

The README should be standalone and not depend on knowledge of "classic" Expectations.

It should also clearly answer the question: why should I use Expectations instead of clojure.test?

Add support for expecting a subset

It would be great to be able to check that the actual result sequence contains some elements, something like:

(expect #{1 2} (in #{0 1 2 3 4}))

Document focus/selectors

Expectations has expect-focused. Most clojure.test runners have a more general system based on metadata keywords on named tests. Document it at least for Leiningen and Cognitect's test-runner.

expect causes ClassCastException with sorted-map

First of all thank-you for this library! I've been happily using it for years :)

Using a sorted-map with non-keyword keys causes a ClassCastException. The issue originates in ->test-report when x is a map and the code is trying to lookup the keys ::e/more, ::e/in-flag, ::e/from-each-flag. In my case the map is a sorted map with integer keys, and comparison between Keyword and Long causes Clojure to throw an error.

Happy to help look into this and put together a PR if it makes sense. Wanted to get your input/guidance first though.

  ;; throws ClassCastException
  (expect (sorted-map 1 2) (sorted-map 1 2))
  (expect {1 2} (sorted-map 1 2))
  (expect {"a" 1} (sorted-map "a" 1))

  ;; no errors. works as expected with keyword keys
  (expect {:a 1} (sorted-map :a 1))

  ;; no issues with sorted sets
  (expect (sorted-set 1) (sorted-set 1 2))
  (expect #{1} (sorted-set 1))
1. Unhandled java.lang.ClassCastException
   class java.lang.Long cannot be cast to class clojure.lang.Keyword
   (java.lang.Long is in module java.base of loader 'bootstrap';
   clojure.lang.Keyword is in unnamed module of loader 'app')

              Keyword.java:  122  clojure.lang.Keyword/compareTo
                 Util.java:  153  clojure.lang.Util/compare
                   RT.java:  283  clojure.lang.RT$DefaultComparator/compare
    PersistentTreeMap.java:  330  clojure.lang.PersistentTreeMap/doCompare
    PersistentTreeMap.java:  317  clojure.lang.PersistentTreeMap/entryAt
    PersistentTreeMap.java:  297  clojure.lang.PersistentTreeMap/valAt
    PersistentTreeMap.java:  302  clojure.lang.PersistentTreeMap/valAt
    KeywordLookupSite.java:   45  clojure.lang.KeywordLookupSite$1/get
                  test.clj:   46  expectations.clojure.test/->test-report
                  test.clj:   36  expectations.clojure.test/->test-report
                      REPL:   24  user/eval70863

Enable three-argument expect with message

  • (expect a) is supported like (is a)
  • (expect e a) is supported like (is (= e a)) (and its variants)
  • (expect e a msg) is not supported, so there's not equivalent to (is expr msg)

This would require pushing ex? and e' one argument further -- or breaking expect into two macros, one documented, one not, which might be better...?

Like-expected behaviour for maps val inside in

Expectations uses the format (expect expected actual) for all tests. It looks convenient if we could check the values inside the keys expected-way.

(expect {:foo 1 :bar #"foo" :baz integer? :not-checked-key :any-value}
        (in {:foo 1 :bar "boofooar" :baz 8}))

Improve more-> / more-of docs with exception example

user=> (expect (more-> clojure.lang.ExceptionInfo type
  #_=>                 (more-of {:keys [status responseCode]}
  #_=>                           409 status
  #_=>                           4001110 responseCode) ex-data)
  #_=>         (ex-info "boo" {:status 409 :responseCode 4001110}))
true

expect with expressions-as-predicate don't always work as expected

@camsaul highlighted this difference from "classic" Expectations:

seanc@DESKTOP-30ICA76:~/clojure$ clj -Sdeps '{:deps {expectations/expectations {:mvn/version "RELEASE"}}}'
Clojure 1.10.3
user=> (use 'expectations)
nil
user=> (expect (re-pattern "\\d+") "1000")
#'user/expect1608036982
user=>

Ran 1 tests containing 1 assertions in 3 msecs
0 failures, 0 errors.
seanc@DESKTOP-30ICA76:~/clojure$ clj -Sdeps '{:deps {com.github.seancorfield/expectations {:mvn/version "RELEASE"}}}'
Clojure 1.10.3
user=> (use 'expectations.clojure.test)
nil
user=> (expect (re-pattern "\\d+") "1000")

FAIL in () (NO_SOURCE_FILE:1)
"1000"

expected: (=? (re-pattern "\\d+") "1000")
  actual: (not (=? #"\d+" "1000"))
false
user=>

This is not an intentional change but likely happens because e.c.t tries to determine, at macro expansion time, how to run the predicate test under the hood.

Add expect-not

expect-not would assert (not (expect ..))

Not sure how far reaching this would be (consider the binary defexpect shortcut).

Document fixtures

Need to show how to use clojure.test's use-fixtures -- since the documentation for it is pretty awful and Expectations has a completely different way to handle this.

No equivalent to thrown-with-msg?

clojure.test has thrown-with-msg? which lets you test for both the exception type and the message -- show how this can be done with expectations.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.