All Projects → athos → Pinpointer

athos / Pinpointer

Licence: epl-1.0
Pinpointer is yet another clojure.spec error reporter based on a precise error analysis

Programming Languages

clojure
4091 projects
clojurescript
191 projects

Labels

Projects that are alternatives of or similar to Pinpointer

Ghost Lang
👻 A friendly little language for you and me.
Stars: ✭ 296 (+221.74%)
Mutual labels:  spec
Spected
Validation library
Stars: ✭ 717 (+679.35%)
Mutual labels:  spec
Kitchen In Travis
Chef cookbook example to run test-kitchen inside Travis CI.
Stars: ✭ 36 (-60.87%)
Mutual labels:  spec
Laravel Json Api Paginate
A paginator that plays nice with the JSON API spec
Stars: ✭ 351 (+281.52%)
Mutual labels:  spec
Ghostwheel
Hassle-free inline clojure.spec with semi-automatic generative testing and side effect detection
Stars: ✭ 556 (+504.35%)
Mutual labels:  spec
Pix Api
API Pix: a API do Arranjo de Pagamentos Instantâneos Brasileiro.
Stars: ✭ 832 (+804.35%)
Mutual labels:  spec
ngff
Next-generation file format (NGFF) specifications for storing bioimaging data in the cloud.
Stars: ✭ 52 (-43.48%)
Mutual labels:  spec
Pytest Spec
Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION.
Stars: ✭ 65 (-29.35%)
Mutual labels:  spec
Orchestra
Complete instrumentation for clojure.spec
Stars: ✭ 573 (+522.83%)
Mutual labels:  spec
Sketch Measure
Make it a fun to create spec for developers and teammates
Stars: ✭ 6,960 (+7465.22%)
Mutual labels:  spec
Element Queries Spec
A spec for a Container-Style Element Query Syntax
Stars: ✭ 375 (+307.61%)
Mutual labels:  spec
Matrix Doc
Matrix Documentation (including The Spec)
Stars: ✭ 536 (+482.61%)
Mutual labels:  spec
Spec
OStatus Specification
Stars: ✭ 18 (-80.43%)
Mutual labels:  spec
Swiftproject
swift project that brings together some demos, componented, Target-Action, use Swift
Stars: ✭ 310 (+236.96%)
Mutual labels:  spec
Spec Examples
Some examples on using clojure.spec!
Stars: ✭ 48 (-47.83%)
Mutual labels:  spec
Phrase
Clojure(Script) library for phrasing spec problems.
Stars: ✭ 275 (+198.91%)
Mutual labels:  spec
Expound
Human-optimized error messages for clojure.spec
Stars: ✭ 806 (+776.09%)
Mutual labels:  spec
Friendly Public Transport Format
A format for APIs, libraries and datasets containing and working with public transport data.
Stars: ✭ 69 (-25%)
Mutual labels:  spec
Kahlan
✔️ PHP Test Framework for Freedom, Truth, and Justice
Stars: ✭ 1,065 (+1057.61%)
Mutual labels:  spec
Array Api
RFC document, tooling and other content related to the array API standard
Stars: ✭ 26 (-71.74%)
Mutual labels:  spec

Pinpointer

Clojars Project CircleCI codecov join the chat at https://gitter.im/athos/pinpointer

Pinpointer is yet another clojure.spec error reporter based on a precise error analysis.

It has the following features:

  • Visually pinpoints which portion of the input data is causing the spec error, based on the spec error analysis of spectrace, a fine-grained spec error analyzer
  • Formats and colorizes the error reports in an easy-to-grasp manner
  • Tracks 'value changes', i.e. reports the spec errors correctly even when s/conformer in the spec transforms the input data
  • Extensible to user-defined spec macros (not documented yet)

Notice: Pinpointer is built on top of clojure.spec, which is one of Clojure's new features that have been developed most actively. So, it's still in alpha and its APIs are also subject to change.

Installation

Add the following to your :dependencies:

Clojars Project

Why and how to use it

clojure.spec provides an API named explain, which describes which portion of the input data caused a spec error:

=> (s/def ::x integer?)
:user/x
=> (s/def ::y string?)
:user/y
=> (s/explain (s/keys :req-un [::x ::y]) {:y 1})
In: [:y] val: 1 fails spec: :user/y at: [:y] predicate: string?
val: {:y 1} fails predicate: (contains? % :x)
nil
=>

As you can see above, the result of explain is simple and plain, but it is often not easy to understand intuitively what was wrong. And it will take longer time to find out where the actual problem is as the spec and input data are getting larger.

pinpoint: replacement of s/explain

Pinpointer provides an API compatible with explain, which is named pinpoint, and it shows the spec errors in a visually easy-to-grasp manner:

=> (require '[pinpointer.core :as p])
nil
=> (p/pinpoint (s/keys :req-un [::x ::y]) {:y 1})
Detected 2 spec errors:
----------------------------------------------------------------------
(1/2)

    Cause: {:y 1}
           ^^^^^^
 Expected: (fn [%] (contains? % :x))

----------------------------------------------------------------------
(2/2)

    Cause: {:y 1}
               ^
 Expected: string?

----------------------------------------------------------------------
nil
=>

You can also colorize the error reports by adding the option {:colorize :ansi} to increase the readability:

pinpoint has several other options. See the docstring for more details.

pinpoint-out: plugin implementation for s/*explain-out*

If you'd rather completely replace the explain facility for any kinds of spec error reporting, it would be helpful to replace s/*explain-out* with pinpointer.core/pinpoint-out instead:

=> (set! s/*explain-out* p/pinpoint-out)
#function[pinpointer.core/pinpoint-out]
=>
;; from now on, p/pinpoint-out will be used in place of s/explain-printer
=>
=> (defn f [x] (inc x))
#'user/f
=> (s/fdef f
     :args (s/cat :x (s/and integer? even?))
     :ret (s/and integer? odd?))
user/f
=> (require '[clojure.spec.test.alpha :as t])
nil
=> (t/instrument)
[user/f]
=> (f 3)
ExceptionInfo Call to #'user/f did not conform to spec:
Detected 1 spec error:
----------------------------------------------------------------------
(1/1)

    Cause: (3)
            ^
 Expected: even?

----------------------------------------------------------------------
  user/eval3842 (form-init1169392389971828339.clj:1)
  clojure.core/ex-info (core.clj:4744)
=>

ClojureScript support

Pinpointer also supports ClojureScript. Note, however, that it may use eval for its spec error analysis in general (especially, when analyzing specs with a literal fn in them) while ClojureScript doesn't have a platform-independent eval fn.

If you use Pinpointer from a self-hosted ClojureScript implementation equipped with eval such as Planck or Lumo, it should work fine even in general cases as follows:

=> (require '[planck.core :as planck])
nil
=> (p/pinpoint (s/and integer? #(> % 10)) 5 {:eval planck/eval})
Detected 1 spec error:
----------------------------------------------------------------------
(1/1)

    Cause: 5
           ^
 Expected: (fn [%] (> % 10))

----------------------------------------------------------------------
nil
=>

Known Issues

There are a couple of known issues in Pinpointer, primarily due to clojure.spec's bugs. They can be found on Issues page, being tagged with spec bug.

If you found something wrong when using Pinpointer and you want to report an issue, check whether or not it's already been filed there first.

License

Copyright © 2016-2018 Shogo Ohta (@athos0220)

Distributed under the Eclipse Public License 1.0.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].