1

For my Python package 'imfp', I am doing my building and testing via 'Github Actions' using 'poetry' and pytest in a virtual environment. I've got the Github Actions script working successfully until the very step, when I run the tests using pytest.

Weirdly, the 'pytest --version' command works just fine, printing 'pytest 7.2.2'. However, 'pytest tests' returns the error, 'pytest: command not found'.

Per suggestions found in other threads on Substack, I have also tried:

py.test tests
py.test: command not found

python -m pytest tests
No module named pytest

py -m pytest tests
No module named pytest

python3 -m pytest tests
No module named pytest

Here is my Github Actions script:

name: build-test

on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.11"]
        poetry-version: [latest]
        os: [windows-latest]
    defaults:
      run:
        shell: bash
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install and configure Poetry
        uses: snok/install-poetry@v1
      - name: Configure Poetry
        run: |
          poetry config virtualenvs.in-project true
      - name: Install project
        run: |
          poetry install --no-interaction
      - name: Activate venv windows
        run: |
          source .venv/scripts/activate
          pytest --version
        if: runner.os == 'Windows'
      - name: Activate venv other
        run: |
          source .venv/bin/activate
          pytest --version
        if: runner.os != 'Windows'
      - name: Run tests
        run: |
          python3 -m pytest tests/

Note that as far as I can tell, this question is not a duplicate. Most of the similar threads involve a failure of 'pytest --version', but that command is working in this case.

workflow logs: https://github.com/chriscarrollsmith/imfp/actions/workflows/actions.yml

  • Looks like you missed `source .venv/bin/activate` before running tests. – Azeem Mar 31 '23 at 15:01
  • 1
    BTW, you shouldn't push your `.venv` folder to your repo as it has your local references in there. See https://github.com/chriscarrollsmith/imfp/blob/main/.venv/pyvenv.cfg. Check this thread for more details on this: https://stackoverflow.com/questions/6590688/is-it-bad-to-have-my-virtualenv-directory-inside-my-git-repository. – Azeem Mar 31 '23 at 15:02
  • Thanks, but the activation is in there: - name: Activate venv windows run: | source .venv/scripts/activate And as far as I can tell, it's executing successfully. – Christopher Carroll Smith Mar 31 '23 at 15:08
  • 1
    It's not [here](https://github.com/chriscarrollsmith/imfp/actions/runs/4576209750/workflow#L44-L46) where you run your tests. Each `run` is a different shell. Previous `run` sections have `source` in there that's why `pytest --version` works there. – Azeem Mar 31 '23 at 15:09
  • 1
    Wow, that solved it. I didn't know it was initializing a new shell with every run. Really appreciate the insight. Thank you so much!! – Christopher Carroll Smith Mar 31 '23 at 15:22
  • Sure, no problem. :) I thought you knew and forgot to add it in the last step as the previous sections already had it. Good to hear that it resolved the issue. You now have a [successful run](https://github.com/chriscarrollsmith/imfp/actions/runs/4576542150/jobs/8080817885). – Azeem Mar 31 '23 at 15:25

2 Answers2

2

According to jobs.<job_id>.steps[*].run:

Each run keyword represents a new process and shell in the runner environment.

So, venv activated in a previous step does not remain activated in the next one.

You need to activate it again before running tests.

Azeem
  • 11,148
  • 4
  • 27
  • 40
2

Activating a virtual environment is not always necessary. One can also directly call the binaries in the virtual environment's binaries directory instead (Scripts on Windows and bin anywhere else). So for example: .venv/Scripts/python -m pytest.

Alternatively, since Poetry is used, one can also call poetry run python -m pytest (which is probably the best solution, stick to poetry run as long as you use Poetry).

sinoroc
  • 18,409
  • 2
  • 39
  • 70