I'm trying to write a test for my python program, and I've created a /tests directory, where / means the projects root, not system root.
I have all my source files in /myProjectName.
Both directories have a __init__.py file, but project root does not, and both files are empty (do I need a __init__.py in the tests directory ?)
I've tried importing /myProjectName/main.py in /tests/test_main.py, but it doesn't work.
What is the right way to either structure the project directories or import main.py in test_main.py?
I would suggest moving your tests directory to be inside your project directory. Then you can use the answers here to import from the parent directory when you're in tests: Importing modules from parent folder
Otherwise, you can simply set your $PYTHONPATH to point to your project directory when you run tests.
I would like to suggest nose here as it automatically detects the tests and runs them for you
To run the tests, simply do a
$ nosetests
in your project directory
Why not try this line in testmain.py:
import os
os.chdir("/myProjectName/main.py ")
Then execute the script.
Hope it works!
Related
I have a project where I want to VS Code's discover tests and other testing features to make testing easier. I have a problem that imports in test files break when I try to discover tests.
I have a file structure like so:
project\
__init__.py
package1\
module1.py
__init__.py
tests\
test.py
__init__.py
In test.py I have a line:
import project.package1.module1 as module1
I run my project by calling python -m project in the root folder, and I am able to run tests successfully by calling python -m pytest project from the root folder.
When I run VS Code's "discover tests" feature or try to step through a file with the debugger, I receive an error 'ModuleNotFoundError: No module named project'.
Does anyone know how to solve this problem?
I had the same issue. The solution that worked for me was to introduce a .envfile that holds my PYTHONPATH entries, relative to my workspace folder.
PYTHONPATH="path1:path2:pathN"
Then I added a line to my workspace settings that specifies the location of my .env file.
// ...
"python.envFile": "${workspaceFolder}/.env",
// ...
I had the same issue where I was able to run pytest and python -m pytest successfully in the terminal within VSCode but the discovery was failing. My solution was to implement the failing import in the following way
import sys
sys.path.insert(0, '/full/path/to/package1/')
from package1.module1 import module1
Note that VSCode was opened with the project folder being the root.
Next solution works for Linux and Windows,
import sys
from pathlib import Path
sys.path.insert(0, str(Path('package1/').resolve()))
It's based on #Chufolon answer. My StackOverflow reputation doesn't allow me to just comment on his answer. I prefer his solution because in the .env there could be sensitive information (passwords, ...) that shouldn't be shared (omit it in .gitignore file) for security reasons; and also because __init__.py is shared by default through Git.
I defined a directory named common in the root directory of my project. Basically, there isn't a main file, but rather lots of scripts which I want to directly run.
What I want to do is something like that:
from ../../common/ import <python_file>
Is it possible without too much of a hustle?
Would I need to put __init__.py to make it work?
The use of .. for imports is really a bad practice. What you should do is that. Create a virtualenv using virtualenvwrapper and then use add2virtualenv common
OR
Add the path of the root directory of your project into your PYTHONPATH env variable
export PYTHONPATH=$PYTHONPATH:/path/of/my/project
An __init__.py file must be placed in every folder containing python code
There're a lot of threads on importing modules from sibling directories, and majority recommends to either simply add init.py to source tree, or modify sys.path from inside those init files.
Suppose I have following project structure:
project_root/
__init__.py
wrappers/
__init__.py
wrapper1.py
wrapper2.py
samples/
__init__.py
sample1.py
sample2.py
All init.py files contain code which inserts absolute path to project_root/ directory into the sys.path. I get "No module names x", no matter how I'm trying to import wrapperX modules into sampleX. And when I try to print sys.path from sampleX, it appears that it does not contain path to project_root.
So how do I use init.py correctly to set up project environment variables?
Do not run sampleX.py directly, execute as module instead:
# (in project root directory)
python -m samples.sample1
This way you do not need to fiddle with sys.path at all (which is generally discouraged). It also makes it much easier to use the samples/ package as a library later on.
Oh, and init.py is not run because it only gets run/imported (which is more or less the same thing) if you import the samples package, not if you run an individual file as script.
This is a broad question because no one seems to have found a solution to it as yet so I think asking to see a working example might prove more useful. So here goes:
Has anyone run a nosetests on a python project using imports of multiple files/packages?
What I mean is, do you have a directory listing such as:
project/
|
|____app/
|___main.py
|___2ndFile.py
|___3rdFile.py
|____tests/
|____main_tests.py
Where your main.py imports multiple files and you perform a nosetests from the project file of utilizing a test script in the main_tests.py file? If so please can you screen shot your import section both of all your main files and your main_tests.py file?
This seems to be a major issue in nosetests, with no apparent solution:
Nosetests Import Error
A test running with nosetests fails with ImportError, but works with python command
https://github.com/nose-devs/nose/issues/978
https://github.com/nose-devs/nose/issues/964
You can't have python modules starting with a digit, so 2ndFile.py, 3rdFile.py won't actually work (rename them).
You'll need an __init__.py inside the app directory, for it to be considered a package, so add that (it can be empty file).
You don't need an __init__.py in the tests directory!
The import statements in main_tests.py should look like from app.main import blah
The absolute path of the project directory needs to be in your sys.path. To achieve this, set an environment variable: export PYTHONPATH=/path/to/project
Now running nosetests should work.
I have the following directory structure:
application
tests
main.py
main.py
application/main.py contains some functions.
tests/main.py will contain my tests for these functions but I can't import the top level main.py. I get the following error:
ImportError: Import by filename is not supported.
I am attempting to import using the following syntax:
import main
What am I doing wrong?
If you'd like your script to be more portable, consider finding the parent directory automatically:
import os, sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# import ../db.py
import db
You must add the application dir to your path:
import sys
sys.path.append("/path/to/dir")
from app import object
Or from shell:
setenv PATH $PATH:"path/to/dir"
In case you use windows:
Adding variable to path in windows.
Or from the command line:
set PATH=%PATH%;C:\path\to\dir
Please mind the diff between PYTHONPATH, PATH, sys.path.
Late to the party - most other answers here are not correct unfortunately - apart LennartRegebro's (and BrenBarn's) which is incomplete. For the benefit of future readers - the OP should, first of all, add the __init__.py files as in
root
application
__init__.py
main.py
tests
__init__.py
main.py
then:
$ cd root
$ python -m application.tests.main
or
$ cd application
$ python -m tests.main
Running a script directly from inside its package is an antipattern - the correct way is running with the -m switch from the parent directory of the root package - this way all packages are detected and relative/absolute imports work as expected.
First of all you need to make your directories into packages, by adding __init__.py files:
application
tests
__init__.py
main.py
__init__.py
main.py
Then you should make sure that the directory above application is on sys.path. There are many ways to do that, like making the application infto a package and installing it, or just executing things in the right folder etc.
Then your imports will work.
You cannot import things from parent/sibling directories as such. You can only import things from directories on the system path, or the current directory, or subdirectories within a package. Since you have no __init__.py files, your files do not form a package, and you can only import them by placing them on the system path.
To import a file in a different subdirectory of the parent directory, try something like this:
sys.path.append(os.path.abspath('../other_sub_dir'))
import filename_without_py_extension
Edit: Missing closing bracket.
in python . exists for same directory, .. for parent directory
to import a file from parent directory you can use ..
from .. import filename (without .py extension)