Модульное тестирование приложения на Python, использующего библиотеку запросов

Я пишу приложение, которое выполняет операции REST, используя Кеннета Рейтцабиблиотека запросов и я изо всех сил пытаюсь найти хороший способ для модульного тестирования этих приложений, потому что запросы предоставляют свои методы через методы уровня модуля.

Что я хочу, так это умение синтезировать разговор между двумя сторонами; предоставить серию утверждений и ответов на запросы.

 kgr05 мар. 2012 г., 00:57
Таким образом, вам нужно смоделировать REST-сервер?
 John Mee05 мар. 2012 г., 02:00
почему это делает unittest неподходящим? Проверьте, как библиотека выполняет свои собственные модульные тесты; может предложить идеи.
 Romløk28 нояб. 2012 г., 14:29
FWIW, библиотека запросов выполняет свои собственные тесты, используя живые URL (github.com, собственный домен авторов и т. Д.).

Ответы на вопрос(5)

насмешник перехватывать звонки в библиотеку запросов и возвращать указанные результаты.

В качестве очень простого примера рассмотрим этот класс, который использует библиотеку запросов:

class MyReq(object):
    def doSomething(self):
        r = requests.get('https://api.github.com', auth=('user', 'pass'))
        return r.headers['content-type']

Вот модульный тест, который перехватывает вызовrequests.get и возвращает указанный результат для тестирования:

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()

Когда я запускаю этот модульный тест, я получаю следующий результат:

.
----------------------------------------------------------------------
Ran 1 test in 0.004s

OK

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()

Для библиотеки запросов это будет перехватывать запрос по методу и конечной точке, к которой вы обращаетесь, и заменять .json () в ответе на переданную json_string.

запросы-макет.

Со своей страницы:

>>> import requests
>>> import requests_mock

Как менеджер контекста:

>>> with requests_mock.mock() as m:

...     m.get('http://test.com', text='data')
...     requests.get('http://test.com').text
...
'data'

Или как декоратор:

>>> @requests_mock.mock()
... def test_func(m):
...     m.get('http://test.com', text='data')
...     return requests.get('http://test.com').text
...
>>> test_func()
'data'
 Thomas Fauskanger18 дек. 2017 г., 18:37
Я сделал так, чтобы это работало с декораторами, но кажется (в моей системе), что это конфликтует с каким-то другим аргументом, поэтому мне пришлось передать аргумент kw в Mocker, как упоминалось вдокументы, Не уверен, что это связано с pytest, но ошибка, которая возникла упомянутые приборы. Спасибо, что вернулись к вопросу.
 Thomas Fauskanger08 дек. 2017 г., 01:59
Есть ли у вас какие-либо знания о том, как сделать эту работу сpytest? Я попробовал точный пример, который вы приводите. Ref .:stackoverflow.com/questions/47703748/...
 Unapiedra18 дек. 2017 г., 17:08
Если я правильно помню, я использовал декоратор. И я думаю, что это также работало с pytest.

попробуйтеhttmock, Это удивительно просто и элегантно:

from httmock import urlmatch, HTTMock
import requests

# define matcher:
@urlmatch(netloc=r'(.*\.)?google\.com

Если вы хотите что-то более общее (например, издеваться над любой библиотекой, выполняющей вызовы 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 гораздо более многофункциональный - он также предлагает код состояния насмешки, потоковые ответы, чередующиеся ответы, динамические ответы (с обратным вызовом).

) 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 гораздо более многофункциональный - он также предлагает код состояния насмешки, потоковые ответы, чередующиеся ответы, динамические ответы (с обратным вызовом).

 mccc17 сент. 2015 г., 10:53
Эта штука прямо из этого мира, спасибо!

что в библиотеке есть пустая страница о модульном тестировании конечного пользователя, в то же время ориентированная на удобство использования и простоту использования. Однако 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)
 Mohamed Ragab21 февр. 2018 г., 11:19
Обновлен URL дляresponses вступительное сообщение

Ваш ответ на вопрос