Giter Site home page Giter Site logo

cabbage's Introduction

Cabbage

Coverage Status CircleCI Hex.pm

(Looking contribution for a better icon!)

A simple addon on top of ExUnit which provides compile time translation of .feature files to exunit tests. Big thanks to @meadsteve and the White Bread project for a huge head start on this project.

Installation

Available in Hex, the package can be installed as:

  1. Add cabbage to your list of dependencies in mix.exs:
def deps do
  [{:cabbage, "~> 0.4.0"}]
end

Example Usage

By default, feature files are expected inside test/features. This can be configured within your application with the following:

config :cabbage, features: "some/other/path/from/your/project/root"

Inside test/features/coffee.feature you might have something like:

Feature: Serve coffee
  Coffee should not be served until paid for
  Coffee should not be served until the button has been pressed
  If there is no coffee left then money should be refunded

  Scenario: Buy last coffee
    Given there are 1 coffees left in the machine
    And I have deposited £1
    When I press the coffee button
    Then I should be served a coffee

To translate this to a simple exunit test, all you need to do is provide the translation of lines to steps in the test. Inside test/features/coffee_test.exs (or anywhere you like really).

defmodule MyApp.Features.CoffeeTest do
  # Options, other than file:, are passed directly to `ExUnit`
  use Cabbage.Feature, async: false, file: "coffee.feature"

  # `setup_all/1` provides a callback for doing something before the entire suite runs
  # As below, `setup/1` provides means of doing something prior to each scenario
  setup do
    on_exit fn -> # Do something when the scenario is done
      IO.puts "Scenario completed, cleanup stuff"
    end
    %{my_starting: :state, user: %User{}} # Return some beginning state
  end

  # All `defgiven/4`, `defwhen/4` and `defthen/4` takes a regex, matched data, state and lastly a block
  defgiven ~r/^there (is|are) (?<number>\d+) coffee(s) left in the machine$/, %{number: number}, %{user: user} do
    # `{:ok, state}` gets returned from each callback which updates the state or
    # leaves the state unchanged when something else is returned
    {:ok, %{machine: Machine.put_coffee(Machine.new, number)}}
  end

  defgiven ~r/^I have deposited £(?<number>\d+)$/, %{number: number}, %{user: user, machine: machine} do
    {:ok, %{machine: Machine.deposit(machine, user, number)}} # State is automatically merged so this won't erase `user`
  end

  # With no matches, the map is empty. Since state is unchanged, its not necessary to return it
  defwhen ~r/^I press the coffee button$/, _, state do
    Machine.press_coffee(state.machine) # instead would be some `hound` or `wallaby` dsl
  end

  # Since state is unchanged, its not necessary to return it
  defthen ~r/^I should be served a coffee$/, _, state do
    assert %Coffee{} = Machine.take_drink(state.machine) # Make your `assert`ions in `defthen/4`s
  end
end

The resulting compiled test will be logically equivalent to:

defmodule MyApp.Features.CoffeeTest do
  use ExUnit.Case, async: false

  setup do
    on_exit fn ->
      IO.puts "Scenario completed, cleanup stuff"
    end
    {:ok, %{my_starting: :state, user: %User{}}}
  end

  # Each scenario would generate a single test case
  @tag :integration
  test "Buy last coffee", %{my_starting: :state, user: user} do
    # From the given
    state = %{user: user, machine: Machine.put_coffee(Machine.new, number)}
    # From the and
    state = Map.put(state, :machine, Machine.deposit(machine, user, number))
    # From the when
    Machine.press_coffee(state.machine)
    # From the then
    assert %Coffee{} = Machine.take_drink(state.machine)
  end
end

This provides the best of both worlds. Feature files for non-technical users, and an actual test file written in Elixir for developers that have to maintain them.

Tables & Doc Strings

Using tables and Doc Strings can be done easily, they are provided through the variables under the names :table and :doc_string. An example can be seen in test/data_tables_test.exs and test/features/data_tables.feature.

Running specific tests

Typically to run an ExUnit test you would do something like mix test test/some_test.exs:12 and elixir will automatically load test/some_test.exs for you, but only run the test on line 12. Since the feature files are being translated into ExUnit at compile time, you'll have to specify the .exs file and not the .feature file to run. The line numbers are printed out as each test runs (at the :info level, so you may need to increase your logger config if you dont see anything). An example is like as follows:

# Runs scenario of test/features/coffee.feature on line 13
mix test test/feature_test.exs:13

Developing

Using Docker Compose

A docker-compose.yml is provided for running the tests in containers.

$ docker-compose up

To wipe all _build and deps you can run:

$ docker-compose down -v

