如何在命令行中将环境变量传递给pytest以测试功能

时间:2019-02-27 08:10:26

标签: python pytest

我有一个脚本使用os.environ.get()从命令行获取变量,例如JENKINS_HOST =“ xx” JENKINS_AUTH =“ xx” JENKINS_TOKEN =“ xx” python script.py

在script.py中,它具有如下功能:

def init_auth():
    login_mode = True
    JENKINS_HOST = os.environ.get("JENKINS_HOST")
    JENKINS_AUTH = os.environ.get("JENKINS_AUTH")
    JENKINS_TOKEN = os.environ.get("JENKINS_TOKEN")

当我使用pytest测试函数init_auth()时,如何将cli环境转移到该函数?

2 个答案:

答案 0 :(得分:0)

我不确定我是否完全理解您的问题。基本上,您不是要从环境中检索值,而是要从CLI检索它们?

如果是这样,我做到这一点的一种方法是在与测试相同的目录中创建一个conftest.py文件,并使用pytest_addoptionpytest_generate_tests钩子。

conftest.py

def pytest_addoption(parser):
    """
    Add CLI options to `pytest` to pass those options to the test cases.
    These options are used in `pytest_generate_tests`.
    """
    parser.addoption('--jenkins-host')
    parser.addoption('--jenkins-auth')
    parser.addoption('--jenkins-token')

def pytest_generate_tests(metafunc):
    metafunc.parametrize(
        'jenkins_host, jenkins_auth, jenkins_token',
        [(metafunc.config.getoption('jenkins_host'),
          metafunc.config.getoption('jenkins_auth'),
          metafunc.config.getoption(jenkins_token'))]

TestFile.py

class TestThis:
    def test_my_thing(jenkins_host, jenkins_auth, jenkins_token):
        # Do tests here

CLI

pytest TestFile.py --jenkins-host "http://my-jenkinshost.com" --jenkins-auth whatever --jenkins-token THE_TOKEN

测试用例中的参数已参数化(等效于在@pytest.mark.parametrize(...)中添加注释pytest_generate_tests

这很好用,pytest完全支持。这是一个基本示例,您可以做更多的事情。有关这些钩子和其他钩子如何工作的更多信息,请参见here

答案 1 :(得分:0)

假设您要测试这样的功能:

def foo():
    something = os.environ.get("SOMETHING")
    if something=="BAD":
       raise Exception("BAM")

它在这样的小应用程序中使用:

def main():
   try:
      foo()
      print("OK")
   except:
      print("SAD")

我可以在命令行上指定最终到达foo的环境值

$ SOMETHING=BAD ./my_app
SAD
$ SOMETHING=ELSE ./my_app
OK

现在,我想测试foo的行为,但是我需要注意不要更改我的环境设置,因此即使测试变坏,也需要设置和恢复它们。 看起来像这样:

def test_foo_ok():
  orig = os.environ.get("SOMETHING")
  os.environ["SOMETHING"]="ELSE"
  try:
     foo()
  finally:
     if orig is None:
        del os.environ["SOMETHING"]
     else:
        os.environ["SOMETHING"]=orig

def test_foo_bad():
  orig = os.environ.get("SOMETHING")
  os.environ["SOMETHING"]="BAD"
  try:
    with pytest.raises(Exception) as excinfo:   
        foo()   
    assert str(excinfo.value) == "BAM" 
  finally:
     if orig is None:
        del os.environ["SOMETHING"]
     else:
        os.environ["SOMETHING"]=orig

如果需要,可以将这些样板包装到装饰器中。我称其为@testwithenv之类的东西,那么测试看起来会更干净。

@testwithenv({"SOMETHING","ELSE"})
def test_foo_ok():
  foo()

@testwithenv({"SOMETHING","BAD"})
def test_foo_bad():
  with pytest.raises(Exception) as excinfo:   
    foo()   
  assert str(excinfo.value) == "BAM"