如何使用 pytest 函数对每个站点使用不同的测试数据集来测试不同的站点,例如 staging/production
how to use a pytest function to test different site using a different set of test data for each site such as staging/production
我有一组 pytest 函数来测试 API,测试数据在 json 文件中,由 pytest.mark.parametrize 加载。因为staging、production和pre_production的数据不同但相似,所以我想把测试数据保存在不同的文件夹中并使用相同的文件名,以保持python函数的干净。站点信息是 pytest 命令行的一个新选项。不行,pytest.mark.parametrize 无法获取正确的文件夹来收集测试数据。
这是在conftest.py
@pytest.fixture(autouse=True)
def setup(request, site):
request.cls.site = site
yield
def pytest_addoption(parser):
parser.addoption("--site", action="store", default="staging")
@pytest.fixture(scope="session", autouse=True)
def site(request):
return request.config.getoption("--site")
这在测试用例文件中:
@pytest.mark.usefixtures("setup")
class TestAAA:
@pytest.fixture(autouse=True)
def class_setup(self):
self.endpoint = read_data_from_file("endpoint.json")["AAA"][self.site]
if self.site == "production":
self.test_data_folder = "SourcesV2/production/"
else: // staging
self.test_data_folder = "SourcesV2/"
testdata.set_data_folder(self.test_data_folder)
@pytest.mark.parametrize("test_data", testdata.read_data_from_json_file(r"get_source_information.json"))
def test_get_source_information(self, test_data):
request_url = self.endpoint + f"/AAA/sources/{test_data['sourceID']}"
response = requests.get(request_url)
print(response)
我可以使用 pytest.skip 跳过不适用于当前站点的测试数据。
if test_data["site"] != self.site:
pytest.skip("this test case is for " + test_data["site"] + ", skiping...")
但是staging/production/pre-production需要把所有的测试数据放在一个文件里,而且报告中会有很多跳过的测试,这不是我喜欢的。
你有什么办法解决这个问题吗?如何根据站点将不同的文件名传递给参数化?
或者,至少,如何让跳过的测试不在报告中写入日志?
谢谢
parametrize
装饰器在加载时计算,而不是在 运行 时计算,因此您不能直接为此使用它。您需要在 运行 时间进行参数化。这可以使用 pytest_generate_tests
钩子来完成:
def pytest_generate_tests(metafunc):
if "test_data" in metafunc.fixturenames:
site = metafunc.config.getoption("--site")
if site == "production":
test_data_folder = "SourcesV2/production"
else:
test_data_folder = "SourcesV2"
# this is just for illustration, your test data may be loaded differently
with open(os.path.join(test_data_folder, "test_data.json")) as f:
test_data = json.load(f)
metafunc.parametrize("test_data", test_data)
class TestAAA:
def test_get_source_information(self, test_data):
...
如果加载测试数据是膨胀的,您也可以缓存它以避免每次测试都读取它。
我有一组 pytest 函数来测试 API,测试数据在 json 文件中,由 pytest.mark.parametrize 加载。因为staging、production和pre_production的数据不同但相似,所以我想把测试数据保存在不同的文件夹中并使用相同的文件名,以保持python函数的干净。站点信息是 pytest 命令行的一个新选项。不行,pytest.mark.parametrize 无法获取正确的文件夹来收集测试数据。
这是在conftest.py
@pytest.fixture(autouse=True)
def setup(request, site):
request.cls.site = site
yield
def pytest_addoption(parser):
parser.addoption("--site", action="store", default="staging")
@pytest.fixture(scope="session", autouse=True)
def site(request):
return request.config.getoption("--site")
这在测试用例文件中:
@pytest.mark.usefixtures("setup")
class TestAAA:
@pytest.fixture(autouse=True)
def class_setup(self):
self.endpoint = read_data_from_file("endpoint.json")["AAA"][self.site]
if self.site == "production":
self.test_data_folder = "SourcesV2/production/"
else: // staging
self.test_data_folder = "SourcesV2/"
testdata.set_data_folder(self.test_data_folder)
@pytest.mark.parametrize("test_data", testdata.read_data_from_json_file(r"get_source_information.json"))
def test_get_source_information(self, test_data):
request_url = self.endpoint + f"/AAA/sources/{test_data['sourceID']}"
response = requests.get(request_url)
print(response)
我可以使用 pytest.skip 跳过不适用于当前站点的测试数据。
if test_data["site"] != self.site:
pytest.skip("this test case is for " + test_data["site"] + ", skiping...")
但是staging/production/pre-production需要把所有的测试数据放在一个文件里,而且报告中会有很多跳过的测试,这不是我喜欢的。
你有什么办法解决这个问题吗?如何根据站点将不同的文件名传递给参数化? 或者,至少,如何让跳过的测试不在报告中写入日志? 谢谢
parametrize
装饰器在加载时计算,而不是在 运行 时计算,因此您不能直接为此使用它。您需要在 运行 时间进行参数化。这可以使用 pytest_generate_tests
钩子来完成:
def pytest_generate_tests(metafunc):
if "test_data" in metafunc.fixturenames:
site = metafunc.config.getoption("--site")
if site == "production":
test_data_folder = "SourcesV2/production"
else:
test_data_folder = "SourcesV2"
# this is just for illustration, your test data may be loaded differently
with open(os.path.join(test_data_folder, "test_data.json")) as f:
test_data = json.load(f)
metafunc.parametrize("test_data", test_data)
class TestAAA:
def test_get_source_information(self, test_data):
...
如果加载测试数据是膨胀的,您也可以缓存它以避免每次测试都读取它。