测试人社区

pytest中hook函数pytest_addoption与pytest_generate_tests问题

创建了3个不同的环境,test、dev、st,分别有不同的数据yml

数据如下:

test_data_add:
  add_case1:
  - 1
  - 1
  - 2
  add_case2:
  - 100
  - 200
  - 300
  add_case3:
  - -22
  - -30
  - -52
  add_case4:
  - 10
  - -5
  - 5
  add_case5:
  - 0.1
  - 0.2
  - 0.3
test_data_div:
  div_case1:
  - 1
  - 1
  - 1
  div_case2:
  - 100
  - 200
  - 0.5
  div_case3:
  - -22
  - -30
  - 0.73
  div_case4:
  - 10
  - -5
  - -2
  div_case5:
  - 0.1
  - 0.2
  - 0.5
  div_case6:
  - 100
  - 0
  - 123

现在使用数据:

def test_env(cmdoption):
    env, datas = cmdoption
    print(f"当前使用环境是:{env}")
    data = datas.get("test_data_add").values()
    ids = datas.get("test_data_add").keys()

问题:

  • 怎么参数化驱动test_add 和test_div ?
  • 是需要每个case都传入cmdoption这个fixture,然后再去查找这个test所需的数据?这样传入也只能生成一个case吧,如何自动根据数据生成多个case?
  • 备注:我想使用上面传入cmdoption这个fixture的方法对case根据参数进行自动生成,使用@pytest.mark.parametrize的方法已了解

hook函数如下

def pytest_addoption(parser):
    mygroup = parser.getgroup("hogwarts")
    mygroup.addoption("--env",
                      default="test",
                      dest='env',
                      help="set your run env")


@pytest.fixture(scope="session")
def cmdoption(request):
    myenv = request.config.getoption("--env", default="test")
    if myenv == "test":
        data_file = os.path.join(BASEPATH, "testdata/datas_test.yml")
    elif myenv == "dev":
        data_file = os.path.join(BASEPATH, "testdata/datas_dev.yml")
    elif myenv == "st":
        data_file = os.path.join(BASEPATH, "testdata/datas_st.yml")
    else:
        print("Error env. Using the default env.")
        data_file = os.path.join(BASEPATH, "testdata/datas_test.yml")

    with open(data_file, encoding='utf-8') as f:
        data = yaml.safe_load(f)

    return myenv, data


def pytest_generate_tests(metafunc: "Metafunc") -> None:
    if "param" in metafunc.fixturenames:
        metafunc.parametrize("param",
                             metafunc.module.data,
                             ids=metafunc.mudule.ids,
                             scope="function")

感谢分享

我的思路是cmdoption函数中不解析数据,只根据参数返回不同环境的数据路径,然后在测试类里面拿到返回的路径后解析出数据再进行参数化。缺点就是需要建立很多不同的yaml文件。如何在一个文件获取不同环境的数据正在研究。

如您所说,在测试类中去解析不同的yml文件,那也不能根据yml文件的数据生成不同的测试用例吧?

或者说用assume来进行多重断言模拟多个case?

    @pytest.mark.test
    def test_aadd(self, cmdoption):
        data_file = cmdoption
        with open(data_file) as f:
            datas = yaml.safe_load(f)
            case_dict = datas.get("test_data_add")
            print(case_dict)
            for case in case_dict.values():
                print(case[0], case[1], case[2])
                pytest.assume(round(self.calc.add(case[0], case[1]), 2) == case[2])