27.15.3.2. packaging.tests.pypi_server — PyPI mock server

When you are testing code that works with Packaging, you might find these tools useful.

27.15.3.2.1. The mock server

class packaging.tests.pypi_server.PyPIServer

PyPIServer is a class that implements an HTTP server running in a separate thread. All it does is record the requests for further inspection. The recorded data is available under requests attribute. The default HTTP response can be overridden with the default_response_status, default_response_headers and default_response_data attributes.

By default, when accessing the server with urls beginning with /simple/, the server also record your requests, but will look for files under the /tests/pypiserver/simple/ path.

You can tell the sever to serve static files for other paths. This could be accomplished by using the static_uri_paths parameter, as below:

server = PyPIServer(static_uri_paths=["first_path", "second_path"])

You need to create the content that will be served under the /tests/pypiserver/default path. If you want to serve content from another place, you also can specify another filesystem path (which needs to be under tests/pypiserver/. This will replace the default behavior of the server, and it will not serve content from the default dir

server = PyPIServer(static_filesystem_paths=["path/to/your/dir"])

If you just need to add some paths to the existing ones, you can do as shown, keeping in mind that the server will always try to load paths in reverse order (e.g here, try “another/super/path” then the default one)

server = PyPIServer(test_static_path="another/super/path")
server = PyPIServer("another/super/path")
# or
server.static_filesystem_paths.append("another/super/path")

As a result of what, in your tests, while you need to use the PyPIServer, in order to isolates the test cases, the best practice is to place the common files in the default folder, and to create a directory for each specific test case:

server = PyPIServer(static_filesystem_paths = ["default", "test_pypi_server"],
                    static_uri_paths=["simple", "external"])

27.15.3.2.2. Base class and decorator for tests

class packaging.tests.pypi_server.PyPIServerTestCase

PyPIServerTestCase is a test case class with setUp and tearDown methods that take care of a single PyPIServer instance attached as a pypi attribute on the test class. Use it as one of the base classes in your test case:

class UploadTestCase(PyPIServerTestCase):

    def test_something(self):
        cmd = self.prepare_command()
        cmd.ensure_finalized()
        cmd.repository = self.pypi.full_address
        cmd.run()

        environ, request_data = self.pypi.requests[-1]
        self.assertEqual(request_data, EXPECTED_REQUEST_DATA)
@packaging.tests.pypi_server.use_pypi_server

You also can use a decorator for your tests, if you do not need the same server instance along all you test case. So, you can specify, for each test method, some initialisation parameters for the server.

For this, you need to add a server parameter to your method, like this:

class SampleTestCase(TestCase):

    @use_pypi_server()
    def test_something(self, server):
        ...

The decorator will instantiate the server for you, and run and stop it just before and after your method call. You also can pass the server initializer, just like this:

class SampleTestCase(TestCase):

    @use_pypi_server("test_case_name")
    def test_something(self, server):
        ...