All Projects → jeaye → Orchestra

jeaye / Orchestra

Licence: epl-1.0
Complete instrumentation for clojure.spec

Programming Languages

clojure
4091 projects

Projects that are alternatives of or similar to Orchestra

microsub
For tracking issues on the Microsub specification
Stars: ✭ 23 (-95.99%)
Mutual labels:  spec
Pymeasure
Scientific measurement library for instruments, experiments, and live-plotting
Stars: ✭ 255 (-55.5%)
Mutual labels:  instrument
Element Queries Spec
A spec for a Container-Style Element Query Syntax
Stars: ✭ 375 (-34.55%)
Mutual labels:  spec
VISAInstrument
基于NI-VISA/VISA32(Virtual Instrument Software Architecture)的仪器编程(C#),支持RS232、USB、GPIB及LAN通信接口的收发控制
Stars: ✭ 132 (-76.96%)
Mutual labels:  instrument
VOSIMSynth
Modular VST environment for building synthesizers and audio processors.
Stars: ✭ 41 (-92.84%)
Mutual labels:  instrument
Ghost Lang
👻 A friendly little language for you and me.
Stars: ✭ 296 (-48.34%)
Mutual labels:  spec
lingot
Musical instrument tuner
Stars: ✭ 54 (-90.58%)
Mutual labels:  instrument
Matrix Doc
Matrix Documentation (including The Spec)
Stars: ✭ 536 (-6.46%)
Mutual labels:  spec
ngff
Next-generation file format (NGFF) specifications for storing bioimaging data in the cloud.
Stars: ✭ 52 (-90.92%)
Mutual labels:  spec
Laravel Json Api Paginate
A paginator that plays nice with the JSON API spec
Stars: ✭ 351 (-38.74%)
Mutual labels:  spec
automock
A library for testing classes with auto mocking capabilities using jest-mock-extended
Stars: ✭ 26 (-95.46%)
Mutual labels:  spec
table-spec
Specs from SQL database schema for data generation and validation
Stars: ✭ 32 (-94.42%)
Mutual labels:  spec
Swiftproject
swift project that brings together some demos, componented, Target-Action, use Swift
Stars: ✭ 310 (-45.9%)
Mutual labels:  spec
eggplant
A behaviour driven development (BDD) library for Clojure. Simplicity is key.
Stars: ✭ 16 (-97.21%)
Mutual labels:  spec
Openmicroservices.org
NOT MAINTAINED https://medium.com/@iopeak/open-microservices-specification-1abd8262ad0e
Stars: ✭ 383 (-33.16%)
Mutual labels:  spec
GRNLR
granular synthesis plugin part of my bachelors thesis
Stars: ✭ 44 (-92.32%)
Mutual labels:  instrument
Phrase
Clojure(Script) library for phrasing spec problems.
Stars: ✭ 275 (-52.01%)
Mutual labels:  spec
Ghostwheel
Hassle-free inline clojure.spec with semi-automatic generative testing and side effect detection
Stars: ✭ 556 (-2.97%)
Mutual labels:  spec
Dx7 Supercollider
My accurate Yamaha DX-7 clone. Programmed in Supercollider.
Stars: ✭ 395 (-31.06%)
Mutual labels:  instrument
Awesome Music Production
A curated list of software, services and resources to create and distribute music.
Stars: ✭ 340 (-40.66%)
Mutual labels:  instrument

Build Status Clojars Project

Orchestra : complete instrumentation for clojure.spec

Orchestra is a Clojure(Script) library made as a drop-in replacement for clojure.spec.test.alpha, which provides custom instrumentation that validates all aspects of function specs. By default, clojure.spec will only instrument :args. This leaves out :ret and :fn from automatic validation; Orchestra checks all of them for you.

Usage

Leiningen dependency:

;; Clojure requirements
;;    org.clojure/clojure >= 1.10.1
;;
;; ClojureScript requirements
;;    org.clojure/clojurescript >= 1.10.597
[orchestra "2021.01.01-1"]

Just replace your ns and require forms to reference orchestra.spec.test instead of clojure.spec.test.alpha. No further code changes required!

;; Before
(ns kitty-ninja
  (:require [clojure.spec.test.alpha :as st]))

;; Clojure: After
(ns kitty-ninja
  (:require [orchestra.core :refer [defn-spec]]
            [orchestra.spec.test :as st]
            [clojure.spec.alpha :as s]))

;; ClojureScript: After
(ns kitty-ninja
  (:require [orchestra.core :refer-macros [defn-spec]]
            [orchestra-cljs.spec.test :as st]
            [clojure.spec.alpha :as s]))

Just as with vanilla Clojure, begin your instrumentation by calling:

; Call after defining all of your specs
(st/instrument)

What it does

If you're not familiar with Clojure's instrumentation, it's worth reading the official spec guide. In short, after calling orchestra.spec.test/instrument, every call to a function which you've spec'd will have its arguments, return value, and :fn spec validated, based on the specs you've provided.

This magic is possible by rebinding the var, to which your spec'd functions are bound, with a different function which first checks all arguments, then calls the original function, then checks the :ret and :fn specs, if they're present.

When to use it

I highly recommend having this always on during development and testing. You may have systems tests, rather than unit tests, and this can help verify that your data stays in the exact shape you intended.

defn-spec

Orchestra also ships with a defn-spec macro for defining both functions and their specs together in a way which encourages having more specs. You can use it like this:

; Clojure
(ns kitty-ninja
  (:require [orchestra.core :refer [defn-spec]]))

; ClojureScript
(ns kitty-ninja
  (:require [orchestra.core :refer-macros [defn-spec]]))

; The return spec comes after the fn name.
(defn-spec my-inc integer?
  [a integer?] ; Each argument is followed by its spec.
  (+ a 1))

(defn-spec my-add integer?
  [a integer?, b integer?] ; Commas can help visually group things.
  (+ a b))

; Doc strings work as expected.
(defn-spec my-add integer?
  "Returns the sum of `a` and `b`."
  [a integer?, b integer?]
  (+ a b))

; If a certain element doesn't have a spec, use any?
(defn-spec get-meow any?
  [meow-map (s/map-of keyword? any?)]
  (:meow meow-map))

; :fn specs can be specified using the fn's meta map.
(defn-spec my-abs number?
  {:fn #(= (:ret %) (-> % :args :n))}
  [n number?]
  (Math/abs n))

; Destructuring works nicely.
(defn-spec add-a-b number?
  [{:keys [a b]} (s/map-of keyword? number?)]
  (+ a b))

; Multiple arities are supported.
(defn-spec sum number?
  ([a number?]
   a)
  ; Varargs are also supported.
  ([a number?, b number?, & args (s/* number?)]
   (apply + a b args)))

A note on defn-spec with multiple arities

Since defn-spec allows for multiple arities, each one with arbitrary specs, some special handling needs to be done for handling how args are validated against the right arity. For the most part, this is done entirely behind the scenes. The one place it slips through is in :fn validation for multi-arity functions. In this case, spec conforming will slightly change the input to the :fn validator and that needs to be handled. Here's an example.

; A multi-arity function like this:
(defn-spec arities number?
  ([a number?]
   (inc a))
  ([a number?, b number?]
   (+ a b))
  ([a string?, b boolean?, c map?]
   0))

; Has an automatically-generated function spec of this:
{:args (s/or :arity-1 (s/cat :a number?)
             :arity-2 (s/cat :a number? :b number?)
             :arity-3 (s/cat :a string? :b boolean? :c map?))
 :ret number?}

; If we call (arities 2 2) then then :fn validator gets this:
{:ret 4, :args [:arity-2 {:a 2, :b 2}]}

; If we call (arities "" false {}) then the :fn validator gets this:
{:ret 0, :args [:arity-3 {:a "", :b false, :c {}}]}

So, the :fn validator needs to take note of possible arities it's handling and it can, for example, do a case on that value to validate differently for each arity. Or just use (-> % :args second) to ignore it and get to the args.

License

Distributed under the Eclipse Public License version 1.0, just like Clojure.

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].