py.test: 如何从夹具生成测试
py.test: How to generate tests from fixtures
我正在编写一组工具来测试自定义 HTTP 服务器的行为:是否设置了适当的响应代码、header 字段等。我正在使用 pytest 编写测试。
目标是向多个资源发出请求,然后在多个测试中评估响应:每个测试应该测试 HTTP 响应的一个方面。但是,并非每个响应都经过每个测试和 vice-versa.
为了避免多次发送相同的 HTTP 请求并重复使用 HTTP 响应消息,我正在考虑使用 pytest 的固定装置,并且 运行 对不同的 HTTP 响应进行相同的测试我想使用 pytest 的生成测试能力。
导入pytest
导入请求
def pytest_generate_tests(metafunc):
funcarglist = metafunc.cls.params[metafunc.function.__name__]
argnames = sorted(funcarglist[0])
metafunc.parametrize(argnames, [[funcargs[name] for name in argnames]
for funcargs in funcarglist])
class TestHTTP(object):
@pytest.fixture(scope="class")
def get_root(self, request):
return requests.get("http://test.com")
@pytest.fixture(scope="class")
def get_missing(self, request):
return requests.get("http://test.com/not-there")
def test_status_code(self, response, code):
assert response.status_code == code
def test_header_value(self, response, field, value):
assert response.headers[field] == value
params = {
'test_status_code': [dict(response=get_root, code=200),
dict(response=get_missing, code=404), ],
'test_header_value': [dict(response=get_root, field="content-type", value="text/html"),
dict(response=get_missing, field="content-type", value="text/html"), ],
}
问题似乎出在定义参数中:dict(response=get_root, code=200)
和类似的定义没有实现,我想绑定到 fixture 和实际函数引用上。
当 运行ning 测试时,我得到这种错误:
________________________________________________ TestHTTP.test_header_value[content-type-response0-text/html] _________________________________________________
self = <ev-question.TestHTTP object at 0x7fec8ce33d30>, response = <function TestHTTP.get_root at 0x7fec8ce8aa60>, field = 'content-type', value = 'text/html'
def test_header_value(self, response, field, value):
> assert response.headers[field] == value
E AttributeError: 'function' object has no attribute 'headers'
test_server.py:32: AttributeError
我怎样才能说服 pytest 取夹具值而不是函数?
无需从夹具生成测试,只需参数化夹具并为其值编写常规测试 returns:
import pytest
import requests
should_work = [
{
"url": "http://test.com",
"code": 200,
"fields": {"content-type": "text/html"}
},
]
should_fail = [
{
"url": "http://test.com/not-there",
"code": 404,
"fields": {"content-type": "text/html"}
},
]
should_all = should_work + should_fail
def response(request):
retval = dict(request.param) # {"url": ..., "code": ... }
retval['response'] = requests.get(request.param['url'])
return retval # {"reponse": ..., "url": ..., "code": ... }
# One fixture for working requests
response_work = pytest.fixture(scope="module", params=should_work)(response)
# One fixture for failing requests
response_fail = pytest.fixture(scope="module", params=should_fail)(response)
# One fixture for all requests
response_all = pytest.fixture(scope="module", params=should_all)(response)
# This test only requests failing fixture data
def test_status_code(response_fail):
assert response_fail['response'].status_code == response_fail['code']
# This test all requests fixture data
@pytest.mark.parametrize("field", ["content-type"])
def test_header_content_type(response_all, field):
assert response_all['response'].headers[field] == response_all['fields'][field]
我正在编写一组工具来测试自定义 HTTP 服务器的行为:是否设置了适当的响应代码、header 字段等。我正在使用 pytest 编写测试。
目标是向多个资源发出请求,然后在多个测试中评估响应:每个测试应该测试 HTTP 响应的一个方面。但是,并非每个响应都经过每个测试和 vice-versa.
为了避免多次发送相同的 HTTP 请求并重复使用 HTTP 响应消息,我正在考虑使用 pytest 的固定装置,并且 运行 对不同的 HTTP 响应进行相同的测试我想使用 pytest 的生成测试能力。 导入pytest 导入请求
def pytest_generate_tests(metafunc):
funcarglist = metafunc.cls.params[metafunc.function.__name__]
argnames = sorted(funcarglist[0])
metafunc.parametrize(argnames, [[funcargs[name] for name in argnames]
for funcargs in funcarglist])
class TestHTTP(object):
@pytest.fixture(scope="class")
def get_root(self, request):
return requests.get("http://test.com")
@pytest.fixture(scope="class")
def get_missing(self, request):
return requests.get("http://test.com/not-there")
def test_status_code(self, response, code):
assert response.status_code == code
def test_header_value(self, response, field, value):
assert response.headers[field] == value
params = {
'test_status_code': [dict(response=get_root, code=200),
dict(response=get_missing, code=404), ],
'test_header_value': [dict(response=get_root, field="content-type", value="text/html"),
dict(response=get_missing, field="content-type", value="text/html"), ],
}
问题似乎出在定义参数中:dict(response=get_root, code=200)
和类似的定义没有实现,我想绑定到 fixture 和实际函数引用上。
当 运行ning 测试时,我得到这种错误:
________________________________________________ TestHTTP.test_header_value[content-type-response0-text/html] _________________________________________________
self = <ev-question.TestHTTP object at 0x7fec8ce33d30>, response = <function TestHTTP.get_root at 0x7fec8ce8aa60>, field = 'content-type', value = 'text/html'
def test_header_value(self, response, field, value):
> assert response.headers[field] == value
E AttributeError: 'function' object has no attribute 'headers'
test_server.py:32: AttributeError
我怎样才能说服 pytest 取夹具值而不是函数?
无需从夹具生成测试,只需参数化夹具并为其值编写常规测试 returns:
import pytest
import requests
should_work = [
{
"url": "http://test.com",
"code": 200,
"fields": {"content-type": "text/html"}
},
]
should_fail = [
{
"url": "http://test.com/not-there",
"code": 404,
"fields": {"content-type": "text/html"}
},
]
should_all = should_work + should_fail
def response(request):
retval = dict(request.param) # {"url": ..., "code": ... }
retval['response'] = requests.get(request.param['url'])
return retval # {"reponse": ..., "url": ..., "code": ... }
# One fixture for working requests
response_work = pytest.fixture(scope="module", params=should_work)(response)
# One fixture for failing requests
response_fail = pytest.fixture(scope="module", params=should_fail)(response)
# One fixture for all requests
response_all = pytest.fixture(scope="module", params=should_all)(response)
# This test only requests failing fixture data
def test_status_code(response_fail):
assert response_fail['response'].status_code == response_fail['code']
# This test all requests fixture data
@pytest.mark.parametrize("field", ["content-type"])
def test_header_content_type(response_all, field):
assert response_all['response'].headers[field] == response_all['fields'][field]