2

I'm having trouble implementing a toy example that runs pytest within .gitlab-ci.yml

gitlab_ci is a repo containing a single file test_hello.py

gitlab_ci/
    test_hello.py

test_hello.py

# test_hello.py

import pytest

def hello():
    print("hello")

def hello_test():
    assert hello() == 'hello'


.gitlab-ci.yml

# .gitlab-ci.yml

pytest:
  image: python:3.6
  script:
    - apt-get update -q -y
    - pip install pytest
    - pytest # if this is removed, the job outputs 'Success'

CI/CD terminal output

$ pytest
=== test session starts ===
platform linux -- Python 3.6.9, pytest-5.2.0, py-1.8.0, pluggy-0.13.0
rootdir: /builds/kunov/gitlab_ci
collected 0 items

=== no tests ran in 0.02s ===
ERROR: Job failed: exit code 1

I'm not sure why the test did not run... pytest does not seem to recognize test_hello.py


Solution

Put the python file inside the newly creared tests folder:

gitlab_ci/
    .gitlab-ci.yml
    tests/
        test_hello.py

Modify gitlab-ci.yml in the following manner:

# .gitlab-ci.yml

pytest:
  image: python:3.6
  script:
  - apt-get update -q -y
  - pip install pytest
  - pwd
  - ls -l
  - export PYTHONPATH="$PYTHONPATH:."
  - python -c "import sys;print(sys.path)"
  - pytest


And test_hello.py would stay the same as before.

kunov
  • 23
  • 4

2 Answers2

2

Manipulation of the PYTHONPATH variable is considered by some to be a bad practice (see e.g., this answer on stackoverflow or this Level Up Coding post). While this is possible not a huge issue in the scope of a GitLab CI job, here is a solution based on Alberto Mardegan's comment at the mentioned blog post without the need to fiddle with PYTHONPATH (also somewhat cleaner):

pytest:
  stage: Test
  script:
  - pwd
  - ls -l
  - python -m pytest

Why does this work? From the pytest docs:

You can invoke testing through the Python interpreter from the command line:

python -m pytest [...] 

This is almost equivalent to invoking the command line script pytest [...] directly, except that calling via python will also add the current directory to sys.path.

ToJo
  • 1,019
  • 1
  • 11
  • 23
  • 1
    Excellent; that seems more precise than [my answer](https://stackoverflow.com/a/58195220/6309). Upvoted. – VonC Feb 08 '22 at 17:31
1

This blog post mentions a similar pipeline, but:

However, this did not work as pytest was unable to find the ‘bild’ module (ie. the source code) to test.
The problem encountered here is that the ‘bild’ module is not able to be found by the test_*.py files, as the top-level directory of the project was not being specified in the system path:

pytest:
  stage: Test
  script:
  - pwd
  - ls -l
  - export PYTHONPATH="$PYTHONPATH:."
  - python -c "import sys;print(sys.path)"
  - pytest

The OP kunov confirms in the comments:

It works now! I put the single file inside a newly created folder called 'test'

VonC
  • 1,129,465
  • 480
  • 4,036
  • 4,755