요청 라이브러리를 사용하는 Python 앱 단위 테스트
Kenneth Reitz의 요청 라이브러리를 사용하여 REST 작업을 수행하는 응용 프로그램을 작성 중이며 요청 이 모듈 수준 메서드를 통해 메서드를 제공하기 때문에 이러한 응용 프로그램을 단위 테스트하는 좋은 방법을 찾기 위해 고군분투하고 있습니다.
제가 원하는 것은 양측 간의 대화를 종합하는 능력입니다. 일련의 요청 주장 및 응답을 제공합니다.
특별히 요청을 사용하는 경우 httmock을 시도 하십시오 . 놀랍도록 간단하고 우아합니다.
from httmock import urlmatch, HTTMock
import requests
# define matcher:
@urlmatch(netloc=r'(.*\.)?google\.com$')
def google_mock(url, request):
return 'Feeling lucky, punk?'
# open context to patch
with HTTMock(google_mock):
# call requests
r = requests.get('http://google.com/')
print r.content # 'Feeling lucky, punk?'
좀 더 일반적인 것을 원한다면 (예를 들어, http를 호출하는 라이브러리를 모의하기 위해) httpretty로 가십시오 .
거의 우아함 :
import requests
import httpretty
@httpretty.activate
def test_one():
# define your patch:
httpretty.register_uri(httpretty.GET, "http://yipit.com/",
body="Find the best daily deals")
# use!
response = requests.get('http://yipit.com')
assert response.text == "Find the best daily deals"
HTTPretty는 훨씬 더 많은 기능을 제공합니다. 모의 상태 코드, 스트리밍 응답, 회전 응답, 동적 응답 (콜백 포함)도 제공합니다.
실제로 라이브러리에 최종 사용자 단위 테스트에 대한 빈 페이지가 있지만 사용자 편의성과 사용 용이성을 목표로하는 것은 조금 이상합니다. 그러나 Dropbox의 사용하기 쉬운 라이브러리는 당연히 responses
. 여기에 소개 포스트가 있습니다. 를 사용 httpretty
하지 않고 실패 이유를 밝히지 않고 유사한 API로 라이브러리를 작성 했다고 말합니다 .
import unittest
import requests
import responses
class TestCase(unittest.TestCase):
@responses.activate
def testExample(self):
responses.add(**{
'method' : responses.GET,
'url' : 'http://example.com/api/123',
'body' : '{"error": "reason"}',
'status' : 404,
'content_type' : 'application/json',
'adding_headers' : {'X-Foo': 'Bar'}
})
response = requests.get('http://example.com/api/123')
self.assertEqual({'error': 'reason'}, response.json())
self.assertEqual(404, response.status_code)
Mocker 와 같은 모의 라이브러리를 사용 하여 요청 라이브러리에 대한 호출을 가로 채서 지정된 결과를 반환 할 수 있습니다.
매우 간단한 예로서 요청 라이브러리를 사용하는 다음 클래스를 고려하십시오.
class MyReq(object):
def doSomething(self):
r = requests.get('https://api.github.com', auth=('user', 'pass'))
return r.headers['content-type']
Here's a unit test that intercepts the call to requests.get
and returns a specified result for testing:
import unittest
import requests
import myreq
from mocker import Mocker, MockerTestCase
class MyReqTests(MockerTestCase):
def testSomething(self):
# Create a mock result for the requests.get call
result = self.mocker.mock()
result.headers
self.mocker.result({'content-type': 'mytest/pass'})
# Use mocker to intercept the call to requests.get
myget = self.mocker.replace("requests.get")
myget('https://api.github.com', auth=('user', 'pass'))
self.mocker.result(result)
self.mocker.replay()
# Now execute my code
r = myreq.MyReq()
v = r.doSomething()
# and verify the results
self.assertEqual(v, 'mytest/pass')
self.mocker.verify()
if __name__ == '__main__':
unittest.main()
When I run this unit test I get the following result:
.
----------------------------------------------------------------------
Ran 1 test in 0.004s
OK
using mocker like in srgerg's answer:
def replacer(method, endpoint, json_string):
from mocker import Mocker, ANY, CONTAINS
mocker = Mocker()
result = mocker.mock()
result.json()
mocker.count(1, None)
mocker.result(json_string)
replacement = mocker.replace("requests." + method)
replacement(CONTAINS(endpoint), params=ANY)
self.mocker.result(result)
self.mocker.replay()
For the requests library, this would intercept the request by method and endpoint you're hitting and replace the .json() on the response with the json_string passed in.
Missing from these answers is requests-mock.
From their page:
>>> import requests >>> import requests_mock
As a context manager:
>>> with requests_mock.mock() as m: ... m.get('http://test.com', text='data') ... requests.get('http://test.com').text ... 'data'
Or as a decorator:
>>> @requests_mock.mock() ... def test_func(m): ... m.get('http://test.com', text='data') ... return requests.get('http://test.com').text ... >>> test_func() 'data'
참고URL : https://stackoverflow.com/questions/9559963/unit-testing-a-python-app-that-uses-the-requests-library
'development' 카테고리의 다른 글
R 스크립트의 경로 얻기 (0) | 2020.12.08 |
---|---|
NSString과 함께 printf를 사용하는 방법 (0) | 2020.12.08 |
Heroku에서 PostgreSQL의 내장 전체 텍스트 검색을 사용하지 않는 이유는 무엇입니까? (0) | 2020.12.08 |
Razor / JavaScript 및 후행 세미콜론 (0) | 2020.12.08 |
안드로이드 폰갭에서 버튼을 클릭하면 앱을 종료 하시겠습니까? (0) | 2020.12.08 |