Spinach is a new awesome BDD framework that features encapsulation and modularity of your step definitions.

We've been using Cucumber for a while now, and we must say we fell in love with it from the first moment.

But not anymore: It broke our hearts.

You know, we realized what we really loved about Cucumber wasn't Cucumber itself but Gherkin. Gherkin is the feature parser behind it and has some really nice features:

A really natural DSL (as natural as it can be)

(as natural as it can be) A simple way to abstract a feature description

to abstract a feature description It helps you focus on business value , even if there's no real impact on the actual execution (In order to...)

But what sucks about cucumber?

Step MADNESS

Where exactly should I put my step definitions? What if they're corelated - can I abstract them in a simple way? Can I reuse them across projects? Could I even test them?

With cucumber, you usually run into this kind of situations and there's no easy way to get over it. You should use better step file namings perhaps? Create some methods that live next to each other in the cucumber World? Nah, it just doesn't feel good.

Step ambiguity

Sharing steps between all the features in your project just doesn't scale. It's fine if you have a couple of features, but you start hitting ambiguous steps when it grows off a certain limit.

And when that happens, you must write them taking in account the ones written before, and just having your mind somewhere else misses the whole point of writing them - you should focus on your feature

Regexp-based step matching

Reusable Cucumber steps == ugly steps. If you want a to reuse the same step between multiple situations, either you're going too far in the integration tests (and thus you should be doing that in the unit tests) or you should be writing some helper methods.

It just doesn't feel good not to have explicitly defined what step is being executed. It's like metaprogramming: it can be useful, but most of the times is a bad habit.

So, for that... we made Spinach

Spinach focuses on step reusability and encapsulation so you can reuse them in a clean way across features and projects.

Features are just Ruby classes

are just Leverages Gherkin parser

parser Steps are just Ruby methods

Supports MiniTest and RSpec as well as Capybara

Fighting step madness and ambiguity

Each feature has its own steps (so no more global steps)

(so no more global steps) Explicit reusability through Ruby mixins

Simple architecture

Small codebase

Fully documented

Simple hooks system

Show me an example

Given this feature

Feature: Test how spinach works In order to know what the heck is spinach As a developer I want it to behave in an expected way Scenario: Formal greeting Given I have an empty array And I append my first name and my last name to it When I pass it to my super-duper method Then the output should contain a formal greeting Scenario: Informal greeting Given I have an empty array And I append only my first name to it When I pass it to my super-duper method Then the output should contain a casual greeting

This is how its Spinach feature steps file looks

class TestHowSpinachWorks < Spinach : : FeatureSteps Given 'I have an empty array' do @array = Array . new end And 'I append my first name and my last name to it' do @array + = [ "John" , "Doe" ] end When 'I pass it to my super-duper method' do @output = capture_output do Greeter . greet ( @array ) end end Then 'the output should contain a formal salutation' do @output . must_include "Hello, mr. John Doe" end And 'I append only my first name to it' do @array + = [ "John" ] end Then 'the output should contain a casual salutation' do @output . must_include "Yo, John! Whassup?" end private def capture_output out = StreamIO . new $stdout = out $stderr = out yield $stdout = STDOUT $stderr = STDERR out . string end end

Ruby compatibility

Spinach runs on MRI 1.9 and Rubinius/JRuby support is on the works.

Note that not giving support for MRI 1.8.7 is a purposeful choice and not a negligence. This is new software, why should we encourage using legacy versions?

So if you wanna give it a try, here's all you need:

We would really love some feedback. Hope you like it!