2013-09-03 7 views
11

मैं ऐसे पैकेज का परीक्षण करने की कोशिश कर रहा हूं जो कुछ वेब सेवाओं में इंटरफेस प्रदान करता हो। इसमें एक टेस्ट सूट है जो इंटरनेट से कनेक्ट के बिना अधिकांश कार्यों का परीक्षण करना चाहिए। हालांकि, कुछ सीमित परीक्षण हैं जो इंटरनेट/डाउनलोड डेटा से कनेक्ट करने का प्रयास कर सकते हैं, और मैं उन्हें दो कारणों से ऐसा करने से रोकना चाहता हूं: सबसे पहले, यह सुनिश्चित करने के लिए कि मेरा परीक्षण सूट काम करता है यदि कोई नेटवर्क कनेक्शन उपलब्ध नहीं है; दूसरा, ताकि मैं अतिरिक्त प्रश्नों के साथ वेब सेवाओं को स्पैम नहीं कर रहा हूं।पायथन: परीक्षण उद्देश्यों के लिए ब्लॉक नेटवर्क कनेक्शन?

एक स्पष्ट समाधान है कि मेरी मशीन को अनप्लग करें/वायरलेस बंद करें, लेकिन जब मैं एक दूरस्थ मशीन पर परीक्षण चला रहा हूं जो स्पष्ट रूप से काम नहीं करता है।

तो, मेरा प्रश्न: क्या मैं एक पायथन प्रक्रिया के लिए नेटवर्क/पोर्ट एक्सेस को अवरुद्ध कर सकता हूं? ("सैंडबॉक्स" यह है, लेकिन नेटवर्क कनेक्शन सिर्फ अवरुद्ध)

(AFAICT, pysandbox ऐसा नहीं करती है)

संपादित करें: मैं उपयोग कर रहा हूँ py.test तो मैं एक समाधान है कि py.test के साथ काम करेंगे की जरूरत मामले में, जो किसी भी प्रस्तावित उत्तरों को प्रभावित करता है।

उत्तर

10

बंदर पैचिंग socket यह करना चाहिए:

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

यकीन है कि यह किसी भी अन्य आयात करने से पहले चलाता है सुनिश्चित करें।

+0

यह बहुत अच्छा है! किसी और चीज से पहले इसे चलाने के लिए py.test कैसे प्राप्त करें इस पर कोई विचार? – keflavich

+0

मेरी आखिरी टिप्पणी का जवाब: इसे 'conftests.py' में चलाएं। – keflavich

+0

@keflavich जानना अच्छा - धन्यवाद! –

7

अद्यतन: अब एक सबसे पुरानी प्लगइन है जो इस उत्तर के समान ही काम करती है! तुम बस कैसे चीजें काम को देखने के लिए इस सवाल का जवाब पढ़ सकते हैं, लेकिन मैं दृढ़ता से प्लगइन का उपयोग कर के बजाय मेरा उत्तर नकल-पेस्ट :-) यहाँ देखें सलाह देते हैं : https://github.com/miketheman/pytest-socket


मैं थॉमस ओरोज्को के बहुत होने के लिए इस सवाल का जवाब मिल गया उपयोगी। केफ्लावविच के बाद, इस तरह मैंने अपने यूनिट टेस्ट सूट में एकीकृत किया। यह हजारों बहुत अलग यूनिट परीक्षण-मामलों (< 100 के साथ मेरे लिए काम करता है, हालांकि सॉकेट की आवश्यकता होती है) ... और सिद्धांतों में और बाहर।

मैंने here पोस्ट किया। सुविधा के लिए नीचे शामिल है। पायथन 2.7.5, पायटेस्ट == 2.7.0 के साथ परीक्षण किया गया। (खुद के लिए परीक्षण करने के लिए, क्लोन सभी 3 फाइलों के साथ निर्देशिका में py.test --doctest-modules चलाते हैं।)

_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) 
+0

क्यों 'कनेक्शन त्रुटि' अपवाद नहीं उठा रहा है? –

+0

@FemtoTrader मुझे लगता है क्योंकि यह _too_ सही है। एक वैध 'कनेक्शन त्रुटि' के लिए, अंतर्निहित त्रुटि को फेंकने वाली त्रुटि को भ्रमित नहीं करना चाहते हैं। प्रैक्टिस में मैं वास्तव में रनटाइम त्रुटि का उप-वर्ग का उपयोग करता हूं लेकिन मैं इस उदाहरण को सरल रखना चाहता था – hangtwenty

+2

Python3 के लिए काम करने वाले किसी भी अपडेट का कोई मौका? मैं इसे एक पायस्ट प्लगइन में बदलने में मदद करने में भी खुश हूं। –

संबंधित मुद्दे