If you want to interactive, using standard mix commands, such as updating dependencies:

$ docker-compose run --rm test deps.update --all

Or, if you want to run a single test, that can be accomplished with:

$ docker-compose run --rm cabbage test test/feature_test.exs

Roadmap

  • Scenarios
  • Scenario Outlines
  • ExUnit Case Templates
  • Data tables
  • Executing specific tests
  • Tags implementation
  • Background steps
  • Integration Helpers for Wallaby (separate project?)
  • Integration Helpers for Hound (separate project?)

cabbage's People

Contributors

astery avatar frahugo avatar gmile avatar hauleth avatar lukeledet avatar maxmarcon avatar mgwidmann avatar mononym avatar nicholasjhenry avatar nicocharlery avatar rawkode avatar revati avatar shdblowers avatar thruflo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cabbage's Issues

state is updated

it seems like the state passed into a test is not always the state given in the setup function. When the state is updated, it uses that state in the following steps. Even across different scenarios.

reproduce

   1 Feature: Bug
   2
   3 Scenario: No state change
   4     Given start state
   5     Then the state is not changed
   6
   7   Scenario: State change
   8     Given start state
   9     When i change state
  10     Then state is changed
test/features/bug_test.exs

   1 defmodule CabbageTest.BugTest do
   2   use Cabbage.Feature, async: true, file: "bug.feature"
   3
   4   setup do
   5     {:ok, params: "start"}
   6   end
   7
   8   defgiven ~r/^start state$/, _vars, %{params: params } do
   9     IO.inspect params
  10   end
  11
  12  defthen ~r/^the state is not changed$/, _vars, %{params: params} do
  13    assert params == "start"
  14   end
  15
  16   defwhen ~r/^i change state$/, _vars, state do
  17     {:ok, %{params: "changed"}}
  18   end
  19
  20   defthen ~r/^state is changed$/, _vars, %{params: params} do
  21     assert params == "changed"
  22   end
  23 end

now when the scenario with state change is executed before the other, it fails.
you can test with mix test --seed 394964

Thx!

Generating .exs files

If I understand correctly: for a .feature file to be executed, it needs to be referenced in a *_test.exs file.

That creates a problem when someone with little code knowledge adds (or changes the name of) the feature files.

I'm already the GlobalFeatures example to define steps independently from the individual features.

Is there an existing macro/script that will just go through the .feature files and create according exunit tests?

Behat-like usage

Hello,

In the PHP world (like it or not) there is Behat. With that tool, you define feature files and Feature context, but those are independant.

It means that in a feature file you can use "givens" and "thens" from any context.

With cabbage, you to define a feature file on top of your context. Is it on purpoe ? What would you think about implementing feature-independant contexts ?

access

Hello, I would need access to gherkin repository as well, so I could create correct step suggestions when outlines are used.
And access to hexdocs documentation, so I could improve it.

Thanks

Tests produce warning

Running the tests with a clean _build folder produces the following warnings:

warning: this clause cannot match because a previous clause at line 1 always matches
  test/feature_test.exs:1

warning: this clause cannot match because a previous clause at line 1 always matches
  test/outline_test.exs:1

Data Tables

@wip
Feature: Data Tables
  As a developer
  I want support for Data Tables 
  So I can get a list of values inside a step definition

Scenario: Data table represented as a list of maps
  Given the following data table
  | id  |  name  |
  | 1    | Luke    |
  | 2   | Darth   |
  When I run a the test file
  Then in the step definition I should get a var with the value
  """
  [%{id: "1", name: "Luke"}, %{id: "2", name: "Darth"}]
  """

Notice: I don't know if Cabbage currently support multiline strings. For more info see: https://cucumber.io/docs/reference#data-tables

Need open source icon

The icons used for both the organization and in the README are 😞 sadly ripped off of whatever I could find on the internet... Would be a good idea to try to get someone with some graphic design experience to make something unique for the project.

Also, looking to start a github page for documentation and project description. Ideas for how that would look are also welcome 😄

BUG: import_feature fails to import module without tags

Hi,

First of all, thanks for this project. I was already doing stuff with ExUnit and .feature files but manually.

Now, regarding the bug:

Given a module with steps like

defmodule Webapp.CommonFeatureSteps do
  use Cabbage.Feature
  # TODO: match role into a variable instead of hardcoding Admin
  defgiven ~r/^login as  "Admin"$/, _vars, %{session: session} do
    # some login logic here
  end
  defand ~r/^visit "(?<path>.*?)"$/, %{path: path}, %{session: session} do
     # some visit logic here
  end
end

When I import_feature Webapp.CommonFeatureSteps then I get the following error:

