Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

--liveserver-verbose and --liveserver-debug command-line arguments #1024

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Changelog
=========

vunreleased ()
--------------

Improvements
^^^^^^^^^^^^

* ``--liveserver-verbose`` command-line parameter, which allows to see
logs from live_server on the standard output, including tracebacks.
Useful for debugging.

v4.5.2 (2021-12-07)
-------------------

Expand Down
11 changes: 11 additions & 0 deletions docs/helpers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,17 @@ depends on the ``transactional_db`` fixture. If tests depend on data
created in data migrations, you should add the
``django_db_serialized_rollback`` fixture.

You can also use ``--liveserver-verbose`` command-line argument, to outputs
the liveserver logs to the standard output, including tracebacks. This is
useful for debugging live server behaviour and environment-related problems.
Take note, logs will be written to standard output, which is being supressed
by pytest by default, so you will need to use ``-s`` or ``--capture=no``
parameter too.

And if your live server still keeps acting weird, there is a switch called
``--liveserver-debug`` which drops into debugger in the console
whenever traceback occurs in a live server page.

.. note:: Combining database access fixtures.

When using multiple database fixtures together, only one of them is
Expand Down
9 changes: 8 additions & 1 deletion pytest_django/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,14 @@ def live_server(request):
"DJANGO_LIVE_TEST_SERVER_ADDRESS"
) or "localhost"

server = live_server_helper.LiveServer(addr)
live_server_class = live_server_helper.LiveServer
if request.config.getvalue("liveserver_verbose") is True:
live_server_class = live_server_helper.VerboseLiveServer

if request.config.getvalue("liveserver_debug") is True:
live_server_class = live_server_helper.VerboseDebuggingLiveServer

server = live_server_class(addr)
request.addfinalizer(server.stop)
return server

Expand Down
21 changes: 19 additions & 2 deletions pytest_django/live_server_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ class LiveServer:
The ``live_server`` fixture handles creation and stopping.
"""

def get_live_server_thread_class(self):
from django.test.testcases import LiveServerThread
return LiveServerThread

def __init__(self, addr: str) -> None:
from django.db import connections
from django.test.testcases import LiveServerThread
from django.test.utils import modify_settings

liveserver_kwargs = {} # type: Dict[str, Any]
Expand Down Expand Up @@ -42,7 +45,9 @@ def __init__(self, addr: str) -> None:
host = addr
else:
liveserver_kwargs["port"] = int(port)
self.thread = LiveServerThread(host, **liveserver_kwargs)

live_server_thread_class = self.get_live_server_thread_class()
self.thread = live_server_thread_class(host, **liveserver_kwargs)

self._live_server_modified_settings = modify_settings(
ALLOWED_HOSTS={"append": host}
Expand Down Expand Up @@ -79,3 +84,15 @@ def __add__(self, other) -> str:

def __repr__(self) -> str:
return "<LiveServer listening at %s>" % self.url


class VerboseLiveServer(LiveServer):
def get_live_server_thread_class(self):
from .verbose_live_server import VerboseLiveServerThread
return VerboseLiveServerThread


class VerboseDebuggingLiveServer(LiveServer):
def get_live_server_thread_class(self):
from .verbose_live_server import VerboseDebuggingLiveServerThread
return VerboseDebuggingLiveServerThread
17 changes: 17 additions & 0 deletions pytest_django/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,23 @@ def pytest_addoption(parser) -> None:
parser.addini(
SETTINGS_MODULE_ENV, "Django settings module to use by pytest-django."
)
group.addoption(
"--liveserver-verbose",
"--liveserver_verbose",
action="store_true",
dest="liveserver_verbose",
default=False,
help="Enable verbose logging for live_server fixture",
)
group.addoption(
"--liveserver-debug",
"--liveserver_debug",
action="store_true",
dest="liveserver_debug",
default=False,
help="Drops into debugger on tracebacks in live_server "
"(only if used with --liveserver-verbose)"
)

parser.addini(
"django_find_project",
Expand Down
37 changes: 37 additions & 0 deletions pytest_django/verbose_live_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import sys
import traceback

from django.core.servers.basehttp import ThreadedWSGIServer, WSGIRequestHandler
from django.test.testcases import LiveServerThread


class VerboseWSGIRequestHandler(WSGIRequestHandler):
debug_on_traceback = False

def handle_uncaught_exception(self, request, resolver, exc_info):
traceback.print_tb(exc_info[2], file=sys.stderr)
if self.debug_on_traceback:
import pytest
pytest.set_trace()

return super(VerboseWSGIRequestHandler, self).handle_uncaught_exception(
request, resolver, exc_info)


class VerboseDebuggingWSGIRequestHandler(VerboseWSGIRequestHandler):
debug_on_traceback = True


class VerboseLiveServerThread(LiveServerThread):
request_handler_class = VerboseWSGIRequestHandler

def _create_server(self):
return ThreadedWSGIServer(
(self.host, self.port),
self.request_handler_class,
allow_reuse_address=False
)


class VerboseDebuggingLiveServerThread(VerboseLiveServerThread):
request_handler_class = VerboseDebuggingWSGIRequestHandler