Skip to content
A more idiomatic binding of JVM cucumber to Clojure
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src/mullr
test/mullr
.gitignore
LICENSE
README.org
deps.edn

README.org

mullr.clj-cucumber

A more idiomatic and up-to-date binding of JVM cucumber to Clojure. No global state, and suitable for repl-based development.

Usage

Add the dependency

Add it to your deps.edn

{:deps {mullr/clj-cucumber {:git/url "https://github.com/mullr/clj-cucumber"
                            :sha "<>"}}}

Make a feature file

Make a feature file, and put it somewhere in your source tree. test/features is a handy location.

Feature: A passing feature
  Scenario: Successful test
    Given some setup
    When I do a thing
    Then the setup happened
    And the thing happened

Make a test file

Make a regular clojure test, and call run-cucumber from it.

(ns cucumber-test
  (:require [clojure.test :refer :all]
            [mullr.clj-cucumber :refer [run-cucumber step]]))

(def test-state (atom {}))

(def steps
  [])

(deftest cucumber
  (is (= 0 (run-cucumber "test/features/passing.feature" steps))))

Run the tests and copy the template step defs

Run your test in whatever way you do normally, then see what was printed. Copy the step templates into your list of steps.

clj -A:test:runner
<snip>

You can implement missing steps with the snippets below:

(step :Given #"^some setup$"
      (fn some-setup []
        (comment  Write code here that turns the phrase above into concrete actions)
        (throw (cucumber.api.PendingException.))))

(step :When #"^I do a thing$"
      (fn I-do-a-thing []
        (comment  Write code here that turns the phrase above into concrete actions)
        (throw (cucumber.api.PendingException.))))

(step :Then #"^the setup happened$"
      (fn the-setup-happened []
        (comment  Write code here that turns the phrase above into concrete actions)
        (throw (cucumber.api.PendingException.))))

(step :Then #"^the thing happened$"
      (fn the-thing-happened []
        (comment  Write code here that turns the phrase above into concrete actions)
        (throw (cucumber.api.PendingException.))))

Fill in the blank

Fill out the body as appropriate.

(def test-state (atom {}))

(def steps
  [(step :Given #"^some setup$"
         (fn some-setup []
           (reset! test-state nil)
           (swap! test-state assoc :setup-happened true)))

   (step :When #"^I do a thing$"
         (fn I-do-a-thing []
           (swap! test-state assoc :thing-happened true)))

   (step :Then #"^the setup happened$"
         (fn the-setup-happened []
           (assert (:setup-happened @test-state))))

   (step :Then #"^the thing happened$"
         (fn the-thing-happened []
           (assert (:thing-happened @test-state))))])

NB You should use assert in your step defs rather than clojure.test’s = macro, so the cucumber test runner can observe the assertion failures.

Happily run your now-passing tests

clj -A:test:runner
Running tests in #{"test"}

Testing cucumber-test
Feature: A passing feature

  Scenario: Successful test # test/features/my.feature:2
    Given some setup        # cucumber_test.clj:8
    When I do a thing       # cucumber_test.clj:13
    Then the setup happened # cucumber_test.clj:17
    And the thing happened  # cucumber_test.clj:21

1 Scenarios (1 passed)
4 Steps (4 passed)
0m0.019s


Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

Other Features

Parameters

As with most cucumber implementations, regex subgroups are turned into paramters to your step functions.

(def steps
 [(step :When #"^I do (\d+) things$"
         (fn I-do-int-things [x]
           ...))])

Hooks

You can add hooks, too, alongside your steps. Use the hook macro to make them.

(def steps
  ;; these happen before and after the scenario
  [(hook :before (fn before-hook [] ...)
   (hook :after (fn after-hook [] ...)
   ;; these happen before and after each step
   (hook :before-step (fn before-step-hook [] ...)
   (hook :after-step (fn after-step-hook [] ...)

   (step :Given ...)])

License

Copyright © 2019 Russell Mull

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

You can’t perform that action at this time.