'python unittest ModuleNotFoundError: No module named <...>
I tried to crate simple Python project with flask and unittest. Structure is quite simple:
classes
|-sysinfo
|static
|templates
|- index.html
|- layout.html
|__init__.py
|sysinfo.py
|printinfo.py
tests
|test_sysinfo.py
README.md
requirments.txt
Very simple class in printinfo.py:
#!/usr/bin/python
import psutil
import json
class SysInfo:
.......
def displayInfo(self):
.......
return json.dumps(self.__data)
And simple flask server run with sysinfo.py:
from flask import Flask, flash, redirect, render_template, request, session, abort
from printinfo import SysInfo
import json
obj1 = SysInfo("gb")
app = Flask(__name__)
@app.route('/')
def index():
var = json.loads(obj1.displayInfo())
return render_template('index.html',**locals())
@app.route('/healthcheck')
def healthcheck():
return "Ok"
@app.route("/api/all")
def all():
return obj1.displayInfo()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
del obj1
I run it with python sysinfo.py staying in classes/sysinfo folder and everything works ok.
So I decided to run unittest for my application. Put in classes/tests ( also tried classes/sysinfo/tests) file test_sysinfo.py with code:
import unittest
import printinfo
from sysinfo import sysinfo
import json
import sys
class TestFlaskApi(unittest.TestCase):
def setUp(self):
self.app = sysinfo.app.test_client()
def simple_test(self):
response = self.app.get('/health')
self.assertEqual(
json.loads(response.get_data().decode(sys.getdefaultencoding())),
{'healthcheck': 'ok'}
)
if __name__ == "__main__":
unittest.main()
And when I started it I can see error:
Error Traceback (most recent call last):
File "\Python\Python37-32\lib\unittest\case.py", line 59, in testPartExecutor
yield File "\Python\Python37-32\lib\unittest\case.py", line 615, in run
testMethod() File "\Python\Python37-32\lib\unittest\loader.py", line 34, in testFailure
raise self._exception ImportError: Failed to import test module: test_sysinfo Traceback (most recent call last): File
"\Python\Python37-32\lib\unittest\loader.py", line 154, in
loadTestsFromName
module = __import__(module_name) File "\classes\sysinfo\tests\test_sysinfo.py", line 2, in <module>
import printinfo ModuleNotFoundError: No module named 'printinfo'
I read several articles, some topics here on StackOverflow for my understanding it's related to project structure. I tried to create setup.py and setup.cfg. I managed to start it with this setup, but test still didn't work.
Could you please help me with minimum setup applicable for my case? All the material I found had written for specific case or too general. I cannot apply it for my case.
Solution 1:[1]
Follow flask tutorial I edit __init__.py file to start app from here:
from flask import Flask, flash, redirect, render_template, request, session, abort
from . import printinfo
import json
import os
obj1 = printinfo.SysInfo("gb")
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev'
)
obj1 = printinfo.SysInfo("gb")
@app.route('/')
def index():
var = json.loads(obj1.displayInfo())
return render_template('index.html', **locals())
@app.route('/healthcheck')
def healthcheck():
return "Ok"
@app.route("/api/all")
def all():
return obj1.displayInfo()
#del obj1
return app
Also environment variables should be set for Flask: For Linux and Mac:
export FLASK_APP=sysinfo
export FLASK_ENV=development
For Windows cmd, use set instead of export:
set FLASK_APP=sysinfo
set FLASK_ENV=development
And run application:
flask run
It run application on localhost on port 5000 since development env set. Anyway I needed to add from . import printinfo into __init__.py.
Didn't try test, but think it should work. If interesting will update soon.
Solution 2:[2]
Just followed Flask tutorial. Created conftest.py and test_factory.py. Run Ok with pytest:
import pytest
from sysinfo import create_app
from sysinfo import printinfo
@pytest.fixture
def app():
app = create_app({
'TESTING': True
})
with app.app_context():
printinfo.SysInfo("gb")
yield app
Probably the same setup could be used with unittest. Didn't try.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dmytro |
| Solution 2 | Dmytro |
