I am creating a Python package/library. My directory structure looks like this:
my_package/
|-- my_package/
| |-- tests/
| | |-- __init__.py
| | |-- my_tests.py
| |
| |-- __init__.py
| |-- main.py
|
|-- setup.py
I have all my functions in the main.py file:
def sum_nums(a,b):
res = a + b
return(res)
def mult_nums(a,b):
res = a * b
return(res)
def sub_nums(a,b):
res = a - b
return(res)
my_tests.py looks like this:
from unittest import TestCase
import my_package
def test_sum():
assert sum_nums(3,4) == 7
def test_mult():
assert mult_nums(3,4) == 12
def test_sub():
assert sub_nums(3,4) == -1
When I run my tests from the package root directory as follows:
python setup.py test
... I get the following error:
NameError: name 'sum_nums' is not defined
Is my package directory structure correct?
Am I missing an _ init _.py file?
Does every directory require an _ init _.py file?
Is it okay to place all my functions inside a single main.py file
without using if name == "main"?
You need to indicate that the functions under test came for the my_package package like:
from unittest import TestCase
import my_package
def test_sum():
assert my_package.sum_nums(3,4) == 7
def test_mult():
assert my_package.mult_nums(3,4) == 12
def test_sub():
assert my_package.sub_nums(3,4) == -1
tests should not be in the package so move it up one dir. See sanic or any other module in github for example. Your functions need to be available in init.py. You can import them like is done in sanic.
https://github.com/huge-success/sanic
You also need
from my_package import sum_nums, mult_nums, sub_nums
Or prefix with my_package.
Related
I have 2 directories containing tests:
project/
|
|-- test/
| |
| |-- __init__.py
| |-- test_1.py
|
|-- my_submodule/
|
|-- test/
|
|-- __init__.py
|-- test_2.py
How can I run all tests?
python -m unittest discover .
only runs test_1.py
and obviously
python -m unittest discover my_submodule
only runs test_2.py
unittest currently sees project/my_submodule as an arbitrary directory to ignore, not a package to import. Just add project/my_submodule/__init__.py to change that.
Use a test suite file
A possible solution is to write a test suite file as following:
import unittest
from test import test_1
from my_submodule.test import test_2
loader = unittest.TestLoader()
suite = unittest.TestSuite()
suite.addTest(loader.loadTestsFromModule(test_1))
suite.addTest(loader.loadTestsFromModule(test_2))
runner = unittest.TextTestRunner(verbosity=3)
result = runner.run(suite)
Save the previous file in your folder project and call it runner_test.py.
I have written two example test files as following:
project/test/test_1.py
import unittest
class MyTestCase(unittest.TestCase):
def test_1(self):
print("test1")
self.assertEqual("test1", "test1")
if __name__ == '__main__':
unittest.main()
project/my_submodule/test/test_2.py
import unittest
class MyTestCase(unittest.TestCase):
def test_1(self):
print("test1")
self.assertEqual("test1", "test1")
if __name__ == '__main__':
unittest.main()
If you execute the following command:
> cd /path/to/folder/project
> python runner_test.py
The output of previous command (python runner_test.py) is:
test_1 (test.test_1.MyTestCase) ... test1
ok
test_2 (my_submodule.test.test_2.MyTestCase) ... test2
ok
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
I'm a little confused about the import in a python project.
I used this as a model to create my project:
https://docs.python-guide.org/writing/structure/
at the moment, working in spyder, I set my working directory to MyProject/
MyProject
|
|
--- mymodule
| |
| |--- myclass1.py (contains def MyClass1 )
| |
| |--- myclass2.py (contains def MyClass2 )
|
|
|--- tests
| |
| |-- test_MyClass1.py (contains def TestMyClass1(unittest.TestCase)
| |
| |
| |-- test_MyClass2.py (contains def TestMyClass2(unittest.TestCase)
then I run test_MyClass1.py
the test_MyClass1.py references the MyClass1 this way:
from mymodule.myclass1 import MyClass1
and in the myclass1.py, I reference the MyClass2 this way:
from mymodule.myclass2 import MyClass2
I read about the __init__.py and the namespace packages, the more I read the more confused I get...
Basically I do not want to do :
mymodule.myfile.myclass
but rather:
import mymodule as mm
mm.MyClass1
or again:
from mymodule import *
a = MyClass1()
Still, I want one file by class.
You can add the import of MyClass1 and MyClass2 in mymodule/__init__.py.
Basically you will have the following files:
mymodule/
__init__.py
myclass1.py
myclass2.py
tests/
test_myclass1.py
test_myclass2.py
where:
mymodule/__init__.py contains the following lines:
from mymodule.myclass1 import MyClass1
from mymodule.myclass2 import MyClass2
mymodule/myclass1.py contains MyClass1 definition
mymodule/myclass2.py contains MyClass2 definition
Then in tests/test_myclass1.py you can import MyClass1 thanks to:
from mymodule import MyClass1
a = MyClass1()
or
import mymodule as mm
a = mm.MyClass1()
You can do the same for MyClass2
Im new to python and have looked at various stack overflow posts. i feel like this should work but it doesnt. How do you import a class from another file in python?
This folder structure
src/example/ClassExample
src/test/ClassExampleTest
I have this class
class ClassExample:
def __init__(self):
pass
def helloWorld(self):
return "Hello World!"
I have this test class
import unittest
from example import ClassExample
class ClassExampleTest(unittest.TestCase):
def test_HelloWorld(self):
hello = ClassExample()
self.assertEqual("Hello World!", hello.helloWorld())
if __name__ == '__main__':
unittest.main()
When the unit test runs the object is None:
AttributeError: 'NoneType' object has no attribute 'helloWorld'
What's wrong with this? How do you import a class in python?
If you're using Python 3, then imports are absolute by default. This means that import example will look for an absolute package named example, somewhere in the module search path.
So instead, you probably want a relative import. This is useful when you want to import a module that is relative the module doing the importing. In this case:
from ..example.ClassExample import ClassExample
I'm assuming that your folders are Python packages, meaning that they contain __init__.py files. So your directory structure would look like this.
src
|-- __init__.py
|-- example
| |-- __init__.py
| |-- ClassExample.py
|-- test
| |-- __init__.py
| |-- ClassExampleTest.py
My Flask application.py was getting a bit large and I wanted to spread the content (classes/functions) across a couple of additional py files. I placed class definitions in an appClasses.py and that is imported fine by application.py using
from appClasses import *
And, I placed some function definitions into appFunction.py and import those into application.py using
from appFunction import *
The functions in appFunction.py make use of flask session variables. When the same functions are in application.py there is no issue with session variable references (and app behaves as expected) but as soon as I cut/paste into appFunction.py and import functions I get a name error exception when the first function using session vars is called:
NameError: name 'session' is not defined
Here's a sample function:
def load_hgw_dict():
print("LOAD HGW DICT: called")
if 'hgw_dict_loaded' in session:
print("LOAD HGW DICT: hgw dict is available")
hgw_dict=session['hgw_dict']
else:
print("LOAD HGW DICT: hgw dict not available...adding")
session['hgw_dict_loaded']=True
list_of_hgws="/home/stbweb/LIST_OF_HENBGW"
hgw_file = open(list_of_hgws, "r")
hgw_dict=dict()
for line in hgw_file:
hgw_common, hgw_ip, hgw_hostname = line.split()
hgw_dict[hgw_common]= { 'ip':hgw_ip, 'hostname':hgw_hostname }
hgw_file.close()
print("LOAD HGW DICT: hgw dict =", hgw_dict)
return hgw_dict
Session is created by flask itself when flask application.py is run.
Here's the project dir structure...some files removed for compactness
.
|-- appClasses.py
|-- appHeNBGW.py
|-- application.ini
|-- application.py
|-- application.pyc
|-- cert.pem
|-- flask_session
| -- 2029240f6d1128be89ddc32729463129
|-- __init.py__
|-- key.pem
|-- __pycache__
|<snip>
|-- README.md
|-- set_dev_env
|-- static |<snip>
|-- templates
| <snip>
-- wsgi.py
I'm having a problem with assigning static files containing resources.
My working directory structure is:
|- README.md
|- nlp
| |-- morpheme
| |-- |-- morpheme_builder.py
| |-- fsa_setup.py
| - tests
| |-- test_fsa.py
| - res
| |-- suffixes.xml
The code for fsa_setup.py is:
class FSASetup():
fsa = None
def get_suffixes():
list_suffix = list()
file = os.path.realpath("../res/suffixes.xml")
.....
if __name__ == "__main__":
FSASetup.get_suffixes()
The code for morpheme_builder.py is:
class MorphemeBuilder:
def get_all_words_from_fsa(self):
......
if __name__ == "__main__":
FSASetup.get_suffixes()
When it is called in fsa_setup.py, the file path's value is '\res\suffixes.xml' and that is correct, but when the other case realized, the file path value is '\nlp\res\suffixes.xml'.
I know how it works like this. So how can I give the path of the resource to the file.
The problem is that morpheme_builder.py is in the directory morphem. So when you say ../res/suffixes.xml it will go on directory back ... so it will go to nlp/res/suffixes.xml. What about if you use os.path.abspath("../res/suffixes.xml")?