Geek Culture
Published in

Geek Culture

How to avoid file name collisions in pytest

Significance of __init__.py in pytest

https://dock2learn.com/tech/how-to-avoid-file-name-collisions-in-pytest/

Introduction:

While writing unit tests for projects with multiple directories using pytest, have you ever tried naming two test files in different directories with same name? Let’s try doing that with a small example.

Naming test files:

Let’s say we have a directory structure like below.

-- tests
|__unit
|__dir1
|__test_file.py
|__dir2
|__test_file.py

dir1/test_file.py

def test_my_function_dir1():
print(f" Inside test_my_function_dir1 ")

dir1/test_file.py

def test_my_function_dir2():
print(f" Inside test_my_function_dir2 ")

Try executing the test_file.py file from dir1 and test_file.py from dir2.

(practo-env)dir1 % pytest
===================== test session starts ===================
platform darwin -- Python 3.9.9, pytest-7.0.1, pluggy-1.0.0
rootdir: /Users/tests/unit/dir1
collected 1 item

test_file.py . [100%]

====================== 1 passed in 0.00s ======================
(practo-env)dir2 % pytest
===================== test session starts ===================
platform darwin -- Python 3.9.9, pytest-7.0.1, pluggy-1.0.0
rootdir: /Users/tests/unit/dir2
collected 1 item

test_file.py . [100%]

====================== 1 passed in 0.00s ======================

In both the cases, the tests pass without any failures or warnings. Now, let’s try running the tests from the unit directory.

(practo-env) unit % pytest
======================== test session starts ==============
platform darwin -- Python 3.9.9, pytest-7.0.1, pluggy-1.0.0
rootdir: /Users/tests/unit
collected 1 item / 1 error

========================= ERRORS ===========================
______________ ERROR collecting dir2/test_file.py ______
import file mismatch:
imported module 'test_file' has this __file__ attribute:
/Users/tests/unit/dir1/test_file.py
which is not the same as the test file we want to collect:
/Users/tests/unit/dir2/test_file.py
HINT: remove __pycache__ / .pyc files and/or use a unique basename for your test file modules
======================= short test summary info ===============
ERROR dir2/test_file.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
========================== 1 error in 0.06s ===================

Despite the files have different tests, they still fail when they run as a complete set of tests from the root directory.

The Solution:

Adding an empty __init__.py file to all the test sub-directories can avoid this issue.In our case both dir1 and dir2 should have a __init__.py file.

-- tests
|__unit
|__dir1
|__test_file.py
|__ __init__.py
|__dir2
|__test_file.py
|__ __init__.py

Now we have added __init__.py files in dir1 and dir2. Let’s try re-running the tests from unit directory.

(practo-env) dkb@dkb-a01 unit % pytest
============== test session starts ========================
platform darwin -- Python 3.9.9, pytest-7.0.1, pluggy-1.0.0
rootdir: /Users/tests/unit
collected 2 items

dir1/test_file.py . [ 50%]
dir2/test_file.py . [100%]

=========================== 2 passed in 0.01s ==============

The advantage of having an __init__.py file is we could have the same test file names in multiple test sub-directories. Now, the million dollar question is why would we even have such scenario? And would we ever run into one?

We may have to segregate our tests into unit and component tests and we may end-up naming the same name to the same test files. This is just one use case I can think of.

Well, we may run into such scenario..may be not..It doesn’t hurt to add the file as a pre-caution. Does it?

Happy Learning!!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store