python-3.xaws-lambdaaws-sam-cliaws-samaws-toolkit

Python import statement. ModuleNotFoundError: when running tests and referencing a module in a parent folder


Question: How do I fix the import statement in my test file?

================================================

I run the following commands:

commands to run up the tests

cd cluster_health
python -m pytest tests/ -v -s

I then get the following error!

    ImportError while importing test module '<full path>...\cluster_health\tests\unit\test_handler.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests\unit\test_handler.py:5: in <module>
    from health_check import app
health_check\app.py:3: in <module>
    import my_elastic_search
E   ModuleNotFoundError: No module named 'my_elastic_search'

.\cluster_health\tests\unit\test_handler.py

import json
import sys
import pytest
import health_check
from health_check import app
from health_check import my_elastic_search
# from unittest.mock import patch
import mock
from mock import Mock

def test_lambda_handler(apigw_event, monkeypatch):
    CONN = Mock(return_value="banana")
    monkeypatch.setattr('health_check.my_elastic_search.connect', CONN)
    ret = app.lambda_handler(apigw_event, "")    
    # etc...

.\cluster_health\health_check\app.py

import json
import sys
import my_elastic_search

def lambda_handler(event, context):
    print(my_elastic_search.connect("myhost", "myuser", "mypass"))
    # etc

.\cluster_health\health_check\my_elastic_search.py

def connect(the_host, the_user, the_pass):
    return "You are connected!"

Solution

  • Thanks to importing modules from parent folder and @woofless (above) here is my solution to the problem (the problem statement really is that I am referencing a module in a parent directory. The scaffolding for the AWS Toolkit for Visual Studio with SAM does not provide the appropriate code to reference additional parent modules adequately)!

    Note the sys.path.insert below. Additionally, as per @woofless I simplified my namespace reference so that it does not reference the root folder "health_check". Voila!

    .\cluster_health\tests\unit\test_handler.py

    import sys, os, inspect
    currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
    parentdir = os.path.dirname(currentdir)
    parentdir = "%s\\health_check"%os.path.dirname(parentdir)
    sys.path.insert(0,parentdir)
    print(parentdir)
    
    import json
    
    import pytest
    import health_check
    import app
    import my_elastic_search