networktest


Namenetworktest JSON
Version 1.1.0 PyPI version JSON
download
home_pagehttps://github.com/jwplayer/networktest
SummaryTools for testing applications that make network requests.
upload_time2024-03-06 05:31:07
maintainer
docs_urlNone
authorMatt Wisniewski
requires_python
licenseApache License 2.0
keywords network test functional unit integration api http request
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            Networktest
===========

A library to test and enforce testing rules for Python applications that make network requests.

Installation
============

.. code-block:: bash

    pip install networktest

Blocking network requests
=========================

networktest provides a context manager NetworkBlocker that can be used to prevent tests or an application from making network requests.

.. code-block:: python

    import urllib.request
    from networktest import NetworkBlocker

    with NetworkBlocker():
        # A NetworkBlockException will be raised
        urllib.request.urlopen('http://127.0.0.1').read()

In some types of tests you may want to allow certain types of requests but not others. When testing an API you may want to allow tests to access that API's database but not make requests to another API.

.. code-block:: python

    import urllib.request
    from networktest import NetworkBlocker
    from my_database import Database

    with NetworkBlocker(allowed_packages=NetworkBlocker.AllowablePackages.DATASTORE):
        # This is fine
        Database.query('SELECT 1')

        # A NetworkBlockException will be raised
        urllib.request.urlopen('http://127.0.0.1').read()

If you're in the process of migrating your tests to mock requests you may want to use NetworkBlocker's warning mode. This mode will allow requests but display a warning.

.. code-block:: python

    import urllib.request
    from networktest import NetworkBlocker

    with NetworkBlocker(mode=NetworkBlocker.Modes.WARNING):
        # This will be allowed but a warning will be displayed
        urllib.request.urlopen('http://127.0.0.1').read()

TestCase Support
----------------

Some TestCases are provided that will apply NetworkBlocker to all tests in that case with some default settings.

.. code-block:: python

    import urllib.request
    from my_database import Database
    from networktest import NetworkBlockedTest, NetworkLimitedTest

    class MyTest(NetworkBlockedTest):

        def test_blocker(self):
            # A NetworkBlockException will be raised
            urllib.request.urlopen('http://127.0.0.1').read()

    class MyOtherTest(NetworkLimitedTest):

        def test_blocker(self):
            # This is fine
            Database.query('SELECT 1')

            # A NetworkBlockException will be raised
            urllib.request.urlopen('http://127.0.0.1').read()

pytest Support
--------------

pytest markers networkblocked and networklimited are available to apply NetworkBlocker to tests. These may be applied to modules, classes, methods or any other way pytest markers are supported.

.. code-block:: python

    from pytest import mark

    @mark.networkblocked
    def test_blocked(self):
        # A NetworkBlockException will be raised
        urllib.request.urlopen('http://127.0.0.1').read()

    @mark.networklimited
    def test_limited(self):
        # This is fine
        Database.query('SELECT 1')

        # A NetworkBlockException will be raised
        urllib.request.urlopen('http://127.0.0.1').read()

NetworkBlocker may be applied to an entire directory by adding an autouse fixture to a conftest.py file in that directory.

.. code-block:: python

    @pytest.fixture(scope='module', autouse=True)
    def networkblocker():
        with NetworkBlocker():
            yield

Mocking API requests
====================

HttpApiMock is provided to help with mocking API requests in unit and functional tests.

.. code-block:: python

    import urllib.request
    from networktest.mock import HttpApiMock

    class MyApiMock(HttpApiMock):

        hostnames = [
           'my-api'
        ]

        endpoints = [
            HttpApiMockEndpoint(
                operation_id='example',
                match_pattern=b'^GET /example/(?P<example_id>.*?)/',
                response=lambda groups: (418, {
                    'id': groups['example_id'],
                })
            )
        ]

    def test_my_api():
        with MyApiMock() as mock_api:
            response = urllib.request.urlopen('http://my-api/')
            response.read()
            # Requests which do not have a matched endpoint return a 200 response code by default
            assert response.getcode() == 200

            try:
                # This request matches the 'example' endpoint defined in MyApiMock
                urllib.request.urlopen('http://my-api/example/1234/').read()
            except urllib.error.HTTPError as e:
                # The response is the one defined for the 'example' endpoint
                assert e.code == 418
                assert e.read() == b'{"id": "1234"}'

            # It's possible to change the default responses inside of a test
            # In most tests it would make sense to apply MyApiMock to all tests of a certain type
            #   and only explictly use MyApiMock when doing something like this.
            mock_api.example.response = lambda groups: (204, None)
            response = urllib.request.urlopen('http://my-api/')
            response.read()
            assert response.getcode() == 204

