diff --git a/bookwyrm/tests/query_logger.py b/bookwyrm/tests/query_logger.py new file mode 100644 index 0000000000..6474ff41b2 --- /dev/null +++ b/bookwyrm/tests/query_logger.py @@ -0,0 +1,39 @@ +""" Log query runtimes for testing """ +import time + + +class QueryLogger: + """Returns the sql and duration for any query run + Taken wholesale from: + https://docs.djangoproject.com/en/dev/topics/db/instrumentation/ + """ + + def __init__(self): + self.queries = [] + + # pylint: disable=too-many-arguments + def __call__(self, execute, sql, params, many, context): + current_query = {"sql": sql, "params": params, "many": many} + start = time.monotonic() + try: + result = execute(sql, params, many, context) + except Exception as err: # pylint: disable=broad-except + current_query["status"] = "error" + current_query["exception"] = err + raise + else: + current_query["status"] = "ok" + return result + finally: + duration = time.monotonic() - start + current_query["duration"] = duration + self.queries.append(current_query) + + +def raise_long_query_runtime(queries, threshold=0.0006): + """Raises an exception if any query took longer than the threshold""" + for query in queries: + if query["duration"] > threshold: + raise Exception( # pylint: disable=broad-exception-raised + "This looks like a slow query:", query["duration"], query["sql"] + ) diff --git a/bookwyrm/tests/views/books/test_book.py b/bookwyrm/tests/views/books/test_book.py index ee6e7d8b47..fa0a328a39 100644 --- a/bookwyrm/tests/views/books/test_book.py +++ b/bookwyrm/tests/views/books/test_book.py @@ -7,6 +7,7 @@ from django.contrib.auth.models import Group, Permission from django.contrib.contenttypes.models import ContentType from django.core.files.uploadedfile import SimpleUploadedFile +from django.db import connection from django.http import Http404 from django.template.response import TemplateResponse from django.test import TestCase @@ -16,8 +17,9 @@ from bookwyrm import forms, models, views from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.tests.validate_html import validate_html +from bookwyrm.tests.query_logger import QueryLogger, raise_long_query_runtime - +# pylint: disable=invalid-name class BookViews(TestCase): """books books books""" @@ -68,9 +70,15 @@ def test_book_page(self): ) request = self.factory.get("") request.user = self.local_user - with patch("bookwyrm.views.books.books.is_api_request") as is_api: - is_api.return_value = False - result = view(request, self.book.id) + + query_logger = QueryLogger() + with connection.execute_wrapper(query_logger): + with patch("bookwyrm.views.books.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.book.id) + + raise_long_query_runtime(query_logger.queries) + self.assertIsInstance(result, TemplateResponse) validate_html(result.render())