## TL;DR
The test suite imports dotenv but python-dotenv was never declared as a dependency: it is installed on developer machines and missing in the clean CI environment. Add python-dotenv to the test requirements, reinstall in the CI job, and verify the import resolves. Take care to declare python-dotenv, the real package, not the dotenv stub package on PyPI, which is a different thing.

## The query
```text
pytest ModuleNotFoundError: No module named 'dotenv' in CI  -  missing python-dotenv
```

## Use this when
- pytest fails in CI with ModuleNotFoundError: No module named 'dotenv'
- the code calls load_dotenv() or reads dotenv somewhere in tests or app code
- the same suite passes on every developer machine

## Not for
- a .env file is missing in CI (the package imports fine but values are empty; that is config, not dependencies)
- the installed package is the dotenv stub instead of python-dotenv (uninstall it, install python-dotenv)
- dotenv imports fine but load_dotenv finds no file (check the working directory and the file path)

## Steps

### 1. Confirm the package is missing in CI
Check both environments. Installed locally, absent in CI is the expected asymmetry.
```bash
pip show python-dotenv 2>/dev/null | head -2 || echo "not installed"
```
```yaml
- name: Check dotenv in CI
  run: pip show python-dotenv || echo "python-dotenv NOT installed"
```
Expected output: local shows python-dotenv installed and CI shows it missing.

### 2. Declare python-dotenv in the test requirements
Add it where the CI install step reads. Pin a version so the suite does not float.
```text
# requirements-test.txt
python-dotenv==1.0.1
```
Expected output: the dependency is declared in a file the CI job installs.

### 3. Reinstall and verify the import in CI
Reinstall from the requirements file and import the module directly. The import succeeding is the acceptance check.
```bash
pip install -r requirements-test.txt
python -c "import dotenv; print(dotenv.__version__)"
pytest tests/test_config.py -q
```
Expected output: the import works and the previously failing tests collect and pass.

## Tool compatibility
- pytest 7 - 8
- Python 3.9 - 3.13
- python-dotenv 1.x

## Variant phrasings
- No module named 'dotenv' in CI
- ModuleNotFoundError: No module named 'dotenv' pytest
- python-dotenv missing in GitHub Actions

## Why it happens
PyPI hosts two packages with confusingly similar names: python-dotenv, the real one, and dotenv, an unrelated stub. Developers usually have the right one installed from long ago, while CI installs strictly from declared requirements. If the requirements never named it, or named the wrong one, the import fails only in CI.

## Edge cases / pitfalls
- verify with pip show that the installed distribution is python-dotenv, not the dotenv stub
- load_dotenv() searches from the working directory upward; CI's working directory may differ from local, so pass an explicit path in tests
- committing a .env file to fix CI is a secrets leak; use CI environment variables and keep the file gitignored
- if only tests need dotenv, put it in the test requirements rather than the runtime requirements

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_fkR5hUt_AqjmSNwFzJaVOg
