{"id":13509260,"url":"https://github.com/meadery/white-bread","last_synced_at":"2026-02-13T23:01:31.204Z","repository":{"id":54305304,"uuid":"31561675","full_name":"meadery/white-bread","owner":"meadery","description":"🍞 Story BDD tool for elixir using gherkin","archived":false,"fork":false,"pushed_at":"2020-11-04T09:56:20.000Z","size":390,"stargazers_count":230,"open_issues_count":16,"forks_count":36,"subscribers_count":10,"default_branch":"master","last_synced_at":"2026-01-14T07:34:01.741Z","etag":null,"topics":["bdd","cucumber","elixir","gherkin","story-bdd","testing"],"latest_commit_sha":null,"homepage":"","language":"Elixir","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/meadery.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-02T20:32:56.000Z","updated_at":"2025-10-14T09:39:52.000Z","dependencies_parsed_at":"2022-08-13T11:31:00.598Z","dependency_job_id":null,"html_url":"https://github.com/meadery/white-bread","commit_stats":null,"previous_names":["meadsteve/white-bread"],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/meadery/white-bread","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meadery%2Fwhite-bread","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meadery%2Fwhite-bread/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meadery%2Fwhite-bread/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meadery%2Fwhite-bread/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/meadery","download_url":"https://codeload.github.com/meadery/white-bread/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meadery%2Fwhite-bread/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29422192,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-13T22:20:51.549Z","status":"ssl_error","status_checked_at":"2026-02-13T22:20:49.838Z","response_time":78,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["bdd","cucumber","elixir","gherkin","story-bdd","testing"],"created_at":"2024-08-01T02:01:05.329Z","updated_at":"2026-02-13T23:01:30.925Z","avatar_url":"https://github.com/meadery.png","language":"Elixir","readme":"WhiteBread\n==========\n[![Build Status](https://travis-ci.org/meadsteve/white-bread.svg?branch=master)](https://travis-ci.org/meadsteve/white-bread)\n[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/meadsteve/white-bread?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge)\n\n# Looking for maintainers\nThis project is looking for someone who'd like to take over ownershp: Discuss here: https://github.com/meadsteve/white-bread/issues/114\n\n# What?\nStory BDD tool written in and for Elixir. Based on [cucumber](https://cukes.info/).\nParses Gherkin formatted feature files and executes them as acceptance tests.\n\n## Is this a testing tool?\nThe short answer is no. The medium answer is it's a development tool that should really be used in conjuction with some testing framework. For a longer answer checkout this post by Aslak Hellesøy: [the world's most misunderstood collaboration tool](https://cukes.info/blog/2014/03/03/the-worlds-most-misunderstood-collaboration-tool).\n\n## Why the name?\nGherkin and cucumber made me think of [cucumber sandwiches](http://en.wikipedia.org/wiki/Cucumber_sandwich).\nWhich are traditionally made with very thin white bread.\n\n# Alternative tools\nBefore adopting whitebread you should investigate the alternaitves. This project (whitebread) contains a lot of code around setup, execution, and output of tests. An alternative gherkin based BDD tool can be found at https://github.com/cabbage-ex/cabbage. Cabbage parses gherkin feature files and creates exunit tests. This means a lot more of the logic is standard exunit code.\n\n# Getting started - installing\nAdd \"white_bread\" to your `mix.exs` file with the version you wish to use:\n\n```elixir\ndefp deps do\n    [\n        ...\n        { :white_bread, \"~\u003e 4.1.1\", only: [:dev, :test] }\n        ...\n    ]\nend\n```\n\n# Getting started - Basic usage\nCreate a features directory. In here add some *.feature files describing your software. They should be gherkin syntax like:\n\n```gherkin\nFeature: Serve coffee\n  Coffee should not be served until paid for\n  Coffee should not be served until the button has been pressed\n  If there is no coffee left then money should be refunded\n\n  Scenario: Buy last coffee\n    Given there are 1 coffees left in the machine\n    And I have deposited £1\n    When I press the coffee button\n    Then I should be served a coffee\n```\nRun the command:\n```bash\nmix white_bread.run\n```\nThis should prompt you with a few messages like:\n\n```bash\nloading config from features/config.exs\nConfig file not found at features/config.exs.\nCreate one [Y/n]?\ny\n\nSuite: All\nContext module not found Elixir.WhiteBreadContext (features/contexts/white_bread_context.exs)\nCreate one [Y/n]?\ny\n\n```\nThis will create a basic config file and also a context ```features/contexts/white_bread_context.exs```.\nA context file tells WhiteBread how to understand the gherkin in your feature files and also\nwhat setup is required.\n\nThese will need to be implemented like:\n\n```elixir\ndefmodule SunDoe.CoffeeShopContext do\n  use WhiteBread.Context\n\n  feature_starting_state fn  -\u003e\n    coffee_storage = setup_coffee_storage\n    %{in_memory_coffee_db: coffee_storage}\n  end\n\n  scenario_starting_state fn state -\u003e\n    state.in_memory_coffee_db |\u003e clear_db\n    state\n  end\n\n  # `_status` will be either {:ok, scenario} | {:error, reason, scenario}\n  scenario_finalize fn _status, state -\u003e\n    state.in_memory_coffee_db |\u003e shutdown_db\n  end\n\n  given_ \"there are 1 coffees left in the machine\", fn state -\u003e\n    {:ok, state |\u003e Dict.put(:coffees, 1)}\n  end\n\n  given_ ~r/^I have deposited £(?\u003cpounds\u003e[0-9]+)$/, fn state, %{pounds: pounds} -\u003e\n    {:ok, state |\u003e Dict.put(:pounds, pounds)}\n  end\n\n  when_ \"I press the coffee button\", fn state -\u003e\n    # Domain logic to serve coffees would happen\n    # here. Then update the state with the result\n    {:ok, state |\u003e Dict.put(:coffees_served, 1)}\n  end\n\n  then_ \"I should be served a coffee\", fn state -\u003e\n    served_coffees = state |\u003e Dict.get(:coffees_served)\n\n    # The context automatically imports ExUnit.Assertions\n    # so any usual assertions can be made\n    assert served_coffees == 1\n\n    {:ok, :whatever}\n  end\nend\n```\n\nAfter doing this rerun\n\n```\nmix white_bread.run\n```\n\nIf you want to run WhiteBread in test environment run this\n```\nMIX_ENV=test mix white_bread.run\n```\n\nTo execute on each time WhiteBread in test environment without prefixing the command with `MIX_ENV=test`, you can also add this line in `mix.exs`\n\n```\ndef project do\n    [\n        ...\n        preferred_cli_env: [\"white_bread.run\": :test],\n        ...\n    ]\nend\n```\n\n## Integrating a testing library\n\nBy default, `use WhiteBread.Context` will import ExUnit.Assertions. If you're not using ExUnit, you'll probably want to override this default by calling `use WhiteBread.Context, test_library: :some_other_library_name`.\n\nAt the moment, the only library names available are `:ex_unit` (same as the default), `:espec`, and `nil` (which skips the test library setup step altogether).\n\n# Next steps - Additional Suites and subcontexts\n\nAfter following the getting started steps you may find your default context starts to get a bit large.\nThere are two ways this can be broken apart:\n\n1. By composing your default suite out of subcontexts using the `import_steps_from` macro.\n2. By splitting your features into different suites each starting with a different context.\n\n## Subcontexts\n\nSub contexts allow the step definitions of multiple contexts to be imported in to a parent context.\nThe parent context defines all the start and stop callbacks but all the steps in the child context\nwill be available.\n\n```elixir\ndefmodule WhiteBread.Example.DefaultContext do\n  use WhiteBread.Context\n\n  import_steps_from WhiteBread.Example.SharedContext\n\n  # Rest of the context here as usual\n  #...\nend\n```\n\n## Multiple suites\n\nDefining suites allows you to use a different starting context for groups of features. This will\noften be along the lines of a bounded context.\nYou can also run one feature multiple times under different contexts. This is especially useful\nif you have a few different ways of accessing your software (web, rest api, command line etc.).\n\nSuite configuration is loaded from ```features/config.exs```. An example with multiple suites is:\n\n```elixir\ndefmodule WhiteBread.Example.Config do\n  use WhiteBread.SuiteConfiguration\n\n  suite name:          \"Default\",\n        context:       WhiteBread.Example.DefaultContext,\n        feature_paths: [\"features/sub_dir_one\"]\n\n  suite name:          \"Alternate\",\n        context:       WhiteBread.Example.AlternateContext,\n        feature_paths: [\"features/sub_dir_two\"]\n\n  suite name:          \"Alternate - Songs\",\n        context:       WhiteBread.Example.AlternateContext,\n        feature_paths: [\"features/sub_dir_one\"],\n        tags:          [\"songs\"]\nend\n```\nEach suite gets run loading all the features in the given paths and running them using the specified context.\nAdditionally the scenarios can be filtered to specific tags.\n\n## Suites: Context per feature\n\nThis is part of the Suite Configuration and it automatically maps a `.feature` with a `context` module file automatically.\n\nIt is also possible to run this with additional manually defined suites.\n\nExample:\n```elixir\ndefmodule WhiteBread.Example.Config do\n  use WhiteBread.SuiteConfiguration\n\n  context_per_feature namespace_prefix: WhiteBread.Example,\n                      entry_path: \"features/context_per_feature\"\n\n  # Extra config can also be provided to apply to each generated suite                      \n  context_per_feature namespace_prefix: WhiteBread.Example,\n                      entry_path: \"features/context_per_feature\",\n                      extra: [\n                        tags: ['special']\n                      ]\n\n  suite name:          \"Alternate\",\n        context:       WhiteBread.Example.AlternateContext,\n        feature_paths: [\"features/sub_dir_two\"]\nend\n```\n\nAbout the `context_per_feature` configuration:\n\n- `namespace_prefix:` the namespace your modules will start with. The file name of the feature will be converted into a module name and appended to the end of the `namespace_prefix` e.g. `my_new_sandwich.feature` to `WhiteBread.Example.MyNewSandwichContext`\n- `entry_path:` the location of your feature files.\n\n**note:** context files need to be added to your `features/contexts` folder still.\n\n## Speeding things up - async running\n\nMore than likely you have a multicore machine. To get things going a little\nfaster each suite can be configured to run all features and scenarios in a\nseparate process.\n\nThis can be done by setting run_async to true on any suite:\n```elixir\ndefmodule WhiteBread.Example.Config do\n  use WhiteBread.SuiteConfiguration\n\n  suite name:          \"Speedy run\",\n        context:       WhiteBread.Example.DefaultContext,\n        feature_paths: [\"features/sub_dir_one\"],\n        run_async:     true\nend\n```\nnote: At the moment each suite will be run sequentially in the order they appear\nin the config file.\n\n## Speeding things up - timeouts\nBy default each scenario gets 30 seconds to execute. After which point it will\nfail with a timeout warning. Each context can define a custom timeout function:\n\n```elixir\ndefmodule WhiteBread.Example.DefaultContext do\n  use WhiteBread.Context\n  scenario_timeouts fn _feature, scenario -\u003e\n    case scenario.name do\n      \"possible slow scenario\" -\u003e 60_000\n      _               -\u003e 5000\n    end\n  end\n\n  # Rest of the context here as usual\n  #...\nend\n```\nThis function gets the full structs representing the feature and scenario being\nexecuted so it's possible to base the decision to change the timeout on any\navailable property: tags, name, description etc.\n\n## HTML Output (and other outputs)\n\nFor HTML reports configure WhiteBread (e.g. in `config.exs`) with the HTML outputer and optionally a file name for the document:\n\nJSON reports are also available.\n\n```Elixir\nconfig :white_bread,\n  outputers: [{WhiteBread.Outputers.Console, []},\n              {WhiteBread.Outputers.HTML, path: \"~/build/whitebread_report.html\"},\n              {WhiteBread.Outputers.JSON, path: \"~/build/whitebread_report.json\"}\n             ]\n```\n\n# Public interface and BC breaks\nThe public interface of this library covers:\n\n* The exported mix command: ```mix white_bread.run```\n* The ```WhiteBread``` and ```WhiteBread.Helpers``` modules.\n* The macros exported by the ```WhiteBread.Context``` module.\n* The ContextBehaviour defined in ```WhiteBread.ContextBehaviour```.\n* The config.exs structure and the macros exported by the ```WhiteBread.SuiteConfiguration``` module.\n* The structures defined in ```WhiteBread.Gherkin```.\n* The location of feature and context files loaded automatically.\n* The messages that custom outputers receive (documented in WhiteBread.Outputer)\n\nAny changes outside of the above will not be considered a BC break. Although every effort will be made to not introduce unnecessary change in any other area.\n\n# Contribute\nContributions more than welcome but please raise an issue first to discuss any large changes.\n","funding_links":[],"categories":["Testing"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeadery%2Fwhite-bread","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmeadery%2Fwhite-bread","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeadery%2Fwhite-bread/lists"}