All Projects → lambdahands → Opticlj

lambdahands / Opticlj

Licence: mit
A Clojure(Script) expectation/snapshot testing library, inspired by cram, ppx_expect, and jest

Programming Languages

clojure
4091 projects

Projects that are alternatives of or similar to Opticlj

Nrepl
A Clojure network REPL that provides a server and client, along with some common APIs of use to IDEs and other tools that may need to evaluate Clojure code in remote environments.
Stars: ✭ 475 (+2400%)
Mutual labels:  repl
Readline Sync
Synchronous Readline for interactively running to have a conversation with the user via a console(TTY).
Stars: ✭ 601 (+3063.16%)
Mutual labels:  repl
Pointfreeco
🎬 The source for www.pointfree.co, a video series on functional programming and the Swift programming language.
Stars: ✭ 782 (+4015.79%)
Mutual labels:  snapshot-testing
Red
Red is a next-generation programming language strongly inspired by Rebol, but with a broader field of usage thanks to its native-code compiler, from system programming to high-level scripting and cross-platform reactive GUI, while providing modern support for concurrency, all in a zero-install, zero-config, single 1MB file!
Stars: ✭ 4,725 (+24768.42%)
Mutual labels:  repl
Rebel Readline
Terminal readline library for Clojure dialects
Stars: ✭ 574 (+2921.05%)
Mutual labels:  repl
Bic
A C interpreter and API explorer.
Stars: ✭ 719 (+3684.21%)
Mutual labels:  repl
Piggieback
nREPL support for ClojureScript REPLs
Stars: ✭ 452 (+2278.95%)
Mutual labels:  repl
Vim Quickrepl
The Simplest Faster way to open your REPL for filetypes.
Stars: ✭ 17 (-10.53%)
Mutual labels:  repl
Iruby
Official gem repository: Ruby kernel for Jupyter/IPython Notebook
Stars: ✭ 600 (+3057.89%)
Mutual labels:  repl
Elm Platform
Bundle of all core development tools for Elm
Stars: ✭ 775 (+3978.95%)
Mutual labels:  repl
Testing Playground
🐸 Simple and complete DOM testing playground that encourage good testing practices.
Stars: ✭ 511 (+2589.47%)
Mutual labels:  repl
Murex
Bash-like $SHELL designed for greater commandline productivity and safer shell scripts
Stars: ✭ 527 (+2673.68%)
Mutual labels:  repl
Unicodeplots.jl
Unicode-based scientific plotting for working in the terminal
Stars: ✭ 724 (+3710.53%)
Mutual labels:  repl
Snapshot Diff
Diffing snapshot utility for Jest
Stars: ✭ 490 (+2478.95%)
Mutual labels:  snapshot-testing
Rappel
A linux-based assembly REPL for x86, amd64, armv7, and armv8
Stars: ✭ 818 (+4205.26%)
Mutual labels:  repl
Icr
Interactive console for Crystal programming language
Stars: ✭ 452 (+2278.95%)
Mutual labels:  repl
Nteract
📘 The interactive computing suite for you! ✨
Stars: ✭ 5,713 (+29968.42%)
Mutual labels:  repl
Terminalgraphics.jl
True graphics for your Julia REPL
Stars: ✭ 17 (-10.53%)
Mutual labels:  repl
Playbook Ios
📘A library for isolated developing UI components and automatically taking snapshots of them.
Stars: ✭ 830 (+4268.42%)
Mutual labels:  snapshot-testing
Inspector
A drop-anywhere C++ REPL
Stars: ✭ 767 (+3936.84%)
Mutual labels:  repl

opticlj

opticlj is a Clojure(Script) expectation testing (also known as snapshot testing) library.

Rationale

Expectations, or snapshots, is an automated testing strategy that captures the output of a program as a reference to its correctness. In contrast to unit testing, snapshots don't require the programmer to specify the correct output of their program but instead to verify the output.

opticlj let's you define these snapshots and automatically generate the outputs into files. If you change the implementation of your program, the output files may be checked against the new behavior for differences.