Integration tests
=================

HttpApiMock may also be used to create assertions for integration tests without preventing API requests from being made.

.. code-block:: python

    import urllib.request
    from networktest.mock import HttpApiMock

    class MyApiMock(HttpApiMock):

        hostnames = [
            'my-api'
        ]

        endpoints = [
            HttpApiMockEndpoint(
                operation_id='example',
                match_pattern=b'^GET /example/(?P<example_id>.*?)/',
                response=lambda groups: (204, None)
            )
        ]

    def test_my_api():
        with MyApiMock(mode=MyApiMock.Modes.WATCH) as mock_api:
            urllib.request.urlopen('http://my-api/example/1234/').read()
            mock_api.example.request_mock.assert_called_once()


Versioning
==========

This package strictly follows `semantic versioning <https://semver.org>`_.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/jwplayer/networktest",
    "name": "networktest",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "network,test,functional,unit,integration,api,http,request",
    "author": "Matt Wisniewski",
    "author_email": "mattw@jwplayer.com",
    "download_url": "https://files.pythonhosted.org/packages/bd/e0/6a7ce8b292d897d1797c600c0b5741a90eb846ffe9779b64fb53948bc6b8/networktest-1.1.0.tar.gz",
    "platform": null,
    "description": "Networktest\n===========\n\nA library to test and enforce testing rules for Python applications that make network requests.\n\nInstallation\n============\n\n.. code-block:: bash\n\n    pip install networktest\n\nBlocking network requests\n=========================\n\nnetworktest provides a context manager NetworkBlocker that can be used to prevent tests or an application from making network requests.\n\n.. code-block:: python\n\n    import urllib.request\n    from networktest import NetworkBlocker\n\n    with NetworkBlocker():\n        # A NetworkBlockException will be raised\n        urllib.request.urlopen('http://127.0.0.1').read()\n\nIn some types of tests you may want to allow certain types of requests but not others. When testing an API you may want to allow tests to access that API's database but not make requests to another API.\n\n.. code-block:: python\n\n    import urllib.request\n    from networktest import NetworkBlocker\n    from my_database import Database\n\n    with NetworkBlocker(allowed_packages=NetworkBlocker.AllowablePackages.DATASTORE):\n        # This is fine\n        Database.query('SELECT 1')\n\n        # A NetworkBlockException will be raised\n        urllib.request.urlopen('http://127.0.0.1').read()\n\nIf you're in the process of migrating your tests to mock requests you may want to use NetworkBlocker's warning mode. This mode will allow requests but display a warning.\n\n.. code-block:: python\n\n    import urllib.request\n    from networktest import NetworkBlocker\n\n    with NetworkBlocker(mode=NetworkBlocker.Modes.WARNING):\n        # This will be allowed but a warning will be displayed\n        urllib.request.urlopen('http://127.0.0.1').read()\n\nTestCase Support\n----------------\n\nSome TestCases are provided that will apply NetworkBlocker to all tests in that case with some default settings.\n\n.. code-block:: python\n\n    import urllib.request\n    from my_database import Database\n    from networktest import NetworkBlockedTest, NetworkLimitedTest\n\n    class MyTest(NetworkBlockedTest):\n\n        def test_blocker(self):\n            # A NetworkBlockException will be raised\n            urllib.request.urlopen('http://127.0.0.1').read()\n\n    class MyOtherTest(NetworkLimitedTest):\n\n        def test_blocker(self):\n            # This is fine\n            Database.query('SELECT 1')\n\n            # A NetworkBlockException will be raised\n            urllib.request.urlopen('http://127.0.0.1').read()\n\npytest Support\n--------------\n\npytest markers networkblocked and networklimited are available to apply NetworkBlocker to tests. These may be applied to modules, classes, methods or any other way pytest markers are supported.\n\n.. code-block:: python\n\n    from pytest import mark\n\n    @mark.networkblocked\n    def test_blocked(self):\n        # A NetworkBlockException will be raised\n        urllib.request.urlopen('http://127.0.0.1').read()\n\n    @mark.networklimited\n    def test_limited(self):\n        # This is fine\n        Database.query('SELECT 1')\n\n        # A NetworkBlockException will be raised\n        urllib.request.urlopen('http://127.0.0.1').read()\n\nNetworkBlocker may be applied to an entire directory by adding an autouse fixture to a conftest.py file in that directory.\n\n.. code-block:: python\n\n    @pytest.fixture(scope='module', autouse=True)\n    def networkblocker():\n        with NetworkBlocker():\n            yield\n\nMocking API requests\n====================\n\nHttpApiMock is provided to help with mocking API requests in unit and functional tests.\n\n.. code-block:: python\n\n    import urllib.request\n    from networktest.mock import HttpApiMock\n\n    class MyApiMock(HttpApiMock):\n\n        hostnames = [\n           'my-api'\n        ]\n\n        endpoints = [\n            HttpApiMockEndpoint(\n                operation_id='example',\n                match_pattern=b'^GET /example/(?P<example_id>.*?)/',\n                response=lambda groups: (418, {\n                    'id': groups['example_id'],\n                })\n            )\n        ]\n\n    def test_my_api():\n        with MyApiMock() as mock_api:\n            response = urllib.request.urlopen('http://my-api/')\n            response.read()\n            # Requests which do not have a matched endpoint return a 200 response code by default\n            assert response.getcode() == 200\n\n            try:\n                # This request matches the 'example' endpoint defined in MyApiMock\n                urllib.request.urlopen('http://my-api/example/1234/').read()\n            except urllib.error.HTTPError as e:\n                # The response is the one defined for the 'example' endpoint\n                assert e.code == 418\n                assert e.read() == b'{\"id\": \"1234\"}'\n\n            # It's possible to change the default responses inside of a test\n            # In most tests it would make sense to apply MyApiMock to all tests of a certain type\n            #   and only explictly use MyApiMock when doing something like this.\n            mock_api.example.response = lambda groups: (204, None)\n            response = urllib.request.urlopen('http://my-api/')\n            response.read()\n            assert response.getcode() == 204\n\nIntegration tests\n=================\n\nHttpApiMock may also be used to create assertions for integration tests without preventing API requests from being made.\n\n.. code-block:: python\n\n    import urllib.request\n    from networktest.mock import HttpApiMock\n\n    class MyApiMock(HttpApiMock):\n\n        hostnames = [\n            'my-api'\n        ]\n\n        endpoints = [\n            HttpApiMockEndpoint(\n                operation_id='example',\n                match_pattern=b'^GET /example/(?P<example_id>.*?)/',\n                response=lambda groups: (204, None)\n            )\n        ]\n\n    def test_my_api():\n        with MyApiMock(mode=MyApiMock.Modes.WATCH) as mock_api:\n            urllib.request.urlopen('http://my-api/example/1234/').read()\n            mock_api.example.request_mock.assert_called_once()\n\n\nVersioning\n==========\n\nThis package strictly follows `semantic versioning <https://semver.org>`_.\n",
    "bugtrack_url": null,
    "license": "Apache License 2.0",
    "summary": "Tools for testing applications that make network requests.",
    "version": "1.1.0",
    "project_urls": {
        "Homepage": "https://github.com/jwplayer/networktest"
    },
    "split_keywords": [
        "network",
        "test",
        "functional",
        "unit",
        "integration",
        "api",
        "http",
        "request"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "16a4445efb3414bbd26bd3a589b828e93d6b31d49799514b67e6ac473556732c",
                "md5": "d51bc9f7c33b952e5f9b5292e280fed4",
                "sha256": "a3dce15fc5fda0562235a11d2496f597c9532b8d25317863db205f043d501a5a"
            },
            "downloads": -1,
            "filename": "networktest-1.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d51bc9f7c33b952e5f9b5292e280fed4",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 15171,
            "upload_time": "2024-03-06T05:31:06",
            "upload_time_iso_8601": "2024-03-06T05:31:06.620870Z",
            "url": "https://files.pythonhosted.org/packages/16/a4/445efb3414bbd26bd3a589b828e93d6b31d49799514b67e6ac473556732c/networktest-1.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bde06a7ce8b292d897d1797c600c0b5741a90eb846ffe9779b64fb53948bc6b8",
                "md5": "e8ba69db61b75763f1a5d173f695e753",
                "sha256": "50478d9d8c62e972631aa9627e28994fe6f75289c927891017bb4a9dea0a41c8"
            },
            "downloads": -1,
            "filename": "networktest-1.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "e8ba69db61b75763f1a5d173f695e753",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 17781,
            "upload_time": "2024-03-06T05:31:07",
            "upload_time_iso_8601": "2024-03-06T05:31:07.797574Z",
            "url": "https://files.pythonhosted.org/packages/bd/e0/6a7ce8b292d897d1797c600c0b5741a90eb846ffe9779b64fb53948bc6b8/networktest-1.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-03-06 05:31:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jwplayer",
    "github_project": "networktest",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "tox": true,
    "lcname": "networktest"
}
        
Elapsed time: 0.22083s