u84six
u84six

Reputation: 4941

pytest (or unittest) not working when a source file has a dependency

I'm not sure why this is so difficult to get going, but I'm new to Python and I'm trying to get any unit test framework to run tests, but if I test a file that has a dependency, I get "Module Not Found". I've seen similar posts on SO but none of them solve my problem. I'm using Python on Windows.

The project structure is like this:

some_project
---- my_app
     ---- my_app.py
     ---- my_lib.py
---- test
     ---- test_my_app.py

In my_app.py, I have something like:

 def say_hello(name: str) -> str:
         return f"Hello, {name}"

In test_my_app.py, I have:

from my_app.my_app import say_hello
def test_say_hello():
    assert say_hello("Bob") == "Hello, Bob"

Then when I run pytest, everything works and the test passes. But if I add a dependency into the mix by including my_lib.py:

In my_lib.py:

def concat(s1: str, s2: str) -> str:
    return f"{s1}, {s2}"

Then in my_app.py:

from my_lib import concat
def say_hello(name: str) -> str:
    return concat("Hello", name)

When I run pytest, I get the error "ModuleNotFoundError: No module named 'my_lib'

How is it that it can find my_app.py but can't find my_lib.py? They're in the same package. I've looked for solutions in the pytest docs and python documentation, but not much there about it. I played around with editing sys.path, but haven't been able to get it right. I put init.py files in both the my_app package and the test package, but that didn't change anything. Does anyone have a solution to this? Why is it so difficult to get unit tests to work in Python?

Upvotes: 0

Views: 2427

Answers (2)

Zaxxon
Zaxxon

Reputation: 667

Kept running into this issue myself. First thing I got thru was pytest not being found. Turned out I needed to run my console in Windows with "Run as Administrator...". After that, and reinstalling "pip install pytest -U" one last time (not sure if that was needed but I did it anyways), pytest started working.

Then I added a __init__.py file in my tests folder.

some_project
---- my_app
     ---- my_app.py
     ---- my_lib.py
---- tests
     ---- __init__.py
     ---- conftest.py
     ---- setup_my_app.py
     ---- test_my_app.py
     ---- test_my_app.json

And __init__.py has this in it:

# Allows us to reference other non test_...py and ..._test.py py files in our tests folder and from the parent folder. 
# Allows us to reference non .py files, like .json files
import sys
import os
    
currentdir = os.path.dirname(os.path.realpath(__file__))
parentdir = os.path.dirname(currentdir)
    
sys.path.append(currentdir)
sys.path.append(parentdir)

Then I run pytest from the "some_project" folder. If you try to run it from the "some_project/tests" folder it won't work. You can also run pytest from a parent folder of "some_project". Not sure about needing __init__.py elsewhere with this solution.

At this point, pytest will import .py files from the root of some_project if there were .py files there as well as subfolder .py files. It'll also allow you to reference non test_...py/..._test.py files, like regular py, json, etc files.

For example, in test_my_app.py I can have the following, then run pytest from the \some_project path:

import json
import pytest
import my_app
import setup_my_app


def test_something_super_important():
    with open("tests/test_my_app.json") as f:
        json_str = f.read()
    data = json.loads(json_str)
    assert 1+1 == 2

Upvotes: 0

Teejay Bruno
Teejay Bruno

Reputation: 2159

This really has nothing to do with pytest and more a general question regarding python imports. It's tough to answer your question without knowing more info, but I would recommend resetting your path and doing some quick reading regarding absolute/relative imports to see if the answer becomes apparent.

However, if I had to guess, I would say this will fix your issue.

from my_app.my_lib import concat

Upvotes: 1

Related Questions