import from parent directory python - pytest

I am trying to run a pytest test for filea.py using the following directory structure
test_filea.py
from filea import *
def test_one_p_one():
r = one_p_one()
assert r == 2
filea.py
def one_p_one():
return 1 + 1
When i have to following directory structure every thing works fine.
├── filea.py
├── test_filea.py
but when i move my tests into a sub directory like this
├── filea.py
└── tests
└── test_filea.py
i get the error:
test_filea.py:1: in <module>
from filea import *
E ModuleNotFoundError: No module named 'filea'
My editor seems to indicate the import in the file in the sub directory is ok.. (no read squiggly lines)
but when i run this using "pytest"
i get the error indicated above.

As per pytest documentation about test discovery, try like this:
add an empty __init__.py file in testsdirectory;
make sure that, when you run pytest ., the parent directory of filea.py and tests is the current working directory.

It depends where you run the tests from, and how you invoke pytest. Calling pytest tests is different than calling python -m pytest tests, the later adds the current working directory into the sys.path, which makes filea module importable.

Related

Running tests against source code or the package

I've written some Python that I'm distributing as a custom package. I have some tests that I run against the source code while I'm developing, but I also want users who install the package to be able to run the same tests against the distributed package.
My package follows this structure:
my_package
├── MyPackage
│ ├── __init__.py
│ └── my_module.py
├── setup.py
└── tests
└── test_my_package.py
The my_package.py is
def my_function():
print("here!")
return True
And test_my_package.py is:
import unittest
import sys
sys.path.insert(0, "../")
from MyPackage.my_module import my_function
class TestMyModule(unittest.TestCase):
def test_somehting(self):
self.assertTrue(my_function())
As I'm manipulating sys.path, I'm always running the tests against the development code. Is there a way to use stuptools so I can run the tests against development code but the users run against the installed package?
Thanks!
There is a misconception when you say "tests that I run against the source code while I'm developing".
You always should run your tests against the packaged code because you want to be sure that the packaged code, which your users will run, works.
You could use tox to run your tests which automatically creates a package from your source code and even runs the tests for different Python Versions, eg the currently supported Python 3.6, 3.7 and 3.8.
While it would be a very rare thing, your users could then run the tests also.

How to run protoc correctly with different file import?

My main file to generate has these import :
import "protos/google_annotations.proto";
import "protos/nakama_annotations.proto";
import "protos/nakama_api.proto";
The folder structure :
├── lib
├── protos
├── google_annotations.proto
├── nakama_annotations.proto
├── nakama_api.proto
├── apigrpc.proto <--- this is the file to generate.
The highlight syntax is ok.(Android studio)
The 2 cases that i got error are :
1.
Command run in protos directory
Run protoc apigrpc.proto --java_out=. --proto_path=.
Get this error
protos/google_annotations.proto: File not found.
protos/nakama_annotations.proto: File not found.
protos/nakama_api.proto: File not found.
Specify all import files
Command run in protos directory
Run
protoc apigrpc.proto --java_out=. --proto_path=google_annotations.proto --proto_path=nakama_annotations.proto --proto_path=nakama_api.proto
Get this error apigrpc.proto: File does not reside within any path specified using --proto_path
What did i do wrong?
I just found what's wrong. It's about import.
I have to remove the prefex protos because the import file is in the same level of directory.
So the import become this :
import "google_annotations.proto";
import "nakama_annotations.proto";
import "nakama_api.proto";
The reason that I put protos in front before because the Android Studio plugin doesn't show red highlight when I put like that. Now After remove that, it highlight red, but it works.

pytest coverage never runs function body

I am using vscode with pytest and pytest-cov in order to generate a coverage report for my tests. However, no matter what I do the report always indicates that no code was run, event though I know the test functions call the code in question.
My project structure, simplified for clarity, is
Root
├── src
| └──my_package
| ├──__init__.py
| └──my_module.py
├── tests
| └──my_package_tests
| ├──__init__.py
| └──my_module_test.py
└── pytest.ini
pytest.ini contains
[pytest]
addopts = --cov=my_package --cov-report=html:./reports/coverage_report
The tests import and call functions from my_package
When I run the tests, and look at the generated report, I can see that lines in my_package are being marked as having run when the module is imported, but no code in the function bodies are being marked as executed. The test are passing so the code is being executed.
I'm at a loss on this one. I've tried doing this via command line only, uninstalling pytest-cov and trying manually, but nothing has worked.

