Reputation: 437
Right now I have the following directory of test features:
Tests/
--BehaveTest1/
----BehaveTest1.feature
----steps/
------test_steps.py
--BehaveTest2/
----BehaveTest2.feature
----steps/
------test_steps.py
As the test steps for BehaveTest1 and BehaveTest2 are common, I'd like to implement a common module that could be called by both test cases when they need to. At the moment I have made a common/ directory inside the Tests/ folder and import it (inside the test_steps.py files for each test feature) by:
import sys, os
sys.path.append('../common')
import common
But I do not want to mess with the path so I was wondering if there are any better ways to do this with the structure of behave test features?
Upvotes: 4
Views: 9016
Reputation: 1
It is possible to have a structure like this, the steps from alice.features and bob.features will run if I run this command : "behave" or "behave --tags @"
DIRECTORY STRUCTURE:
+-- features/
+-- steps/ (optional, common steps)
+-- alice.features/
| +-- steps/ (specific steps for alice sub features, can use common steps)
| +-- *.feature
+-- bob.features/
+-- steps/
+-- *.feature
+-- environment.py
Upvotes: 0
Reputation: 437
The most flexible way to do this for me was to create a folder of my classes inside my steps folder:
features/test.feature
test_steps/
test_steps/classes
test_environment.py
Upvotes: -3
Reputation: 151380
There is no need to mess with sys.path
, and this is not dependent on the version of Python you are using. This works just as well with Python 2.7 or Python 3.x.
Given the following file structure:
Tests/
├── BehaveTest1
│ ├── BehaveTest1.feature
│ └── steps
│ └── test_steps.py
├── BehaveTest2
│ ├── BehaveTest2.feature
│ └── steps
│ └── test_steps.py
├── common.py
├── __init__.py
The presence of __init__.py
in the Tests
directory is key. It is an empty file, but without it, Python will fail to load the module because Tests
won't be considered to be a package.
I can have test_steps.py
in both directories just do:
import Tests.common
And the Tests/common.py
file contains:
from behave import when, then
@when("foo")
def foo(context):
pass
@then("bar")
def bar(context):
pass
@when
and @then
are automatically put into the files that Behave loads from the steps/
subdirectories but not from any other module that you load with import
.
I can then run it with fake feature files that call upon the steps defined in common.py
:
$ behave Tests/BehaveTest*
Feature: BehaveTest1 # Tests/BehaveTest1/BehaveTest1.feature:1
Scenario: foo # Tests/BehaveTest1/BehaveTest1.feature:3
When foo # Tests/common.py:3 0.000s
Then bar # Tests/common.py:7 0.000s
Feature: BehaveTest2 # Tests/BehaveTest2/BehaveTest2.feature:1
Scenario: foo # Tests/BehaveTest2/BehaveTest2.feature:3
When foo # Tests/common.py:3 0.000s
Then bar # Tests/common.py:7 0.000s
2 features passed, 0 failed, 0 skipped
2 scenarios passed, 0 failed, 0 skipped
4 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m0.000s
Upvotes: 10
Reputation: 61
Actually there is no other way like the way you are doing it:
You want to import code from some location. That means you need to make python aware of this location. And that is done via the PYTHONPATH or sys.path.append().
Behave is (as far as I know) only able to find code in the "steps" directory where the feature-file is located. If you have additional code, you have to set the sys.path.
In python > 3.3 it can be bit easier, since the "namespace" packages (pep420) makes it possible to call
:$ behave Tests/BehaveTest1/BehaveTest1.feature
within the parent folder of your Tests directory. Then you would have to do
import Tests.common
within your step files.
That is because Tests, BehaveTests1 and BehaveTests2 would become a python package.
Upvotes: 0