[英]python pytest for testing the requests and response
I am a beginner to using pytest in python and trying to write test cases for the following method which get the user address when correct Id is passed else rises custom error BadId. 我是初学者在python中使用pytest并尝试为以下方法编写测试用例,当正确的Id传递时获取用户地址,否则上升自定义错误BadId。
def get_user_info(id: str, host='127.0.0.1', port=3000 ) -> str:
uri = 'http://{}:{}/users/{}'.format(host,port,id)
result = Requests.get(uri).json()
address = result.get('user',{}).get('address',None)
if address:
return address
else:
raise BadId
Can someone help me with this and also can you suggest me what are the best resources for learning pytest? 有人可以帮我解决这个问题,你也可以建议我学习pytest的最佳资源是什么? TIA
TIA
Your test regimen might look something like this. 您的测试方案可能看起来像这样。
First I suggest creating a fixture to be used in your various method tests. 首先,我建议创建一个用于各种方法测试的夹具。 The fixture sets up an instance of your class to be used in your tests rather than creating the instance in the test itself.
fixture将设置一个类的实例,以便在测试中使用,而不是在测试中创建实例。 Keeping tasks separated in this way helps to make your tests both more robust and easier to read.
以这种方式保持任务分离有助于使您的测试更健壮,更易于阅读。
from my_package import MyClass
import pytest
@pytest.fixture
def a_test_object():
return MyClass()
You can pass the test object to your series of method tests: 您可以将测试对象传递给一系列方法测试:
def test_something(a_test_object):
# do the test
However if your test object requires some resources during setup (such as a connection, a database, a file, etc etc), you can mock it instead to avoid setting up the resources for the test. 但是,如果您的测试对象在安装过程中需要一些资源(例如连接,数据库,文件等),则可以模拟它以避免为测试设置资源。 See this talk for some helpful info on how to do that.
有关如何执行此操作的一些有用信息,请参阅此演讲 。
By the way: if you need to test several different states of the user defined object being created in your fixture, you'll need to parametrize your fixture. 顺便说一句:如果您需要测试夹具中创建的用户定义对象的几种不同状态 ,则需要对夹具进行参数化。 This is a bit of a complicated topic, but the documentation explains fixture parametrization very clearly .
这是一个复杂的主题,但文档非常清楚地解释了夹具参数化 。
The other thing you need to do is make sure any .get
calls to Requests
are intercepted. 您需要做的另一件事是确保拦截任何对
Requests
.get
调用。 This is important because it allows your tests to be run without an internet connection, and ensures they do not fail as a result of a bad connection, which is not the thing you are trying to test. 这很重要,因为它允许您的测试在没有Internet连接的情况下运行,并确保它们不会因连接错误而失败,这不是您尝试测试的内容。
You can intercept Requests.get
by using the monkeypatch feature of pytest
. 您可以拦截
Requests.get
使用猴补丁功能的pytest
。 All that is required is to include monkeypatch
as an input parameter to the test regimen functions. 所需要的只是将
monkeypatch
作为测试方案函数的输入参数。
You can employ another fixture to accomplish this. 您可以使用另一个夹具来完成此任务。 It might look like this:
它可能看起来像这样:
import Requests
import pytest
@pytest.fixture
def patched_requests(monkeypatch):
# store a reference to the old get method
old_get = Requests.get
def mocked_get(uri, *args, **kwargs):
'''A method replacing Requests.get
Returns either a mocked response object (with json method)
or the default response object if the uri doesn't match
one of those that have been supplied.
'''
_, id = uri.split('/users/', 1)
try:
# attempt to get the correct mocked json method
json = dict(
with_address1 = lambda: {'user': {'address': 123}},
with_address2 = lambda: {'user': {'address': 456}},
no_address = lambda: {'user': {}},
no_user = lambda: {},
)[id]
except KeyError:
# fall back to default behavior
obj = old_get(uri, *args, **kwargs)
else:
# create a mocked requests object
mock = type('MockedReq', (), {})()
# assign mocked json to requests.json
mock.json = json
# assign obj to mock
obj = mock
return obj
# finally, patch Requests.get with patched version
monkeypatch.setattr(Requests, 'get', mocked_get)
This looks complicated until you understand what is happening: we have simply made some mocked json objects (represented by dictionaries) with pre-determined user ids and addresses. 在您了解正在发生的事情之前,这看起来很复杂:我们只是使用预先确定的用户ID和地址制作了一些模拟的json对象(由字典表示)。 The patched version of
Requests.get
simply returns an object- of type MockedReq
- with the corresponding mocked .json()
method when its id is requested. 修补版本的
Requests.get
只返回一个类型为MockedReq
的对象 - 在请求其id时使用相应的MockedReq
.json()
方法。
Note that Requests
will only be patched in tests that actually use the above fixture, eg: 请注意,
Requests
仅在实际使用上述夹具的测试中进行修补,例如:
def test_something(patched_requests):
# use patched Requests.get
Any test that does not use patched_requests
as an input parameter will not use the patched version. 任何不使用
patched_requests
作为输入参数的测试都不会使用修补版本。
Also note that you could monkeypatch Requests
within the test itself, but I suggest doing it separately. 另请注意,您可以在测试中对monkeypatch
Requests
进行monkeypatch,但我建议您单独进行。 If you are using other parts of the requests API, you may need to monkeypatch those as well. 如果您正在使用请求API的其他部分,您可能还需要对它们进行monkeypatch。 Keeping all of this stuff separate is often going to be easier to understand than including it within your test.
保持所有这些东西分开往往比在测试中包含它更容易理解。
Write your various method tests next. 接下来写下各种方法测试。 You'll need a different test for each aspect of your method.
您需要针对方法的每个方面进行不同的测试。 In other words, you will usually write a different test for the instance in which your method succeeds, and another one for testing when it fails.
换句话说,您通常会为方法成功的实例编写不同的测试,而另一个测试则在测试失败时进行测试。
First we test method success with a couple test cases. 首先,我们使用几个测试用例测试方法成功。
@pytest.mark.parametrize('id, result', [
('with_address1', 123),
('with_address2', 456),
])
def test_get_user_info_success(patched_requests, a_test_object, id, result):
address = a_test_object.get_user_info(id)
assert address == result
Next we can test for raising the BadId
exception using the with pytest.raises
feature. 接下来,我们可以使用
with pytest.raises
功能测试是否引发BadId
异常。 Note that since an exception is raised, there is not a result
input parameter for the test function. 请注意,由于引发了异常,
result
测试函数没有result
输入参数。
@pytest.mark.parametrize('id', [
'no_address',
'no_user',
])
def test_get_user_info_failure(patched_requests, a_test_object, id):
from my_package import BadId
with pytest.raises(BadId):
address = a_test_object.get_user_info(id)
As posted in my comment, here also are some additional resources to help you learn more about pytest: 正如我在评论中发布的,这里还有一些额外的资源可以帮助您了解有关pytest的更多信息:
Also be sure to check out Brian Okken's book and Bruno Oliveira's book . 另外一定要查看Brian Okken的书和Bruno Oliveira的书 。 They are both very helpful for learning pytest.
它们对学习pytest非常有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.