behave-django icon indicating copy to clipboard operation
behave-django copied to clipboard

Build fails, probably because behave can't find steps directory

Open bittner opened this issue 7 years ago • 8 comments

The current build for PR #63 fails. When I run behave or python manage.py behave locally I get:

$ behave
ConfigError: No steps directory in '/home/peter/Development/repos/behave-django'
$ python manage.py behave
Creating test database for alias 'default'...
ConfigError: No steps directory in '/home/peter/Development/repos/behave-django'
Destroying test database for alias 'default'...

I've done some research and found some probably unrelated issue in the behave project. Not sure.

The problem seems to be related to how behave discovers the steps/ folder when paths are specified in the behave configuration.

bittner avatar Jun 15 '18 10:06 bittner

Note to self: Try behave --verbose for diagnosis (as proposed by Jens)

bittner avatar Jul 24 '18 16:07 bittner

Side note: In the builds a CLI test is failing, but really the multiple-feature-directories.feature should fail for the problem the failing build is exposing. :worried:

bittner avatar Oct 21 '18 16:10 bittner

Current result of problem analysis, after some refactoring:

A) When a single path is specified in the behave configuration everything works as expected, e.g.

[behave]
paths = tests/acceptance

... even with some special directory layout, e.g.

tests/acceptance/
├── environment.py
├── features
│   └── foo-bar.feature
└── steps
    └── foo_bar.py

B) When several paths are specified neither of those paths is looked at, e.g.

[behave]
paths =
    tests/acceptance
    tests/test_app/features

... same with just the parent path, e.g.

[behave]
paths =
    tests/acceptance
    tests/test_app

C) When a single path is specified in the ini-style file list notation the execution fails alike, e.g.

[behave]
paths =
    tests/test_app/features

Hence, it looks like the ini-style file list notation is causing problems. Or, in other words, behave only accepts paths to be a (single line of) string.

bittner avatar Oct 21 '18 22:10 bittner

Aha! Gotcha!

The behave documentation shows a configuration example, which starts the value list right in the same line as the equal sign. This syntax, interestingly enough, works. However, if only one of the locations contains a steps/ directory that location has to come first!

Example:

[behave]
paths = tests/acceptance
        tests/test_app

In this setup the tests/acceptance folder has to contain both a features/ and a steps/ (or a combined features/steps/) folder. Here it's sufficient that tests/test_app only contains a features/ directory (no steps!).

The other way round:

[behave]
paths = tests/test_app
        tests/acceptance

... behave will abort execution:

ConfigError: No steps directory in '/home/.../repos/behave-django/tests/test_app'

I'm not sure whether both behaviors are intended:

  1. sequence<text> is a text with newlines (not a list), list syntax is not allowed or meant to be used -- (see documentation)
  2. *.feature files can be scattered around in several locations, but (at least) the first location does have to also provide a steps/ directory with the implementations. (Yet still, the steps implementations will be shared. The first location may even just point to a steps/ directory.) -- (the documentation doesn't mention this explicitly)

@jenisys, any comments or clarifications?

bittner avatar Oct 22 '18 07:10 bittner

@bittner Currently, only one location for the steps is supported per test run. You can work around that by using build-scripts (makefile, invoke, etc.) to run behave with a list of folders (as sequence).

NOTE: The configparser module implements/requires the behaviour that the first item needs to be in the first line. Normal case for "append-mode" where many values are allowed.

jenisys avatar Oct 22 '18 18:10 jenisys

The configparser module implements/requires the behaviour that the first item needs to be in the first line. Normal case for "append-mode" where many values are allowed.

When I try ConfigParser with a "list-style" syntax it's returning me the string value starting with a newline. Hence, the behavior in Behave may be implementation-specific and could be changed. Any thoughts?

>>> cp = configparser.ConfigParser()
>>> list_config = """[behave]
... my_list =
...     foo
...     bar
...     baz
... """
>>> cp.read_string(list_config)
>>> cp['behave'].get('my_list')
'\nfoo\nbar\nbaz'

bittner avatar Oct 23 '18 07:10 bittner

Provide a pull-request for behave/configuration.py:399 that "corrects" this behaviour (but a trailing .split() or .splitlines() is still needed).

NOTE:

  • Weird that the slightly different API usage results in different behaviour ?!?
  • Note that your example will raise an exception if the [behave] section does not exist.
  • I encountered this behaviour in many other projects w/ configparser (and argparse).

jenisys avatar Oct 23 '18 19:10 jenisys

@jenisys The fix for this is really easy. Writing the tests (mocking the ConfigParser) is a pain, though. I've tried this with a colleague. Not nice. I may place a PR anytime soon.

bittner avatar Dec 02 '18 23:12 bittner