{"id":13721555,"url":"https://github.com/codegram/spinach","last_synced_at":"2025-05-07T13:33:16.282Z","repository":{"id":1715016,"uuid":"2444880","full_name":"codegram/spinach","owner":"codegram","description":"Spinach is a BDD framework on top of Gherkin.","archived":false,"fork":false,"pushed_at":"2024-10-24T11:46:01.000Z","size":1264,"stargazers_count":580,"open_issues_count":19,"forks_count":69,"subscribers_count":27,"default_branch":"main","last_synced_at":"2024-11-10T08:03:41.524Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"codegram.github.com/spinach","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codegram.png","metadata":{"files":{"readme":"README.markdown","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2011-09-23T15:38:42.000Z","updated_at":"2024-10-14T10:06:13.000Z","dependencies_parsed_at":"2023-07-06T01:55:20.477Z","dependency_job_id":"4f477160-b5c9-4b92-8b9c-54e4014c12ea","html_url":"https://github.com/codegram/spinach","commit_stats":{"total_commits":600,"total_committers":50,"mean_commits":12.0,"dds":0.565,"last_synced_commit":"e7987bb2ec5f92c0048d25793e3927a5f4550f3b"},"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codegram%2Fspinach","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codegram%2Fspinach/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codegram%2Fspinach/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codegram%2Fspinach/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codegram","download_url":"https://codeload.github.com/codegram/spinach/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224605033,"owners_count":17339249,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T01:01:18.525Z","updated_at":"2024-11-14T10:31:44.543Z","avatar_url":"https://github.com/codegram.png","language":"Ruby","funding_links":[],"categories":["Alternatives","Ruby","Tools","Testing"],"sub_categories":["Ruby"],"readme":"# Spinach - BDD framework on top of Gherkin\n\n[![Gem Version](https://badge.fury.io/rb/spinach.svg)](https://badge.fury.io/rb/spinach)\n![Tests](https://github.com/codegram/spinach/workflows/Tests/badge.svg)\n\nSpinach is a high-level BDD framework that leverages the expressive\n[Gherkin language][gherkin] (used by [Cucumber][cucumber]) to help you define\nexecutable specifications of your application or library's acceptance criteria.\n\nConceived as an alternative to Cucumber, here are some of its design goals:\n\n- Step maintainability: since features map to their own classes, their steps are\n  just methods of that class. This encourages step encapsulation.\n\n- Step reusability: In case you want to reuse steps across features, you can\n  always wrap those in plain ol' Ruby modules.\n\nSpinach is tested against Ruby MRI **2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2** as well as **JRuby **.\n\n## Getting started\n\nStart by adding spinach to your Gemfile:\n\n```ruby\ngroup :test do\n  gem 'spinach'\n  # gem 'rspec'\nend\n```\n\nSpinach works out-of-the-box with your favorite test suite, but you can also\nuse it with RSpec as well if you put the following in `features/support/env.rb`:\n\n```ruby\nrequire 'rspec'\n```\n\nNow create a `features` folder in your app or library and write your first\nfeature:\n\n```cucumber\nFeature: Test how spinach works\n  In order to know what the heck is spinach\n  As a developer\n  I want it to behave in an expected way\n\n  Scenario: Formal greeting\n    Given I have an empty array\n    And I append my first name and my last name to it\n    When I pass it to my super-duper method\n    Then the output should contain a formal greeting\n\n  Scenario: Informal greeting\n    Given I have an empty array\n    And I append only my first name to it\n    When I pass it to my super-duper method\n    Then the output should contain a casual greeting\n```\n\nNow for the steps file. Remember that in Spinach steps are just Ruby classes,\nfollowing a camelcase naming convention. Spinach generator will do some\nscaffolding for you:\n\n```shell\n$ spinach --generate\n```\n\nSpinach will detect your features and generate the following class:\n\n## features/steps/test_how_spinach_works.rb\n\n```ruby\nclass Spinach::Features::TestHowSpinachWorks \u003c Spinach::FeatureSteps\n  step 'I have an empty array' do\n  end\n\n  step 'I append my first name and my last name to it' do\n  end\n\n  step 'I pass it to my super-duper method' do\n  end\n\n  step 'the output should contain a formal greeting' do\n  end\n\n  step 'I append only my first name to it' do\n  end\n\n  step 'the output should contain a casual greeting' do\n  end\nend\n```\n\nThen, you can fill it in with your logic - remember, it's just a class, you can\nuse private methods, mix in modules or whatever!\n\n```ruby\nclass Spinach::Features::TestHowSpinachWorks \u003c Spinach::FeatureSteps\n  step 'I have an empty array' do\n    @array = Array.new\n  end\n\n  step 'I append my first name and my last name to it' do\n    @array += [\"John\", \"Doe\"]\n  end\n\n  step 'I pass it to my super-duper method' do\n    @output = capture_output do\n      Greeter.greet(@array)\n    end\n  end\n\n  step 'the output should contain a formal greeting' do\n    @output.must_include \"Hello, mr. John Doe\"\n  end\n\n  step 'I append only my first name to it' do\n    @array += [\"John\"]\n  end\n\n  step 'the output should contain a casual greeting' do\n    @output.must_include \"Yo, John! Whassup?\"\n  end\n\n  private\n\n  def capture_output\n    out = StringIO.new\n    $stdout = out\n    $stderr = out\n    yield\n    $stdout = STDOUT\n    $stderr = STDERR\n    out.string\n  end\nend\n\nmodule Greeter\n  def self.greet(name)\n    if name.length \u003e 1\n      puts \"Hello, mr. #{name.join(' ')}\"\n    else\n      puts \"Yo, #{name.first}! Whassup?\"\n    end\n  end\nend\n```\n\nThen run your feature again running `spinach` and watch it all turn green! :)\n\n## Shared Steps\n\nYou'll often find that some steps need to be used in many\nfeatures. In this case, it makes sense to put these steps in reusable\nmodules. For example, let's say you need a step that logs the\nuser into the site.\n\nThis is one way to make that reusable:\n\n```ruby\n# ... features/steps/common_steps/login.rb\nmodule CommonSteps\n  module Login\n    include Spinach::DSL\n\n    step 'I am logged in' do\n      # log in stuff...\n    end\n  end\nend\n```\n\nUsing the module (in any feature):\n\n```ruby\n# ... features/steps/buying_a_widget.rb\nclass Spinach::Features::BuyAWidget \u003c Spinach::FeatureSteps\n  # simply include this module and you are good to go\n  include CommonSteps::Login\nend\n```\n\n## Audit\n\nOver time, the definitions of your features will change. When you add, remove\nor change steps in the feature files, you can easily audit your existing step\nfiles with:\n\n```shell\n$ spinach --audit\n```\n\nThis will find any new steps and print out boilerplate for them, and alert you\nto the filename and line number of any unused steps in your step files.\n\nThis does not modify the step files, so you will need to paste the boilerplate\ninto the appropriate places. If a new feature file is detected, you will be\nasked to run `spinach --generate` beforehand.\n\n**Important**: If auditing individual files, common steps (as above) may be\nreported as unused when they are actually used in a feature file that is not\ncurrently being audited. To avoid this, run the audit with no arguments to\naudit all step files simultaneously.\n\n## Tags\n\nFeature and Scenarios can be marked with tags in the form: `@tag`. Tags can be\nused for different purposes:\n\n- applying some actions using hooks (eg: `@javascript`, `@transaction`, `@vcr`)\n\n```ruby\n# When using Capybara, you can switch the driver to use another one with\n# javascript capabilities (Selenium, Poltergeist, capybara-webkit, ...)\n#\n# Spinach already integrates with Capybara if you add\n# `require spinach/capybara` in `features/support/env.rb`.\n#\n# This example is extracted from this integration.\nSpinach.hooks.on_tag(\"javascript\") do\n  ::Capybara.current_driver = ::Capybara.javascript_driver\nend\n```\n\n- filtering (eg: `@module-a`, `@customer`, `@admin`, `@bug-12`, `@feat-1`)\n\n```cucumber\n# Given a feature file with this content\n\n@feat-1\nFeature: So something great\n\n  Scenario: Make it possible\n\n  @bug-12\n  Scenario: Ensure no regression on this\n```\n\nThen you can run all Scenarios in your suite tagged `@feat-1` using:\n\n```shell\n$ spinach --tags @feat-1\n```\n\nOr only Scenarios tagged either `@feat-1` or `@bug-12` using:\n\n```shell\n$ spinach --tags @feat-1,@bug-12\n```\n\nOr only Scenarios tagged `@feat-1` that aren't tagged `@bug-12` using:\n\n```shell\n$ spinach --tags @feat-1,~@bug-12\n```\n\nBy default Spinach will ignore Scenarios marked with the tag `@wip` or whose\nFeature is marked with the tag `@wip`. Those are meant to be work in progress,\nscenarios that are pending while you work on them. To explicitly run those, use\nthe `--tags` option:\n\n```shell\n$ spinach --tags @wip\n```\n\n## Hook architecture\n\nSpinach provides several hooks to allow you performing certain steps before or\nafter any feature, scenario or step execution.\n\nSo, for example, you could:\n\n```ruby\nSpinach.hooks.before_scenario do |scenario|\n  clear_database\nend\n\nSpinach.hooks.on_successful_step do |step, location|\n  count_steps(step.scenario.steps)\nend\n\nSpinach.hooks.after_run do |status|\n  send_mail if status == 0\nend\n```\n\nFull hook documentation is here:\n\n[Spinach's hook documentation](https://github.com/codegram/spinach/blob/master/lib/spinach/hooks.rb)\n\n## Local Before and After Hooks\n\nSometimes it feels awkward to add steps into feature file just because you need to do some test setup and cleanup. And it is equally awkward to add a global hooks for this purpose. For example, if you want to add a session timeout feature, to do so, you want to set the session timeout time to 1 second just for this feature, and put the normal timeout back after this feature. It doesn't make sense to add two steps in the feature file just to change the session timeout value. In this scenario, a `before` and `after` blocks are perfect for this kind of tasks. Below is an example implementation:\n\n```ruby\nclass Spinach::Features::SessionTimeout \u003c Spinach::FeatureSteps\n  attr_accessor :original_timeout_value\n  before do\n    self.original_timeout_value = session_timeout_value\n    change_session_timeout_to 1.second\n  end\n\n  after do\n    change_session_timeout_to original_timeout_value\n  end\n\n  # remaining steps\nend\n```\n\n## RSpec mocks\n\nIf you need access to the [rspec-mocks](https://github.com/rspec/rspec-mocks) methods in your steps, add this line to your `env.rb`:\n\n```ruby\nrequire 'spinach/rspec/mocks'\n```\n\n## Reporters\n\nSpinach supports two kinds of reporters by default: `stdout` and `progress`.\nYou can specify them when calling the `spinach` binary:\n\n    spinach --reporter progress\n\nWhen no reporter is specified, `stdout` will be used by default.\n\nOther reporters:\n\n- For a console reporter with no colors, try [spinach-console-reporter][spinach-console-reporter] (to be used with Jenkins)\n- For a rerun reporter, try [spinach-rerun-reporter][spinach-rerun-reporter] (writes failed scenarios in a file)\n\n## Wanna use it with Rails 3?\n\nUse [spinach-rails](http://github.com/codegram/spinach-rails)\n\n## Other rack-based frameworks\n\nCheck out our [spinach-sinatra demo](https://github.com/codegram/spinach-sinatra-demo)\n\n## Resources\n\n- [Landing page](http://codegram.github.com/spinach)\n- [Slides](http://codegram.github.com/spinach-presentation)\n- [Blog post](http://blog.codegram.com/2011/10/how-to-achieve-more-clean-encapsulated-modular-step-definitions-with-spinach)\n- [API Documentation](http://rubydoc.info/github/codegram/spinach/master/frames)\n- [Google group](https://groups.google.com/forum/#!forum/spinach_bdd)\n\n### Related gems\n\n- [guard-spinach](http://github.com/codegram/guard-spinach)\n- [spinach-rails](http://github.com/codegram/spinach-rails)\n- [spinach-console-reporter][spinach-console-reporter] (to be used with Jenkins)\n- [spinach-rerun-reporter][spinach-rerun-reporter] (writes failed scenarios in a file)\n- [spring-commands-spinach](https://github.com/jvanbaarsen/spring-commands-spinach) (to be used with spring)\n\n### Demos\n\n- [spinach rails demo](https://github.com/codegram/spinach-rails-demo)\n- [spinach sinatra demo](https://github.com/codegram/spinach-sinatra-demo)\n- [simple todo Rails app](https://github.com/codegram/tasca-spinach-demo)\n\n## Contributing\n\n- [List of spinach contributors](https://github.com/codegram/spinach/contributors)\n\nYou can easily contribute to Spinach. Its codebase is simple and\n[extensively documented][documentation].\n\n- Fork the project.\n- Make your feature addition or bug fix.\n- Add specs for it. This is important so we don't break it in a future\n  version unintentionally.\n- Commit, do not mess with rakefile, version, or history.\n  If you want to have your own version, that is fine but bump version\n  in a commit by itself I can ignore when I pull.\n- Send me a pull request. Bonus points for topic branches.\n\n## License\n\nMIT (Expat) License. Copyright 2011-2023 [Codegram Technologies](http://codegram.com)\n\n[gherkin]: http://github.com/codegram/gherkin-ruby\n[cucumber]: http://github.com/cucumber/cucumber\n[documentation]: http://rubydoc.info/github/codegram/spinach/master/frames\n[spinach-console-reporter]: https://github.com/ywen/spinach-console-reporter\n[spinach-rerun-reporter]: https://github.com/javierav/spinach-rerun-reporter\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodegram%2Fspinach","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodegram%2Fspinach","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodegram%2Fspinach/lists"}