使用 pytest 进行测试:适用于 GitLab 的导入不适用于 VS Code(反之亦然)

Testing with pytest: import that works on GitLab doesn't work in VS Code (and vice versa)

TL;DR:如何设置我的 GitLab 测试管道,以便测试也在 VS Code 上本地 运行?

我是 GitLab 管道的新手,所以如果问题很业余,请原谅我。我有一个在线设置的 GitLab 存储库,我正在使用 VS Code 在本地进行开发。我已经创建了一个新的管道,我想确保我所有的单元测试(用 PyTest 编写)运行 在我提交的任何时候。

问题是,即使我在两个地方使用相同的 setup.py 文件(很明显),我也无法同时进行 VS Code 测试和 GitLab 管道测试。问题是,我正在为我的测试导入,如果我导入 like

...
from external_workforce import misc_tools
# I want to test functions in this misc_tools module
...

然后它可以在 GitLab 上运行,但不能在 VS Code 上运行,因为 VS Code 在我进行测试发现时会报错,即:ModuleNotFoundError: No module named 'external_workforce'。但是,这适用于 GitLab。但是如果我像这样导入(在我的 test_tools.py 文件中,请参见下面的位置):

...
from hr_datapool.external_workforce import misc_tools 
...

它在 VS Code 中有效,但现在 GitLab 对我说 ModuleNotFoundError: No module named 'hr_datapool'

我认为相关信息可能是以下,如果需要更多信息,请询问更多信息!

我的文件结构是:

.
|__ requirements.txt
    setup.py
    hr_datapool
    |__ external_workforce
        |__ __init__.py
            misc_tools.py
            tests
            |__ test_tools.py
        |__ other_module
            ...
        

在我的管道编辑器(.gitlab-ci.yml 文件)中我有:

image: python:3.9.7

variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

cache:
  paths:
    - .cache/pip
    - venv/

before_script:
  - python --version  # For debugging
  - pip install virtualenv
  - virtualenv venv
  - source venv/bin/activate
  - pip install -r requirements.txt

test:
  script:
    - pytest --pyargs hr_datapool #- python setup.py test

run:
  script:
    - python setup.py bdist_wheel
  artifacts:
    paths:
      - dist/*.whl

最后,我的 setup.py 是:

import re
from unittest import removeResult
from setuptools import setup, find_packages

with open('requirements.txt') as f:
    requirements = f.read().splitlines()
    for req in ['wheel', 'bar']:
        requirements.append(req)
    
setup(
   name='hr-datapool',
   version='0.1',
   ...
   packages=find_packages(), 
   install_requires=requirements,
)

基本上,问题是:如何设置我的 GitLab 测试管道,以便测试也在 VS Code 上本地 运行?谢谢!

更新:

添加来自 VS Code 的完整跟踪:

> conda run -n base --no-capture-output --live-stream python ~/.vscode/extensions/ms-python.python-2022.2.1924087327/pythonFiles/get_output_via_markers.py ~/.vscode/extensions/ms-python.python-2022.2.1924087327/pythonFiles/testing_tools/run_adapter.py discover pytest -- --rootdir "." -s --cache-clear hr_datapool
cwd: .
[ERROR 2022-2-23 9:2:4.500]: Error discovering pytest tests:
 [r [Error]: ============================= test session starts ==============================
platform darwin -- Python 3.9.7, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /Users/myuser/Documents/myfolder
plugins: anyio-2.2.0
collected 0 items / 1 error

==================================== ERRORS ====================================
_____ ERROR collecting hr_datapool/external_workforce/tests/test_tools.py ______
ImportError while importing test module '/Users/myuser/Documents/myfolder/hr_datapool/external_workforce/tests/test_tools.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
../../opt/anaconda3/lib/python3.9/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
hr_datapool/external_workforce/tests/test_tools.py:2: in <module>
    from external_workforce import misc_tools
E   ModuleNotFoundError: No module named 'external_workforce'
=========================== short test summary info ============================
ERROR hr_datapool/external_workforce/tests/test_tools.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
===================== no tests collected, 1 error in 0.08s =====================

Traceback (most recent call last):
  File "/Users/myuser/.vscode/extensions/ms-python.python-2022.2.1924087327/pythonFiles/get_output_via_markers.py", line 26, in <module>
    runpy.run_path(module, run_name="__main__")
  File "/Users/myuser/opt/anaconda3/lib/python3.9/runpy.py", line 268, in run_path
    return _run_module_code(code, init_globals, run_name,
  File "/Users/myuser/opt/anaconda3/lib/python3.9/runpy.py", line 97, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/Users/myuser/opt/anaconda3/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/Users/myuser/.vscode/extensions/ms-python.python-2022.2.1924087327/pythonFiles/testing_tools/run_adapter.py", line 22, in <module>
    main(tool, cmd, subargs, toolargs)
  File "/Users/myuser/.vscode/extensions/ms-python.python-2022.2.1924087327/pythonFiles/testing_tools/adapter/__main__.py", line 100, in main
    parents, result = run(toolargs, **subargs)
  File "/Users/myuser/.vscode/extensions/ms-python.python-2022.2.1924087327/pythonFiles/testing_tools/adapter/pytest/_discovery.py", line 44, in discover
    raise Exception("pytest discovery failed (exit code {})".format(ec))
Exception: pytest discovery failed (exit code 2)
ERROR conda.cli.main_run:execute(33): Subprocess for 'conda run ['python', '/Users/myuser/.vscode/extensions/ms-python.python-2022.2.1924087327/pythonFiles/get_output_via_markers.py', '/Users/A111086670/.vscode/extensions/ms-python.python-2022.2.1924087327/pythonFiles/testing_tools/run_adapter.py', 'discover', 'pytest', '--', '--rootdir', '/Users/myuser/Documents/myfolder', '-s', '--cache-clear', 'hr_datapool']' command failed.  (See above for error)

    at ChildProcess.<anonymous> (/Users/myuser/.vscode/extensions/ms-python.python-2022.2.1924087327/out/client/extension.js:32:39235)
    at Object.onceWrapper (events.js:422:26)
    at ChildProcess.emit (events.js:315:20)
    at maybeClose (internal/child_process.js:1048:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:288:5)]

PYTHONPATH 导致了问题。

As external_workforce 父文件夹路径 -> 使用 GitLab 时 PYTHONPATHhr_datapool 的路径。 虽然 hr_datapool 父文件夹路径在PYTHONPATH 当你使用VSCode.

你运行是在VSCode终端上测试的吗?您是否将此添加到 settings.json 文件中?

  "terminal.integrated.env.windows": {
    "PYTHONPATH": "${workspaceFolder};"
  },

然后就可以在VSCode的终端执行pytest了。但是你没有在 GitLab 中配置这个,而是添加 hr-datapool- pytest --pyargs hr_datapoolsetup( name='hr-datapool',),所以你会得到错误信息。