I am stuck with this incredibly silly error. I am trying to run pytest on a Raspberry Pi using bluepy.
pi@pi:~/bluepy/bluepy $ pytest test_asdf.py
============================= test session starts ==============================
platform linux2 -- Python 2.7.9, pytest-3.0.7, py-1.4.33, pluggy-0.4.0
rootdir: /home/pi/bluepy, inifile:
collected 0 items / 1 errors
==================================== ERRORS ====================================
______________ ERROR collecting bluepy/test_bluetoothutility.py _______________
ImportError while importing test module '/home/pi/bluepy/bluepy/test_asdf.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test_asdf:4: in <module>
from asdf import AsDf
asdf.py:2: in <module>
from bluepy.btle import *
E ImportError: No module named btle
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!
=========================== 1 error in 0.65 seconds ============================
I realised that my problem could be that rootdir is showing incorrect path. It should be
/home/pi/bluepy/bluepy
I've been reading pytest docs but I just do not get it how to change the rootdir.
Your problem is nothing to do with Pytest's rootdir.
The rootdir in Pytest has no connection to how test package names are constructed and rootdir is not added to sys.path
, as you can see from the problem you were experiencing. (Beware: the directory that is considered rootdir may be added to the path for other reasons, such as it also being the current working directory when you run python -m pytest
.)
The problem here, as others have described, is that the top-level bluepy/
is not in sys.path
. The easiest way to handle this if you just want to get something running interactively for yourself is as per Cecil Curry's answer: cd
to the top-level bluepy
and run Pytest as python -m pytest bluepy/test_asdf.py
(or just python -m pytest
if you want it to discover all test_*
files in or under the current directory and run them). But I think you will need to use python -m pytest
, not just pytest
, in order to make sure that the current working directory is in the path.
If you're looking to set up a test framework that others can easily run without mysterious failures like this, you'll want to set up a test script that sets the current working directory or PYTHONPATH
or whatever appropriately. Or use tox
. Or just make this a Python package using standard tools that can run the tests for you. (All that goes way beyond the scope of this question.)
By the way, I concur with Cecil's opinion of Mackie Messer's answer; messing around with conftest.py
like that is overly difficult and fragile; there are better solutions for almost any circumstance.
Appendix: Use of rootdir
There are only two things, as far as I'm aware, for which rootdir is used:
.pytest_cache/
directory is stored in the rootdir unless otherwise specified (with the cache_dir
configuration option).conftest.py
, it will always be loaded, even if no test files are loaded from in or under the rootdir. The documentation claims that the rootdir also used to generate nodeids, but adding a conftest.py
containing
def pytest_runtest_logstart(nodeid, location):
print("logstart nodeid={} location={}".format(nodeid, location))
and running pytest --rootdir=/somewhere/way/outside/the/tree
shows that to be incorrect (though node locations are relative to the rootdir).
Actually, py.test
is correctly discovering the rootdir
for your project to be /home/pi/bluepy
. That's good.
Tragically, you are erroneously attempting to run py.test
within your project's package subdirectory (i.e., /home/pi/bluepy/bluepy
) rather than within your project's rootdir
(i.e., /home/pi/bluepy
). That's bad.
Let's break this down a little. From within the:
/home/pi/bluepy
directory, there is a bluepy.btle
submodule. (Good.)
/home/pi/bluepy/bluepy
subdirectory, there is no bluepy.btle
submodule. (Bad.) Unless you awkwardly attempt to manually inject the parent directory of this subdirectory (i.e., /home/pi/bluepy
) onto sys.path
as Makie Messer perhaps inadvisably advises, Python has no means of inferring that the package bluepy
actually refers to the current directory coincidentally also named bluepy
. To avoid ambiguity issues of this sort, Python is typically only run outside rather than inside of a project's package subdirectory.Since you ran py.test
from the latter rather than the former directory, Python is unable to find the bluepy.btle
submodule on the current sys.path
. For this and similar reasons, py.test
should typically only ever be run from your project's top-level rootdir
(i.e., /home/pi/bluepy
):
pi@pi:~/ $ cd ~/bluepy
pi@pi:~/bluepy $ py.test bluepy/test_asdf.py
Lastly, note that it's typically preferable to defer test discovery to py.test
. Rather than explicitly listing all test script filenames on the command line, consider instead letting py.test
implicitly find and run all tests containing some substring via the -k
option. For example, to run all tests whose function names are prefixed by test_asdf
(regardless of the test script they reside in):
pi@pi:~/ $ cd ~/bluepy
pi@pi:~/bluepy $ py.test -k test_asdf .
The suffixing .
is optional, but often useful. It instructs py.test
to set its rootdir
property to the current directory (i.e., /home/pi/bluepy
). py.test
is usually capable of finding your project's rootdir
and setting this property on its own, but it can't hurt to specify it manually. (Especially as you're having... issues.)
For further details on rootdir
discovery, see Initialization: determining rootdir and inifile in the official py.test
documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With