… which is not the same as the test file we want to collect [pytest + dh_auto_build]

George Shuklin
OpsOps
Published in
2 min readNov 17, 2016

Yet another gory story from devops trenches.

I created a python application. I wanted to package it. I wrote setup.py, I wrote tests in tests/ directory, I got 100% code coverage. I created git branch for debianization, I wrote debian/control, debian/rules, debian/changelog (and a few more to comply Debian policy). It all looks proper and shiny. I want to build it with git-buildpackage (AKA gbp).

$ gbp buildpackage

build/lib.linux-x86_64–2.7/tests/test_config.py ………………
================= ERRORS =====================
_____ ERROR collecting tests/test_config.py ___________________
import file mismatch:
imported module ‘tests.test_config’ has this __file__ attribute:
/home/amarao/git/dibctl/build/lib.linux-x86_64–2.7/tests/test_config.py
which is not the same as the test file we want to collect:
/home/amarao/git/dibctl/tests/test_config.py
HINT: remove __pycache__ / .pyc files and/or use a unique basename for your test file modules

Why, why, I done it fine, aren’t I?

Small bisect restricts all this large gbp machinery to smaller command sequence:

dh_auto_build
py.test

dh_auto_build itself calls to ‘setup.py build’. It just copies files in the package:

creating build/lib.linux-x86_64–2.7
creating build/lib.linux-x86_64–2.7/tests
copying tests/test_config.py -> build/lib.linux-x86_64–2.7/tests
copying tests/__init__.py -> build/lib.linux-x86_64–2.7/tests
copying tests/test_dib.py -> build/lib.linux-x86_64–2.7/tests
copying tests/test_dibctl.py -> build/lib.linux-x86_64–2.7/tests
creating build/lib.linux-x86_64–2.7/dibctl
copying dibctl/dib.py -> build/lib.linux-x86_64–2.7/dibctl
copying dibctl/config.py -> build/lib.linux-x86_64–2.7/dibctl
copying dibctl/__init__.py -> build/lib.linux-x86_64–2.7/dibctl
copying dibctl/dibctl.py -> build/lib.linux-x86_64–2.7/dibctl

And duplicates of those file annoy pytest to the death:

$ find -name “test*.py”
./build/lib.linux-x86_64–2.7/tests/test_config.py
./build/lib.linux-x86_64–2.7/tests/test_dib.py
./build/lib.linux-x86_64–2.7/tests/test_dibctl.py
./tests/test_config.py
./tests/test_dib.py
./tests/test_dibctl.py

There are few nice results when googling in Duckduckgo about this pytest error message. The most important is this stackoverflow question (and its answer).

To make py.test works one should give up __init__.py in the tests directory (to allow relative import of the ‘parent’ code) or one should mangle with the pytest tests discovery sequence.

My old debian/rules looked like this:

#!/usr/bin/make -foverride_dh_auto_test:
py.test
%:
dh $@

Now it looks like this:

#!/usr/bin/make -foverride_dh_auto_test:
py.test build/
%:
dh $@

(I prefer ‘build/’ to ‘build’ because of the future readers. I don’t want them to confuse path (‘build/’) with make command ‘build’).

--

--

George Shuklin
OpsOps

I work at Servers.com, most of my stories are about Ansible, Ceph, Python, Openstack and Linux. My hobby is Rust.