Repository root
Without an explicit argument, pytest starts from configured testpaths or the current directory. That may be correct in a single-package repository.
Exit code 5 does not mean a test assertion failed. It means pytest collected no tests. In CI, start with the runner's actual directory and collection rules instead of turning the exit code into success.
============================ no tests ran ============================
Error: Process completed with exit code 5.
Short version: run python -m pytest --collect-only against the intended test directory, confirm the pytest command runs from the intended package directory, then fix the path, naming convention, or selection filter that removed every test.
Without an explicit argument, pytest starts from configured testpaths or the current directory. That may be correct in a single-package repository.
A service under services/api usually needs an explicit test path or a run-step working-directory. Checkout does not choose the package for later commands.
jobs:
test-api:
runs-on: ubuntu-latest
defaults:
run:
working-directory: services/api
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.13"
cache: pip
cache-dependency-path: services/api/requirements.txt
- run: python -m pip install -r requirements.txt
- name: Show collected tests
run: python -m pytest --collect-only -q tests
- name: Run tests
run: python -m pytest -q tests
The working directory applies to each run step. The setup action still receives a repository-relative dependency path. The temporary collection step makes a zero-test boundary visible before the full test command.
python -m pytest --collect-only -q tests from the same directory and with the same configuration as CI.testpaths, norecursedirs, and custom python_files, python_classes, or python_functions settings.test_*.py or *_test.py modules, test-prefixed functions, and Test-prefixed classes without an __init__ method.-k, marker, node-id, or path filters temporarily and confirm they did not select an empty set.|| true. That can hide assertion failures, collection errors, and usage errors as well as the zero-test case.Boundary: successful collection proves pytest found test items. It does not prove those tests exercise the intended package, use the expected installed code, or will pass.
Run the free offline CI Rescue Action against one workflow and an optional sanitized log. If the report still leaves the hosted failure unresolved, request a focused diagnosis, reviewable patch, and verification report for one failing job path.
Run the free diagnostic → Request a $49 rescue →