如何在没有 AttributeError 的情况下在 GitLab CI 管道中使用变量?

How to use Variables in GitLab CI pipeline without AttributeError?

我正在使用一个变量来定义我的 .gitlab-ci.yml

中的 ROOT_DIR
variables:
  ROOT_DIR: "/builds/company/projects/projectname/"

在我调用 test.py 函数的作业中:

ut-job:
  stage: test
  script:
    - echo "Unit testing ..."
    - python3 tests/test_file.py "$ROOT_DIR"

在test_file.py中我调用命令行inout如下:

if __name__ == "__main__":
    if sys.platform == "Darwin" or sys.platform == "Windows":
        load_dotenv()
        ROOT_DIR = os.getenv("ROOT_DIR")
    else:
        ROOT_DIR=sys.argv[1]    
    print("PLatform: " + sys.platform)
    print("ROOT_DIR: " + ROOT_DIR)
    
    unittest.main()

管道输出中的打印语句正确打印了 ROOT_DIR,因此 sys.argv 正确获取了变量。

但是,管道失败

AttributeError: module '__main__' has no attribute '/builds/company/projects/projectname/'

意思是,test_file.py main 获取变量但不知何故试图将其也用作属性。

有人可以提示我做错了什么吗?谢谢

调用test_file.py时无需传递参数。我认为这是导致错误的原因。

ut-job:
  stage: test
  script:
    - echo "Unit testing ..."
    - python3 tests/test_file.py

这里的问题是,当您调用 unittest.main 时,它会检查 sys.argv 的内容以获取参数,在本例中为测试名称。它将尝试使用提供的参数通过在当前模块上使用 getattr 来获取 运行 的测试。在这种情况下,导致属性错误。

例如,假设您有一个这样的测试文件 (t.py):

import unittest

class Foo(unittest.TestCase):
    def test_foo(self):
        ...

class Bar(unittest.TestCase):
    def test_bar(self):
        ...

unittest.main()

观察向该文件添加参数时的不同结果:

没有参数 2 个测试 运行:

$ python3 ./t.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

使用参数Foo只有一个测试(Foo)运行s:

$ python3 ./t.py Foo
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

如果您提供一个不存在的测试参数(例如,Baz),您将收到参数传递的属性错误:

$ python3 ./t.py Baz
E
======================================================================
ERROR: Baz (unittest.loader._FailedTest)
----------------------------------------------------------------------
AttributeError: module '__main__' has no attribute 'Baz'

----------------------------------------------------------------------
Ran 1 test in 0.000s

要解决此问题,您可以 (1) 不为脚本传递任何参数或 (2) 在调用 unittest.main

之前修改 sys.argv
if __name__ == "__main__":
    if sys.platform == "Darwin" or sys.platform == "Windows":
        load_dotenv()
        ROOT_DIR = os.getenv("ROOT_DIR")
    else:
        ROOT_DIR=sys.argv[1]
        sys.argv.pop(1)   # remove rootdir from cli arguments 
    print("PLatform: " + sys.platform)
    print("ROOT_DIR: " + ROOT_DIR)
    
    unittest.main()