I’ve set up my project CI to run a “build and test” job - it’s Python and uses pytest as the test runner and coverage for measuring coverage. The command I use, which works locally in my virtual env., is:
The project structure uses an src layout, where there is a subfolder named after the package name inside src:
project_root/
src/
package/
...
The error message in CI is always the same, the tests cannot find some of the package modules:
ModuleNotFoundError: No module named '<package>.<submodule>'
I’ve added a print statement to print out the package contents, and they are missing some modules, even though the local package build contains all files and the command works.
I know Python packaging is the worst aspect of Python, but this is a new low. I don’t see any reason why the same command, using the same tools, works locally but does not work in another Python environment.
If someone can shed some light, that would be great.
Hi. Below, it’s a private, non-proprietary repo, so no problem in sharing here. Note the error is ModuleNotFoundError in a test importing a src module missing from the pip install .
version: 2.1
orbs:
# The python orb contains a set of prepackaged CircleCI configuration you can use repeatedly in your configuration files
# Orb commands and jobs help you with common scripting around a language/tool
# so you dont have to copy and paste it everywhere.
# See the orb documentation here: https://circleci.com/developer/orbs/orb/circleci/python
python: circleci/python@1.2
codecov: codecov/codecov@1.2.5
workflows:
sample: # This is the name of the workflow, feel free to change it to better match your workflow.
# Inside the workflow, you define the jobs you want to run.
# For more details on extending your workflow, see the configuration docs: https://circleci.com/docs/2.0/configuration-reference/#workflows
jobs:
- build-and-test
jobs:
build-and-test: # This is the name of the job, feel free to change it to better match what you're trying to do!
# These next lines defines a Docker executors: https://circleci.com/docs/2.0/executor-types/
# You can specify an image from Dockerhub or use one of the convenience images from CircleCI's Developer Hub
# A list of available CircleCI Docker convenience images are available here: https://circleci.com/developer/images/image/cimg/python
# The executor is the environment in which the steps below will be executed - below will use a python 3.9 container
# Change the version below to your required version of python
docker:
- image: cimg/python:3.7
# Checkout the code as the first step. This is a dedicated CircleCI step.
# The python orb's install-packages step will install the dependencies from a Pipfile via Pipenv by default.
# Here we're making sure we use just use the system-wide pip. By default it uses the project root's requirements.txt.
# Then run your tests!
# CircleCI will report the results back to your VCS provider.
steps:
- checkout
- python/install-packages:
pkg-manager: pip
- python/install-packages:
pip-dependency-file: requirements_test.txt # if you have a different name for your requirements file, maybe one that combines your runtime and test requirements.
pkg-manager: pip
- python/install-packages:
args: pytest
pkg-manager: pip
pypi-cache: false
- run:
name: Lint source code (flake8)
# This assumes flake8 is installed via the install-package step above
command: python -m flake8 src/pyplist
- run:
name: Install package from source & run unit tests
# This assumes coverage and pytest is installed via the install-package step above
command: >
pip install . &&
python -m coverage
run -m pytest
--cache-clear
--code-highlight=yes
--color=yes
-ra
--rootdir .
--tb=native
--verbosity=3
tests
- run:
name: Generate coverage report and artifacts
command: |
python -m coverage report
python -m coverage html
- codecov/upload:
file: htmlcov/index.html
token: CODECOV_TOKEN
Config YML below. The command to run unit tests fails, because it would appear that the locally installed package (from pip install .) is missing modules. This cannot be the case because the same install works locally, and pip show -f pyplist shows all package modules present. Maybe the container is being cached [?].