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

Behave v1.2.7.dev3 breaks management command

Open bittner opened this issue 2 years ago • 5 comments

behave-django currently depends on behave v1.2.7.dev2 and we're unable to upgrade to v1.2.7.dev3 (which, for example, sports TOML support), because our code depends on a symbol imported from behave.configuration that was removed in https://github.com/behave/behave/commit/596f339ab9ee8ea9608b08dc826560b9474acc28. The related code was a validation function for argparse:

def valid_python_module(path):
    try:
        module_path, class_name = path.rsplit('.', 1)
        module = import_module(module_path)
        return getattr(module, class_name)
    except (ValueError, AttributeError, ImportError):
        raise argparse.ArgumentTypeError("No module named '%s' was found." % path)

To fix the issue quickly, I'm tempted to add the code removed from behave to our codebase. OTOH, there doesn't seem to be any validation of this kind in the codebase for behave at all anymore. I'm wondering why.

Should we add it back in or did you remove it for a reason, @jenisys?

bittner avatar May 08 '23 17:05 bittner

In addition, this new development version changes the --runner-class option (--behave-runner-class for behave-django) to -r and --runner, which adds both a conflict (for -r == "reverse" in behave-django) and a backward-incompatible change.

To keep confusion low, I'll align our --runner-class option with the change applied to the behave codebase. This will introduce two new options --behave-runner and --runner, and drop --behave-runner-class and --runner-class.

Both options (they were added with PR #130) were not part of a release on PyPI, so I won't implement a deprecation path.

bittner avatar May 08 '23 18:05 bittner

@bittner I removed it on purpose because behave.configuration does not need it and I stumbled over a number of problems and deficiencies while testing the runner as extension-point:

  • The above implementation of valid_python_module() does not really help the user when something is wrong. Meaning, the user does not get the real reason what is wrong and what he/she should change/correct. Possible failure reasons are: ModuleNotFound, ClassNotFound, InvalidClass, ... (see: BAD CASES below)

  • I wanted to support runner aliases in the config-file (to simplify the use of a runner-class on the command-line). In this case, the command-line option value is a string/name but not a scoped-class-name (with module prefix) and cannot be directly imported. Therefore, it was better to post-pone the runner-import until just before it is used (in the RunnerPlugin).

  • All extension-points in behave that load classes-by-name, use the schema: <DOTTED_MODULE_NAME>:<CLASS_NAME> (like: pytest ) Therefore, I did not want to support the dotted-only-module-and-class-name-schema here.

THEREFORE: If you really need the valid_python_module() function, you should add the code to your code base. Alternatives are:

  • use the RunnerPlugin class or
  • implement the valid_python_module() function by using the RunnerPlugin class

SEE ALSO:

jenisys avatar May 08 '23 19:05 jenisys

Okay, I understand. Thanks for explaining.

I'll try to restore the state that was working earlier for now, changing the CLI options as mentioned above. What we get by this is better than a broken state albeit not ideal: Similar-sounding options that accept a different syntax for "the same thing".

@kingbuzzman Would you have time (and motivation) to look into the RunnerPlugin route?

bittner avatar May 08 '23 20:05 bittner

Hello. Not really sure if this is related to this comment https://github.com/behave/behave-django/issues/147#issuecomment-1538915715

It seems that using a runner configuration on .behaverc is not working. I can run it fine using the management command python manage.py behave --runner "tests.integration.runner:BehaveAzionRunner" but if I try to configure on .behaverc like this

[behave]
runner=tests.integration.runner:BehaveCustomRunner

and run just with python manage.py behave

then I get the following error:

BAD_RUNNER_CLASS: FAILED to load runner.class=tests.integration.runner:BehaveCustomRunner (InvalidClassError)
InvalidClassError: is not a subclass-of 'behave.api.runner:ITestRunner'

Is there something I'm doing wrong over here?

vinigfer avatar Oct 11 '23 21:10 vinigfer

The error message clearly states what you are doing wrong. Your test runner should inherit from behave.api.runner:ITestRunner interface class (which it does not).

BACKGROUND: The first implementation of the runner-classes as extension point hat some limitations. It did not catch some problems that people run into. The current implementation checks for these problems. To be able to do that you must implement the interface for a runner-class.

jenisys avatar Oct 12 '23 08:10 jenisys