Importing behave python steps from subdirectories

The problem

While using the python behave 1.2.7, you may soon end-up with multiple steps trying to find a way to organise them into subdirectories.

tests/
+-- feature/
     +-- *.feature
+-- steps/
    +-- menu_steps/
        +-- user_menu_steps.py
        +-- admin_menu_steps.py
        +-- organisation_menu_steps.py
    +-- profile_steps/
        +-- user_profile_steps.py
        +-- admin_profile_steps.py
environment.py
behave.ini

However, the above strategy will leave the behave runner complaining that the steps could not be found.

"Undefined step. Rest part of scenario is skipped"

The Solution

A way to go resolve this issue is the following

Step 1

Convert all step subdirectories into modules by adding an empty __init__.py file in every step subdirectory.

+-- steps/
    +-- __init__.py
    +-- menu_steps/
        +-- __init__.py
        +-- user_menu_steps.py
        +-- admin_menu_steps.py
        +-- organisation_menu_steps.py
    +-- profile_steps/
        +-- __init__.py
        +-- user_profile_steps.py
        +-- admin_profile_steps.py

Step 2

Import dynamically all step submodules within the steps directory by adding the following at the steps/__init__.py

import os
import pkgutil

__all__ = []
PATH = [os.path.dirname(__file__)]
for loader, module_name, is_pkg in pkgutil.walk_packages(PATH):
    __all__.append(module_name)
    _module = loader.find_module(module_name).load_module(module_name)
    globals()[module_name] = _module

(Based on: https://stackoverflow.com/questions/3365740/how-to-import-all-submodules/3365846#3365846 )

Done !

We have tested the above code using Python 3.7 and python-behave 1.2.7 .

%d bloggers like this: