Reputation: 45
I have two different python file under steps directory: driverlogon.py and triplogon.py
driverlogon.py defines the step
@when(u'enter the {driver_id}')
def step_enter_the_driver_id(context,driver_id):
SelectDriver.input_driver(driver_id)
triplogon.py defines the step
@when(u'enter the configured block number')
def step_enter_the_configured_block_number(context):
ByBlock.enter_block(context.block)
when I run this program, I get the following error message
in this case they have different text and even the content of the function is different.
why is it happening, can anyone help me to understand this? Thanks in advance
Exception AmbiguousStep: @when('enter the configured block number') has already been defined in
existing step @when('enter the {driver_id}') at steps/driverlogon.py:26
Traceback (most recent call last):
File "C:\Program Files (x86)\Python\Lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "C:\Program Files (x86)\Python\Lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Program Files (x86)\Python\Scripts\behave.exe\__main__.py", line 7, in <module>
File "c:\program files (x86)\python\lib\site-packages\behave\__main__.py", line 183, in main
return run_behave(config)
File "c:\program files (x86)\python\lib\site-packages\behave\__main__.py", line 127, in run_behave
failed = runner.run()
File "c:\program files (x86)\python\lib\site-packages\behave\runner.py", line 804, in run
return self.run_with_paths()
File "c:\program files (x86)\python\lib\site-packages\behave\runner.py", line 809, in run_with_paths
self.load_step_definitions()
File "c:\program files (x86)\python\lib\site-packages\behave\runner.py", line 796, in load_step_definitions
load_step_modules(step_paths)
File "c:\program files (x86)\python\lib\site-packages\behave\runner_util.py", line 412, in load_step_modules
exec_file(os.path.join(path, name), step_module_globals)
File "c:\program files (x86)\python\lib\site-packages\behave\runner_util.py", line 386, in exec_file
exec(code, globals_, locals_)
File "steps\triplogon.py", line 23, in <module>
@when(u'enter the configured block number')
File "c:\program files (x86)\python\lib\site-packages\behave\step_registry.py", line 92, in wrapper
self.add_step_definition(step_type, step_text, func)
File "c:\program files (x86)\python\lib\site-packages\behave\step_registry.py", line 58, in add_step_definition
raise AmbiguousStep(message % (new_step, existing_step))
behave.step_registry.AmbiguousStep: @when('enter the configured block number') has already been defined in
existing step @when('enter the {driver_id}') at steps/driverlogon.py:26
Upvotes: 4
Views: 3825
Reputation: 2151
Thanks @Janos.
I'll just extract that behave
issue results here to summarize the solution.
Add the type specifier to the parameter (e.g :S or :d)
@when(u'enter the {driver_id:S}')
def step_enter_the_driver_id(context,driver_id):
SelectDriver.input_driver(driver_id)
@when(u'enter the configured block number')
def step_enter_the_configured_block_number(context):
ByBlock.enter_block(context.block)
Put more complex (longer?) definition first. So if you put it in one file it would be:
@when(u'enter the configured block number')
def step_enter_the_configured_block_number(context):
ByBlock.enter_block(context.block)
@when(u'enter the {driver_id}')
def step_enter_the_driver_id(context,driver_id):
SelectDriver.input_driver(driver_id)
Or check if renaming the files does the trick, if the one with more complex definition is alphabetically before the other one.
Upvotes: 1
Reputation: 856
Even though the answer of @automationleg may be correct in this particular case, the ambiguity issue comes from another direction and cannot always be solved by using double quotes. Ambiguity could still be present.
See this ticket for details: https://github.com/behave/behave/issues/435.
The correct solution is to use type patterns for parameters, otherwise the possessive parser is used and consumes as much as possible - leaving room for supposedly duplicates.
Upvotes: 2
Reputation: 3300
The way step definitions work is as follows:
def step_impl
enter the {driver_id}
enter the configured block number
enter the {driver_id}
, and associates that with the function step_impl
enter the configured block number
, and attempts to associate it with its function definition, but finds that a function step_impl
has already been defined and associated with feature text. No knowing what to do, Behave throws the AmbiguousStep
exception to let you know that a function name has been used twice.To fix this issue, you need to make sure your function names are unique across all step definition files. So in your case, you have two files that each define a function called step_impl
. What you should do is rename these functions with unique names, so that Behave can properly correlate these names at run time. To make sure the names are unique, I recommend choosing names that closely match the decorated text. If it were me writing these definitions, I would rewrite them as follows:
driverlogon.py
@when(u'enter the {driver_id}')
def step_enter_the_driver_id(context,driver_id):
SelectDriver.input_driver(driver_id)
triplogon.py
@when(u'enter the configured block number')
def step_enter_the_configured_block_number(context):
ByBlock.block_data(context.block)
Edit #1:
Thank you for including the stack trace. From that it appears that you have defined the same step twice in two different files:
File "steps\triplogon.py", line 23, in <module>
@when(u'enter the configured block number')
File "c:\program files (x86)\python\lib\site-packages\behave\step_registry.py", line 92, in wrapper
self.add_step_definition(step_type, step_text, func)
File "c:\program files (x86)\python\lib\site-packages\behave\step_registry.py", line 58, in add_step_definition
raise AmbiguousStep(message % (new_step, existing_step))
behave.step_registry.AmbiguousStep: @when('enter the configured block number') has already been defined in
existing step @when('enter the {driver_id}') at steps/driverlogon.py:26
You'll note that at the top line it says:
File "steps\triplogon.py", line 23, in <module>
@when(u'enter the configured block number')
Indicating that the step enter the configured block number
is defined in triplogon.py
Then the last line of the trace says:
behave.step_registry.AmbiguousStep: @when('enter the configured block number') has already been defined in
existing step @when('enter the {driver_id}') at steps/driverlogon.py:26
Which indicates that enter the configured block number
has also been defined in driverlogon.py
Make sure that the step has only been defined in one of the two files.
Upvotes: -1
Reputation: 323
As a solution if you want to keep these names you could write:
driverlogon.py
@when(u'enter the "{driver_id}"')
def step_enter_the_driver_id(context,driver_id):
SelectDriver.input_driver(driver_id)
triplogon.py
@when(u'enter the configured block number')
def step_enter_the_configured_block_number(context):
ByBlock.block_data(context.block)
Exception will not be raised in this case, but the driver_id will be passed as string and step is going to look like the following:
When enter the "10"
But, if you would like it to be parsed as int instead you can use predefined data types d
in this case like below:
@when(u'enter the "{driver_id:d}"')
def step_enter_the_driver_id(context,driver_id):
SelectDriver.input_driver(driver_id)
https://behave.readthedocs.io/en/latest/parse_builtin_types.html
Upvotes: 1