I was inspired by this testing strategy because it navigates elegantly between REPL driven development and testing. Unit testing is often cumbersome, but I've found it to be even more so while writing Clojure code: I often verify the correctness of my functions by simply evaluating them, but that output doesn't persist outside of my own machine.

Snapshot testing may be a way for Clojure developers to cast a wide net over the correctness of their programs while staying close to the REPL.

Use Cases

Snapshot testing is often a great substitute to unit testing, but it in no way has the power to verify programs as thoroughly as property-based testing. Snapshot tests are best used for pure functions, and aren't recommended in cases where correctness must be "proven" (big air quotes).

Inspirations

Installation

[opticlj "1.0.0-alpha10"]

See on Clojars

Disclaimer

opticlj is alpha software, and its API is likely subject to change.

Usage

The below example is a way to get started with opticlj in Clojure.

Require the opticlj.core namespace to get started:

(ns my-project.core-test
  (:require [opticlj.core :as optic :refer [defoptic]]))

Let's define a function to test:

(defn add [x y]
  (+ x y))

Define an optic like so:

(defoptic ::one-plus-one (add 1 1))

This does two things:

  • Defines "runner" function that can be accessed with opticlj.core/run
  • Writes an output file in test/__optic__/my_project/core_test/one_plus_one.clj

Here's what one_plus_one.clj looks like:

(in-ns 'my-project.core-test)

(add 1 1)

2

The in-ns expression allows us to evaluate this file, which is especially useful if your editor integrates with the REPL.

Next, if we change the implementation of add and re-run the optic, we get output confirming the snapshot was checked:

(defn add [x y]
  (+ x y 2))

(run ::one-plus-one)

; outputs
{:file "test/__optic__/my_project/core_test/one_plus_one.clj"
 :err-file "test/__optic__/my_project/core_test/one_plus_one.err.clj"
 :passing? false
 :diff {:string "<truncated>"}
 :form (add 1 1)
 :result 4
 :kw :my-project.core-test/one-plus-one}

A new file was created: test/__optic__/my_project/core_test/one_plus_one.err.clj

(in-ns 'my-project.core-test)

(add 1 1)

4

Also, note how the :passing? key is false. We can view our error diff by calling optic/errors:

(optic/errors)
; prints
--- test/__optic__/my_project/core_test/one_plus_one.clj   2017-09-22 16:03:38.000000000 -0500
+++ -   2017-09-22 16:04:38.000000000 -0500
@@ -2,4 +2,4 @@

 (add 1 1)

-2
+4

What we get back is essentially the output of running:

echo "...my new output..." | diff -u <output-file> -

Let's say we wanted to change the rules of our universe and make the addition of one and one equal to four. We can adjust! our optic to accept these new rules:

(optic/adjust! ::one-plus-one)

; outputs
{:adjusted {:file "test/__optic__/my_project/core_test/one_plus_one.clj"
            :passing? true
            :diff nil
            :err-file nil
            :form (add 1 1)
            :result 4
            :kw :my-project.core-test/one-plus-one}}

Now when we check for errors, we see we have resolved our new form of arithmetic:

(optic/errors)

; outputs
nil

ClojureScript

opticlj supports ClojureScript with a few caveats, namely that in order to run ClojureScript tests, you must output your test code using :target :nodejs in your compiler options. See the test/opticlj/cljs directory for an example of using opticlj with the doo test runner.

A convenience function, opticlj.core/ok?, exists to wrap opticlj's tests in a cljs.test/deftest expression. For example:

(ns my-project.cljs.core-test
  (:require [cljs.test :as test :refer-macros [deftest]]
            [opticlj.core :as optic :refer-macros [defoptic]]))

(defoptic ::two-plus-two (+ 2 2))

(deftest optics
  (test/is (optic/passing? (optic/review!))))

Todo

  • [x] Warn if optics is undefined in the program yet exists in a file
  • [x] Add a clean! method to remove unused optics
  • [x] Use defoptic on defoptic (Inception noise)
  • [ ] Complete API documentation
  • [ ] Reimplement core API with stateless methods
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].