** (Protocol.UndefinedError) protocol Enumerable not implemented for nil
    (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir) lib/enum.ex:116: Enumerable.reduce/3
    (elixir) lib/enum.ex:1776: Enum.reduce/3

I traced the error and in this case, with a module with steps but without tags, it's because in

for {name, block} <- unquote(module).raw_tags() do
  Cabbage.Feature.Helpers.add_tag(__MODULE__, name, block)
end

inside defmacro import_feature in Cabbage.Feature, the value of unquote(module).raw_tags() is nil.

As a side note, I think it might read better import_steps and import_tags instead of import_feature.

API for `tag` definitions is terribly hacky

It uses terrible hack to allow syntax in form:

tag @foo do
  # …
end

Instead it should set tag value as a field in a context that is passed to the setup and force user to match on tags there. It would provide much nicer API and would de-cruft the implementation form hacks.

Add a way to add ExUnit @moduletag and @tag attributes to generated test cases and tests

These features are very useful to define which tests to run in a specific situation through the exclude/include/only arguments to mix test. It would be good to be able to have some way of tagging the tests produced by cabbage, maybe through translating gherkin tags into ExUnit tags.

This might be already implemented but I can't find anything in the documentation.

Test this library it self

After having missing features I had to have to use this library, I forked it and added my required features (#34, #54, #55, #56).

I don't feel entirely safe with current tests.

It seems using .feature tests to test this package isn't most suitable to test package itself.

Maybe package itself should be tested with exunit. By somehow calling .feature tests and asserting CLI output? or I don't know.

Maybe actual test reads generated .feature test AST and asserts it?

Elixir defdelegate macro tests like so

If we will be able to somehow solve this problem, I would be willing to become maintainer (if that is needed of course).

Great job guys. Really cool project. 👍

Document use of case templates

Hi,

I am trying out your library and got stuck attempting to do:

use Cabbage.Feature, use: MyAwesomeTestCase, file: "my_feature.feature"

when I should have been using:

use Cabbage.Feature, template: MyAwesomeTestCase, file: "my_feature.feature"

A few words in the README to this effect would help others not to make my mistake!

Allow use of alternative TestCase

Hey,

This seems pretty awesome! Instead of injecting use ExUnit into all generated tests, can we provide an alternative module through the keyword list?

Awesome job with this 👍

Run single test

Need ability to be able to run a single test like:

mix test test/features/coffee.feature:12

Feature similar to import steps

Hi Matt,

Using Cabbage today and was thinking it would be nice to sort my scenarios into different modules, akin to how white bread does it with the import_steps_from macro.

Is this something that can be done with Cabbage?

If so, I think that should be put in the readme.

If not, I think that would be a really useful feature to add.

Add cucumber expressions functionality

Hello @mgwidmann !
I am wondering if there are plans to add cucumber expressions functionality, so we have something similar as described by Aslak here https://cucumber.io/blog/2017/07/26/announcing-cucumber-expressions

We are currently looking into it and I am wondering if you would accept a PR once we finished?

At the moment we are looking at features cucumber expressions provide, as described here https://docs.cucumber.io/cucumber/cucumber-expressions/
We are thinking at breaking that feature set into 3 features and deliver each in separate PR:

  1. support parameter types
  2. support optional text, alternative text, escaping
  3. support custom parameter types

To achieve that we are thinking of adding extra call to private find_implementation_of_step function, which would call CucumberExpressions module passing regex or string from step definition.
Here is where we would call our module from https://github.com/cabbage-ex/cabbage/blob/master/lib/cabbage/feature.ex#L240

How do you feel about that?

Two `defwhen` that both matches

So we came across an issue where we have two defwhen, and both their regex matches on with the feature we are writing.

Reproduce

Specifically we have something like this:

Example text

selection 1 is marked as won

Case 1

defwhen ~r/^selection (?<index>\d+) is (marked as )?(?<result_name>pending|won|lost|voided|pushed|cashed out|win-push)$/,

Case 2

defwhen ~r/^selection (?<cname>[^ ]+) is (marked as )?(?<result_name>pending|won|lost|voided|pushed|cashed out|win-push)$/,

The defwhens are written in this exact order, case 1 first then case 2.

So we actually intend it to match the first case, hence \d+, but for some reason the example text matches the second case instead. We can confirm that if we comment out the second clause, Cabbage matches the first case just fine.

For our solution, we have updated our second case clause's regex to be more specific instead, and it works:

^selection (?<cname>\D\w+) is (marked as )?(<result_name>pending|won|lost|voided|pushed|cashed out|win-push)$

Question

But we're just wondering, when there are two cases that can both match a feature, which one would Cabbage pick? Is the current behaviour expected, and is it documented somewhere? I would've thought the order of defwhen matters, but it looks like it isn't?

To add, we're not entirely sure if this is always 100% reproducible, because our tests are usually green too, so it could be intermittent?

test library on all supported versions (1.3.4 ... 1.7.3)

It seems that SemaPhoreCI doesn't provide such functionality, or I didn't find it.

TravisCI on the other had does.

In either case, not selected CI is important, but in fact, that library tests are run in all those environments to ensure most compatibility. Currently is set to elixir 1.7.4.

Previously manually fixed issues, that occurred in CI (because it was set to 1.3.4) but locally used 1.7...

  • test in all minor elixir versions starting from 1.3
  • test code format on the latest elixir version
  • test coverage on the latest elixir version
  • reports have ambiguous names of each job, not so self evident from failed job name, which part failed

Support setup, setup_all callbacks

setup_all -> should initialize test file scope
setup -> should be able to setup scenario, alternative to background.

How they should be behaving together?

Different outputers

Is there a way to output scenario results in a more detailed way? Ideally an outputer to HTML

Allow matching exact strings

Instead of always requiring regular expression it would be worth to sometimes provide exact string to not bother about all anchoring and other cruft, this would short "definitions" of such steps by 4 characters at least.

Add cabbage mix tasks

I think it'd be great to have a cabbage mix task to tasks, tailored to features.

  • mix cabbage run

    Particularly it'd be great to be able to run only features, optionally pointing to specific features:

    Like this:

    $ mix cabbage run                                              # runs all feature files
    $ mix cabbage run path/to/first.feature                        # runs only my_first.feature
    $ mix cabbage run path/to/first.feature path/to/second.feature # runs only my_first.feature and second.feature
  • mix cabbage features

    Would display currently developed features.

    $ mix cabbage features
    Serve coffee
    Park a coffee
    Meet a bartender (wip)
    Make a dinner (wip)
    Register a user

But keyword

Hey devs.

This is a feature request.

I noticed that the defbut macro for but gherkin keyword is not implemented. If I'm not wrong this can be easily defined as an alias for defand.

Thanks in advance,

Hisa

Scenarios run multiple times

Tested with Cabbage 0.3.3 and Elixir 1.5.0.

When there are n scenarios in a feature file, it seems that each scenario is run n times. I've created a minimal test case here, but basically what happens is this …

Starting with a single scenario, all seems fine:

Feature: Tests get run multiple times
  Scenario: Scenario 1
    Given a precondition
$ mix test

18:10:43.675 [debug] Parsing line: "Feature: Tests get run multiple times"

18:10:43.676 [debug] Parsing line: "Scenario: Scenario 1"

18:10:43.680 [debug] Parsing line: "Given a precondition"

18:10:43.682 [debug] Parsing line: ""

18:10:43.740 [info]  Line 2:  Scenario: Scenario 1

18:10:43.741 [info]  		Given a precondition
.

Finished in 0.1 seconds
1 test, 0 failures

Add a second scenario, and the number of tests jumps to four:

Feature: Tests get run multiple times
  Scenario: Scenario 1
    Given a precondition

  Scenario: Scenario 2
    Given a precondition
$ mix test

18:12:58.887 [debug] Parsing line: "Feature: Tests get run multiple times"

18:12:58.889 [debug] Parsing line: "Scenario: Scenario 1"

18:12:58.892 [debug] Parsing line: "Given a precondition"

18:12:58.894 [debug] Parsing line: ""

18:12:58.894 [debug] Parsing line: "Scenario: Scenario 2"

18:12:58.894 [debug] Parsing line: "Given a precondition"

18:12:58.894 [debug] Parsing line: ""

18:12:59.001 [info]  Line 2:  Scenario: Scenario 1

18:12:59.001 [info]  		Given a precondition
.
18:12:59.001 [info]  Line 2:  Scenario: Scenario 1

18:12:59.001 [info]  		Given a precondition
.
18:12:59.002 [info]  Line 5:  Scenario: Scenario 2

18:12:59.002 [info]  		Given a precondition
.
18:12:59.002 [info]  Line 5:  Scenario: Scenario 2

18:12:59.002 [info]  		Given a precondition
.

Finished in 0.1 seconds
4 tests, 0 failures

With three scenarios, the number jumps to nine, and so on.

I've added code to the step definition that writes to a file, to verify that the tests are actually running multiple times (rather than it being a problem with reporting). I've also verified that the behaviour is the same regardless of whether or not the scenarios share steps.

Steps don't match in Elixir 1.7

Environment

  • Cabbage 0.3.5
  • Elixir 1.7.1
  • Erlang/OTP 21.0

Steps to reproduce

Create a new project, add cabbage and create a feature file with its associated test module. Run the test to get the "Please add a matching step" error. Paste the generated step definition into the test module.

Expected behaviour

Test passes.

Actual behaviour

Step definition is not found (the "Please add a matching step" error is shown again).

Testing controllers on a Phoenix App

Hi, let me first say thanks for creating this tool. I am trying to write a test for a BDD feature while the feature file is below:

Feature: Root path must always be healthy with 200 on GET
  API should always be online
  Scenario: Visit Index Page
    Given I send a GET requested to root path
    Then I should get 200

The feature file is for a root path of an HTTP endpoint of a Phoenix App.
The test I have written is as below:

defmodule MyAppWeb.PageControllerTest do
  use MyAppWeb.ConnCase
  # Options, other than file:, are passed directly to `ExUnit`
  use Cabbage.Feature, async: false, file: "page_controller_index.feature"
  alias Gherkin.Elements.Scenario

  test "has a @feature" do
    assert "Root path must always be healthy with 200 on GET" = @feature.name
  end

  setup do
    {:ok, %{}}
  end
  defgiven ~r/^I send a GET requested to root path$/, _,_ do
    conn = get(conn, "/")
    {:ok, %{conn: conn}}
  end

  defthen ~r/^I should get 200$/, _, %{conn: conn} do
    assert html_response(conn, 200) =~ "Welcome to Phoenixxx!"
  end
end

PROBLEM: When I run mix test the test runs and skips my given and then clauses. The test has a @feature however runs and passes. I expect the then to fail but the test never gets there! It might be my setup but I have followed the README and compared. I cant get it to work.

Tests don't seem to run at all under 0.3.4

After upgrading Cabbage to 0.3.4, the features no longer seem to get executed. It looks like they're parsed, because I get the expected undefined step message if I remove a step definition, but the code in the step definitions isn't executed, and no tests are reported as having run.

(Elixir 1.5.1, Erlang/OTP 20, macOS 10.13)

tag to setup_tag

Registering tag specific setup callbacks currently is outside of ExUnit default flow.

setup_all -> setup for test as a whole
setup -> setup for each test case in file (in our case for each scenario), there even might be an alias setup_scenario?
setup_tag -> setup only for those features that are marked with tag.

Use different type for feature tests

2nd argument for ExUnit.Case.register_test/4 should be the test type. Currently Cabbage use :test which is pretty uninformative. Instead it would be better to use something like :feature so it would be explicitly stated as feature tests in summary.

If regex pattern matches another step, Cabbage will use the first step using the regex in the file, regardless of the step type

Steps to Reproduce

  • Write a 'Then' feature step in Scenario 1 Feature A
  • Write a 'When' step in Scenario 2 Feature A with the same feature step definition as Scenario 1 Feature A's 'Then' step
  • Write separate test logic for each of the steps, with the same regex
  • Run test for feature
  • See that logic for Scenario 1's 'Then' step gets run instead of Scenario 2's 'When' step, because Scenario 1 comes before Scenario 2 in the test file

AC

  • Given I have two steps with the same definition
  • And the steps are of different types (i.e. one step is a When, and the other is a Then)
  • When the test runs for each scenario
  • Then the correct step runs for the given scenario

How to log steps ala Cucumber

THIS IS NOT AN ISSUE.

Hey devs ... If you want to log your feature step by step similar to how Cucumber logs in Ruby, then you can use FlexLogger and configure it in your test config file.

# file config/test.exs
config :logger,
  backends: [{FlexLogger, :test_logger}, {FlexLogger, :default_logger}]

config :logger, :test_logger,
  logger: :console,
  default_level: :off,
 # the tests that use Cabbage start with FeatureTest. i.e.: FeatureTest.CreatePost
  level_config: [module: FeatureTest, level: :info],
  format: " $levelpad$message\n"

config :logger, :default_logger,
  logger: :console,
  default_level: :warn,
  format: "\n$time $metadata[$level] $levelpad$message\n"

This info might fit quite well into the README and then close this ticket ...

ExUnit / Duplicated Scenario Error with Elixir 1.5

ExUnit with Elixir 1.5 now errors when a duplicate case is used.

.** (ExUnit.DuplicateDescribeError) describe "Scenario" is already defined in Test.Features.LoginTest
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (stdlib) erl_eval.erl:122: :erl_eval.exprs/5
    (stdlib) erl_eval.erl:228: :erl_eval.expr/5
    (stdlib) erl_eval.erl:229: :erl_eval.expr/5

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.