learning python packaging, the old ModuleNotFoundErrro

What am I doing wrong here???
My structure :-
├── tst
│   ├── setup.py
│   └── tst
│   ├── __init__.py
│   ├── mre.py
│   └── start.py
contents of start.py
from mre import mre
def proc1():
mre.more()
return ('ran proc1')
if __name__ == "__main__":
print('test')
print(proc1())
contents of mre.py
class mre(object):
def more():
print('this is some more')
contents of setup.py
from setuptools import setup
setup(name='tst',
version='0.1',
description='just a test',
author='Mr Test',
author_email='test#example.com',
entry_points={'console_scripts': ['tst=tst.start:proc1']},
license='MIT',
packages=['tst'],
zip_safe=False)
nothing in __init__.py
When I run this from the command line all is fine, runs as expected.
However when I package this up using PIP and run using tst I get:-
Traceback (most recent call last):
File "/home/simon/.local/bin/tst", line 5, in <module>
from tst.start import proc1
File "/home/simon/.local/lib/python3.8/site-packages/tst/start.py", line 1, in <module>
from mre import mre
ModuleNotFoundError: No module named 'mre'
I've read numerous posts and I just can't seem to figure this out, if I go into the installed code and change the line
from mre import mre
to
from tst.mre import mre
then it works, but then that doesn't work when running it from the dir for development purposes... I'm obviously missing something obvious :) is it a path issue or am I missing a command in the setup.py?
If someone could point me in the right direction?
edit: do I need to do something different while developing a module thats going to be packaged, perhaps call the code some different way?
cheers
From my point of view, the absolute import from tst.mre import mre is the right thing. You could eventually use from .mre import mre, but the absolute import is safer.
For development purposes:
Use pip's editable mode:
path/to/pythonX.Y -m pip install --editable .
Similar to setuptools develop mode which is slowly going towards deprecation path/to/pythonX.Y setup.py develop.
And run the console script, or the executable module:
tst
path/to/pythonX.Y -m tst.start
Without installation, it is often sill possible to run the executable module:
path/to/pythonX.Y -m tst.start.

How to import python modules from parent and sibling packages

This (or similar) question has been asked many times before, but none of the solutions offered work in my case.
My project structure is like this :
| project_2
main.py
__init__.py
systems.py
| config
__init__.py
options.py
| database
__init__.py
database.py
entity.py
| tests
__init__.py
test_systems.py
test_options.py
test_database.py
test_entity.py
Obviously I need to import all the modules in the test modules under the tests package. I tried relative imports with the dot syntax:
from ..systems import System
from ..config import options
from ..database.entity import Entity
Returns a ValueError: Attempt relative import in non-package. I have tried that with a package structure where everything (including systems) is in its own package. It fails with the same message.
What really bothers me is that this is supposed to work: PEP 328, but it does not. I really want to avoid having to append the packages to $PYTHONPATH or to use some insane method such as loading the modules with imp from the file path.
I read that part of the problem might be that systems.py is in the main package, but that does not explain why the rest of the relative imports do not work either.
P.S. I actually recreated the example from PEP 328 just to test it and it does not work.
You get that when a python file does a relative import, but that file not loaded as a module via import in another module (but e.g. from the commandline). Given this structure:
.
├── main.py
└── test
├── __init__.py
├── a.py
└── b.py
main.py:
from test.a import A
print A
a.py:
from .b import B
A = B
if __name__ == '__main__':
print A
b.py:
B = 'b'
Now try:
python main.py
result is
b
and with
python test/a.py
you get:
Traceback (most recent call last):
File "test/a.py", line 1, in <module>
from .b import B
ValueError: Attempted relative import in non-package
What does work is:
python -m test.a
If you simply add . to your python path, if you run the script from the project_2 folder relative paths such as config.options will work. This requires an update to PYTHONPATH on every machine, unfortunately.
Tested on Python 2.7.14