Skip to content

Commit

Permalink
Add tests for async usage (jazzband#1819)
Browse files Browse the repository at this point in the history
  • Loading branch information
salomvary committed Sep 19, 2023
1 parent 49624ea commit c97146e
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
47 changes: 47 additions & 0 deletions tests/panels/test_sql.py
Expand Up @@ -32,6 +32,20 @@ def sql_call(*, use_iterator=False):
return list(qs)


async def async_sql_call(*, use_iterator=False):
qs = User.objects.all()
if use_iterator:
qs = qs.iterator()
return await sync_to_async(list)(qs)


async def concurrent_async_sql_call(*, use_iterator=False):
qs = User.objects.all()
if use_iterator:
qs = qs.iterator()
return await asyncio.gather(sync_to_async(list)(qs), User.objects.acount())


class SQLPanelTestCase(BaseTestCase):
panel_id = "SQLPanel"

Expand All @@ -57,6 +71,39 @@ def test_recording(self):
# ensure the stacktrace is populated
self.assertTrue(len(query["stacktrace"]) > 0)

async def test_recording_async(self):
self.assertEqual(len(self.panel._queries), 0)

await async_sql_call()

# ensure query was logged
self.assertEqual(len(self.panel._queries), 1)
query = self.panel._queries[0]
self.assertEqual(query["alias"], "default")
self.assertTrue("sql" in query)
self.assertTrue("duration" in query)
self.assertTrue("stacktrace" in query)

# ensure the stacktrace is populated
self.assertTrue(len(query["stacktrace"]) > 0)

async def test_recording_concurrent_async(self):
self.assertEqual(len(self.panel._queries), 0)

await concurrent_async_sql_call()

# ensure query was logged
self.assertEqual(len(self.panel._queries), 2)
query = self.panel._queries[0]
self.assertEqual(query["alias"], "default")
self.assertTrue("sql" in query)
self.assertTrue("duration" in query)
self.assertTrue("stacktrace" in query)

# ensure the stacktrace is populated
self.assertTrue(len(query["stacktrace"]) > 0)


@unittest.skipUnless(
connection.vendor == "postgresql", "Test valid only on PostgreSQL"
)
Expand Down
39 changes: 39 additions & 0 deletions tests/test_integration.py
Expand Up @@ -218,6 +218,18 @@ def test_data_gone(self):
)
self.assertIn("Please reload the page and retry.", response.json()["content"])

def test_sql_page(self):
response = self.client.get("/execute_sql/")
self.assertEqual(len(response.toolbar.get_panel_by_id("SQLPanel").get_stats()["queries"]), 1)

def test_async_sql_page(self):
response = self.client.get("/async_execute_sql/")
self.assertEqual(len(response.toolbar.get_panel_by_id("SQLPanel").get_stats()["queries"]), 1)

def test_concurrent_async_sql_page(self):
response = self.client.get("/async_execute_sql_concurrently/")
self.assertEqual(len(response.toolbar.get_panel_by_id("SQLPanel").get_stats()["queries"]), 2)


@override_settings(DEBUG=True)
class DebugToolbarIntegrationTestCase(IntegrationTestCase):
Expand Down Expand Up @@ -749,3 +761,30 @@ def test_toolbar_language_will_render_to_locale_when_set_both(self):
)
self.assertIn("Query", table.text)
self.assertIn("Action", table.text)

def test_async_sql_action(self):
self.get("/async_execute_sql/")
sql_panel = self.selenium.find_element(By.ID, "SQLPanel")
debug_window = self.selenium.find_element(By.ID, "djDebugWindow")

# Click to show the SQL panel
self.selenium.find_element(By.CLASS_NAME, "SQLPanel").click()

# SQL panel loads
button = self.wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, ".remoteCall"))
)


def test_concurrent_async_sql_action(self):
self.get("/async_execute_sql_concurrently/")
sql_panel = self.selenium.find_element(By.ID, "SQLPanel")
debug_window = self.selenium.find_element(By.ID, "djDebugWindow")

# Click to show the SQL panel
self.selenium.find_element(By.CLASS_NAME, "SQLPanel").click()

# SQL panel loads
button = self.wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, ".remoteCall"))
)
2 changes: 2 additions & 0 deletions tests/urls.py
Expand Up @@ -17,6 +17,8 @@
path("non_ascii_request/", views.regular_view, {"title": NonAsciiRepr()}),
path("new_user/", views.new_user),
path("execute_sql/", views.execute_sql),
path("async_execute_sql/", views.async_execute_sql),
path("async_execute_sql_concurrently/", views.async_execute_sql_concurrently),
path("cached_view/", views.cached_view),
path("cached_low_level_view/", views.cached_low_level_view),
path("json_view/", views.json_view),
Expand Down
14 changes: 14 additions & 0 deletions tests/views.py
@@ -1,3 +1,6 @@
import asyncio

from asgiref.sync import sync_to_async
from django.contrib.auth.models import User
from django.core.cache import cache
from django.http import HttpResponseRedirect, JsonResponse
Expand All @@ -11,6 +14,17 @@ def execute_sql(request):
return render(request, "base.html")


async def async_execute_sql(request):
await sync_to_async(list)(User.objects.all())
return render(request, "base.html")


async def async_execute_sql_concurrently(request):
await asyncio.gather(sync_to_async(list)(User.objects.all()), User.objects.acount())
return render(request, "base.html")



def regular_view(request, title):
return render(request, "basic.html", {"title": title})

Expand Down

0 comments on commit c97146e

Please sign in to comment.