pytest: Как заставить исключения исключения при юнит-тестировании?

Я ожидаю, что в моем коде Python исключения могут быть вызваны после вызова метода requests.Session.request(), например:

  • requests.exceptions.ConnectTimeout
  • requests.exceptions.ReadTimeout литий> requests.exceptions.Timeout литий>

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

Мой вопрос, я использую py.test для модульного тестирования, и я намеренно хочу добавить исключения из определенных частей моего кода. Например, функция, которая вызывает requests.Session.request() вместо возврата действительного requests.Response, он вызывает requests.exception.

Что я хочу убедиться, что мой код успешно обрабатывает ожидаемые и неожиданные исключения, поступающие из других пакетов, которые включают в себя эти исключения из requests ,

Может быть ... Есть ли @decorator, который я мог бы добавить к вышеупомянутой функции для вызова исключений по запросу во время модульного тестирования?

Предложения по выполнению инъекций исключений для модульного тестирования? (правильная формулировка моего вопроса будет принята с благодарностью.)

Спасибо за ответы !!!

Вот весь синглтон-класс, который создает requests.Session и вызывает requests.Session.request():

class MyRequest(metaclass=Singleton):

    def __init__(self, retry_tries=3, retry_backoff=0.1, retry_codes=None):
        self.session = requests.session()

        if retry_codes is None:
            retry_codes = set(REQUEST_RETRY_HTTP_STATUS_CODES)

        self.session.mount(
            'http',
            HTTPAdapter(
                max_retries=Retry(
                    total=retry_tries,
                    backoff_factor=retry_backoff,
                    status_forcelist=retry_codes,
                ),
            ),
        )

    def request(self, request_method, request_url, **kwargs):
        try:
            return self.session.request(method=request_method, url=request_url, **kwargs)
        except Exception as ex:
            log.warning(
                "Session Request: Failed: {}".format(get_exception_message(ex)),
                extra={
                    'request_method': request_method,
                    'request_url': request_url
                }
            )
            raise
4 голоса | спросил jeff00seattle 24 SatEurope/Moscow2016-12-24T19:24:42+03:00Europe/Moscow12bEurope/MoscowSat, 24 Dec 2016 19:24:42 +0300 2016, 19:24:42

3 ответа


0

Вы можете использовать повышение py.test, проверьте его здесь: http://doc.pytest.org/en/latest/assert.html#assertions-about-expected-exceptions

Принимая во внимание ваш код, вы можете сделать что-то вроде следующего:

from requests.exceptions import ConnectTimeout, ReadTimeout, Timeout
from unittest.mock import patch
import pytest

class TestRequestService:
   @patch('path_to_module.MyRequest')
   def test_custom_request(self, my_request_mock):
      my_request_mock.request.side_effect = ConnectTimeout

      with pytest.raises(ConnectTimeout):
          my_request_mock.request(Mock(), Mock())

Кроме того, вы можете использовать pytest.parametrize ( http: //doc. pytest.org/en/latest/parametrize.html ), а также:

from requests.exceptions import ConnectTimeout, ReadTimeout, Timeout
from unittest.mock import patch
import pytest

class TestRequestService:
    @pytest.mark.parametrize("expected_exception", [ConnectTimeout, ReadTimeout, Timeout])
    @patch('path_to_module.MyRequest')
    def test_custom_request(self, my_request_mock, expected_exception):
        my_request_mock.request.side_effect = expected_exception
        with pytest.raises(expected_exception):
            my_request_mock.request(Mock(), Mock())

Здесь вы найдете еще несколько примеров параметризации: http: //layer0.authentise .com /pytest-и-parametrization.html

ответил Enrique Saez 13 MaramMon, 13 Mar 2017 00:27:00 +03002017-03-13T00:27:00+03:0012 2017, 00:27:00
0

В моем приложении я ловлю исключение requests.exceptions.ConnectionError и возвращая сообщение, которое находится в переменной expected ниже. Итак, тест выглядит так:

import pytest
import requests

expected = {'error': 'cant connect to given url'}

class MockConnectionError:
    def __init__(self, *args, **kwargs):
        raise requests.exceptions.ConnectionError

def test_project_method(monkeypatch):
    monkeypatch.setattr("requests.get", MockConnectionError)
    response = project_method('http://some.url.com/')
    assert response == expected
ответил Tarik 25 PM00000020000003431 2018, 14:35:34
0

Исправления, насмешки и внедрение зависимостей - это методы для внедрения поддельных объектов. Исправление иногда трудно сделать правильно, с другой стороны, внедрение зависимостей требует изменения кода, который вы хотите протестировать.

Это простой пример использования внедрения зависимостей. Сначала код, который мы хотим протестировать:

import requests
...  

def fetch_data(url, get=requests.get): 
    return get(url).json()

# this is how we use fetch_data in productive code:
answer = fetch_data("www.google.com?" + term)

И это тогда тест:

import pytest

def test_fetch():

    def get_with_timeout(url):
        raise ConnectTimeout("message")

    with pytest.raises(ConnectTimeout) as e:
         # and now we inject the fake get method:
         fetch_data("https://google.com", get=get_with_timeout)

    assert e.value == "message"

В приведенном выше примере техника насмешки будет выглядеть следующим образом:

def test_exception():

    class TimeoutSessionMock:

        def get(self, *args, **kwargs):
            raise ConnectTimeout("message")

    mr = MyRequest()
    mr.session = TimeoutSessionMock()

    with pytest.raises(ConnectTimeout) as e: 
         mr.request("get", "http://google.com")

    assert e.value == "message"
ответил rocksportrocker 25 PM00000020000000931 2018, 14:50:09

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132