Disabling the Internet for pytest

Jul 31, 2018 07:43 · 310 words · 2 minutes read

Testing legacy applications is hard, especially when you have no idea what side effects functions may have. You can try to mock everything but it’s easy to miss something nested in a module somewhere. Next thing you know, your tests are calling mutating REST endpoints with hardcoded production endpoints and credentials, or maybe you’re accidentally modifying production data somewhere and won’t even notice until someone goes looking for some data that isn’t there anymore.

In any case, preventing pytest from accessing the internet is quite simple, because every network call in Python goes through a single library: socket. The simplest way to disable all network access is to just have the following before all other imports in your test file:

import socket

class block_network(socket.socket):
    def __init__(self, *args, **kwargs):
        raise Exception("Network call blocked")

socket.socket = block_network

That’s a little cumbersome to remember to add to all your test files though, so a better approach is to add it to the top of conftest.py in your root tests directory, this way it is automatically loaded before everything else.

Example test with internet access:

import requests

def test_internet():
    r = requests.get("https://google.com")

Result:

$ pytest -vv
================================================ test session starts =================================================
platform darwin -- Python 3.6.1, pytest-3.7.0, py-1.5.4, pluggy-0.7.1 -- /Users/roganartu/.virtualenvs/blog-Ktof1LT9/bin/python3.6m
cachedir: .pytest_cache
rootdir: /Users/roganartu/Code/blog/test, inifile:
collected 1 item

test_requests.py::test_internet FAILED

====================================================== FAILURES ======================================================
...
    def __init__(self, *args, **kwargs):
>       raise Exception("Network call blocked")
E       Exception: Network call blocked

conftest.py:5: Exception
============================================== 1 failed in 3.48 seconds ==============================================

If you have more complex needs, such as unblocking for certain addresses (eg: localhost), or conditionally enabling network access for specific tests, then you should take a look at pytest-socket. However, if you just want to broadly disable all network access, then adding an extra dependency to your project is probably overkill, and the above seven lines added to your conftest.py should do the trick nicely.