/
How to Test MongoDB and MySQL Call Counts and XBlock Instantiation Counts

How to Test MongoDB and MySQL Call Counts and XBlock Instantiation Counts

An important performance measurement for code is the number of MongoDB and/or MySQL calls the code makes. Each call is likely a network round-trip in the production environment, which is relatively costly. So the number of calls should generally be minimized and tests should be written that monitors the amount of expected MongoDB / MySQL calls.

MongoDB Call Counting

There's a few Python context managers used to count MongoDB calls:

  • check_mongo_calls
  • check_mongo_calls_range

The context managers are part of edx-platform here:

from xmodule.modulestore.tests.factories import check_mongo_calls

Here's some code snippets which uses the context managers:

    with check_mongo_calls(reads):
        with check_sum_of_calls(XBlock, ['__init__'], xblocks, xblocks, include_arguments=False):
            self.grade_course(self.course)
    with check_mongo_calls_range(max_finds=max_mongo_calls, min_finds=min_mongo_calls):
        _course_overview_1 = CourseOverview.get_from_id(course.id)

To guarantee that no MongoDB calls are made in a section of code, use this pattern:

    with check_mongo_calls(0):
        _course_overview_2 = CourseOverview.get_from_id(course.id)

MySQL Call Counting

MySQL queries are counted with a context manager provided by the Django framework - django.test.TestCase.assertNumQueries.

    with self.assertNumQueries(4):
        outcomes.store_outcome_parameters(params, self.user, self.consumer)

To guarantee that no MySQL calls are made in a section of code, use this pattern:

    with self.assertNumQueries(0):
        outcomes.store_outcome_parameters(params, self.user, self.consumer)

XBlock Instantiation Counting

Instantiating XBlocks can be expensive, and large numbers of instantiations can be indicative of a bad query pattern.

with check_sum_of_calls(XBlock, ['__init__'], instantiations, instantiations, include_arguments=False):
    self.grade_course(self.course)