Python: блокировать сетевые соединения в целях тестирования?



Я пытаюсь протестировать пакет, который предоставляет интерфейсы для нескольких веб-служб. Он имеет набор тестов, который должен тестировать большинство функций Без подключения к интернету. Однако есть некоторые затяжные тесты, которые могут попытаться подключиться к интернету / загрузить данные, и я хотел бы предотвратить их по двум причинам: Во-первых, чтобы убедиться, что мой набор тестов работает, если нет сетевого подключения; во-вторых, чтобы я не спамил веб-службы с избытком запросы.



Очевидное решение-отключить мою машину / выключить беспроводную связь, но когда я запускаю тесты на удаленной машине, это, очевидно, не работает.



Итак, мой вопрос: Могу ли я заблокировать доступ к сети / порту для одного процесса python? ("песочница" это, но просто блокирующие сетевые соединения)



(afaict, pysandbox этого не делает)



EDIT: я использую py.test, поэтому мне нужно решение, которое будет работать с py.test, в случае, если это повлияет на любые предлагаемые ответы.

464   2  

2 ответов:

Обезьяна заплатки socket должен сделать это:

import socket
def guard(*args, **kwargs):
    raise Exception("I told you not to use the Internet!")
socket.socket = guard

Убедитесь, что это выполняется перед любым другим импортом.

Update : теперь есть плагин pytest, который делает то же самое, что и этот ответ! Вы можете прочитать ответ, чтобы просто посмотреть, как все работает, но я настоятельно рекомендую использовать плагин вместо копирования-вставки моего ответа: -) смотрите здесь: https://github.com/miketheman/pytest-socket


Я нашел ответ Томаса Ороско очень полезным. Следуя за кефлавичем, вот как я интегрировался в свой набор модульных тестов. Это работает для меня с тысячами очень различные юнит-тесты (

Я разместил здесь. В том числе и ниже для удобства. Тестировался с Python 2.7.5, pytest= = 2.7.0. (Чтобы проверить это самостоятельно, запустите py.test --doctest-modules в директории со всеми 3 клонированными файлами.)

_socket_toggle.py

from __future__ import print_function
import socket
import sys

_module = sys.modules[__name__]

def disable_socket():
    """ disable socket.socket to disable the Internet. useful in testing.

    .. doctest::
        >>> enable_socket()
        [!] socket.socket is enabled.
        >>> disable_socket()
        [!] socket.socket is disabled. Welcome to the desert of the real.
        >>> socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        Traceback (most recent call last):
        ...
        RuntimeError: I told you not to use the Internet!
        >>> enable_socket()
        [!] socket.socket is enabled.
        >>> enable_socket()
        [!] socket.socket is enabled.
        >>> disable_socket()
        [!] socket.socket is disabled. Welcome to the desert of the real.
        >>> socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        Traceback (most recent call last):
        ...
        RuntimeError: I told you not to use the Internet!
        >>> enable_socket()
        [!] socket.socket is enabled.
    """
    setattr(_module, '_socket_disabled', True)

    def guarded(*args, **kwargs):
        if getattr(_module, '_socket_disabled', False):
            raise RuntimeError("I told you not to use the Internet!")
        else:
            # SocketType is a valid public alias of socket.socket,
            # we use it here to avoid namespace collisions
            return socket.SocketType(*args, **kwargs)

    socket.socket = guarded

    print(u'[!] socket.socket is disabled. Welcome to the desert of the real.')


def enable_socket():
    """ re-enable socket.socket to enable the Internet. useful in testing.
    """
    setattr(_module, '_socket_disabled', False)
    print(u'[!] socket.socket is enabled.')

Conftest.py

# Put this in the conftest.py at the top of your unit tests folder,
# so it's available to all unit tests
import pytest
import _socket_toggle


def pytest_runtest_setup():
    """ disable the interet. test-cases can explicitly re-enable """
    _socket_toggle.disable_socket()


@pytest.fixture(scope='function')
def enable_socket(request):
    """ re-enable socket.socket for duration of this test function """
    _socket_toggle.enable_socket()
    request.addfinalizer(_socket_toggle.disable_socket)

Test_example.py

# Example usage of the py.test fixture in tests
import socket
import pytest

try:
    from urllib2 import urlopen
except ImportError:
    import urllib3
    urlopen = urllib.request.urlopen


def test_socket_disabled_by_default():
    # default behavior: socket.socket is unusable
    with pytest.raises(RuntimeError):
        urlopen(u'https://www.python.org/')


def test_explicitly_enable_socket(enable_socket):
    # socket is enabled by pytest fixture from conftest. disabled in finalizer
    assert socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Comments

    Ничего не найдено.