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

INTPYTHON-506 - Add django-rest-framework tests #263

Closed
wants to merge 1 commit into from

Conversation

aclark4life
Copy link
Collaborator

Based on

I've added and fixed 13 DRF tests here that are a subset of the 158 failed tests (1330 passing) as of 18e7177.

Here's the test run:

…
test_exact_search (rest_framework_.test_filters.SearchFilterTests.test_exact_search) ... ok
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {'$or': [{'$regexMatch': {'input': {'$toString': '$title'}, 'regex': {'$concat': ('^', 'zzz', {'$literal': '$'})}, 'options': 'i'}}, {'$regexMatch': {'input': {'$toString': '$text'}, 'regex': 'zzz', 'options': 'i'}}]}}}])
----------------------------------------------------------------------
test_regexp_search (rest_framework_.test_filters.SearchFilterTests.test_regexp_search) ... ok
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {'$and': [{'$or': [{'$regexMatch': {'input': {'$toString': '$title'}, 'regex': 'z{2}', 'options': 'i'}}, {'$regexMatch': {'input': {'$toString': '$text'}, 'regex': 'z{2}', 'options': 'i'}}]}, {'$or': [{'$regexMatch': {'input': {'$toString': '$title'}, 'regex': '^b', 'options': 'i'}}, {'$regexMatch': {'input': {'$toString': '$text'}, 'regex': '^b', 'options': 'i'}}]}]}}}])
----------------------------------------------------------------------
test_search (rest_framework_.test_filters.SearchFilterTests.test_search) ... ok
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {'$or': [{'$regexMatch': {'input': {'$toString': '$title'}, 'regex': 'b', 'options': 'i'}}, {'$regexMatch': {'input': {'$toString': '$text'}, 'regex': 'b', 'options': 'i'}}]}}}])
----------------------------------------------------------------------
test_search_field_with_additional_transforms (rest_framework_.test_filters.SearchFilterTests.test_search_field_with_additional_transforms) ... ERROR
----------------------------------------------------------------------
test_search_field_with_custom_lookup (rest_framework_.test_filters.SearchFilterTests.test_search_field_with_custom_lookup) ... ok
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {'$regexMatch': {'input': {'$toString': '$text'}, 'regex': {'$concat': ('c', {'$literal': '$'})}, 'options': 'i'}}}}])
----------------------------------------------------------------------
test_search_field_with_escapes (rest_framework_.test_filters.SearchFilterTests.test_search_field_with_escapes) ... ok
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {'$or': [{'$regexMatch': {'input': {'$toString': '$title'}, 'regex': '"text', 'options': 'i'}}, {'$regexMatch': {'input': {'$toString': '$text'}, 'regex': '"text', 'options': 'i'}}]}}}])
----------------------------------------------------------------------
test_search_field_with_multiple_words (rest_framework_.test_filters.SearchFilterTests.test_search_field_with_multiple_words) ... ERROR
----------------------------------------------------------------------
test_search_field_with_null_characters (rest_framework_.test_filters.SearchFilterTests.test_search_field_with_null_characters) ... ok
----------------------------------------------------------------------
test_search_field_with_quotes (rest_framework_.test_filters.SearchFilterTests.test_search_field_with_quotes) ... ok
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {'$or': [{'$regexMatch': {'input': {'$toString': '$title'}, 'regex': 'long\\ text', 'options': 'i'}}, {'$regexMatch': {'input': {'$toString': '$text'}, 'regex': 'long\\ text', 'options': 'i'}}]}}}])
----------------------------------------------------------------------
test_search_returns_same_queryset_if_no_search_fields_or_terms_provided (rest_framework_.test_filters.SearchFilterTests.test_search_returns_same_queryset_if_no_search_fields_or_terms_provided) ... ok
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {}}}])
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {}}}])
----------------------------------------------------------------------
test_search_with_filter_subclass (rest_framework_.test_filters.SearchFilterTests.test_search_with_filter_subclass) ... ok
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {'$or': [{'$regexMatch': {'input': {'$toString': '$title'}, 'regex': '^\\w{3}$', 'options': 'i'}}, {'$regexMatch': {'input': {'$toString': '$text'}, 'regex': '^\\w{3}$', 'options': 'i'}}]}}}])
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {'$regexMatch': {'input': {'$toString': '$title'}, 'regex': '^\\w{3}$', 'options': 'i'}}}}])
----------------------------------------------------------------------
test_search_with_nonstandard_search_param (rest_framework_.test_filters.SearchFilterTests.test_search_with_nonstandard_search_param) ... ok
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {'$or': [{'$regexMatch': {'input': {'$toString': '$title'}, 'regex': 'b', 'options': 'i'}}, {'$regexMatch': {'input': {'$toString': '$text'}, 'regex': 'b', 'options': 'i'}}]}}}])
----------------------------------------------------------------------
test_startswith_search (rest_framework_.test_filters.SearchFilterTests.test_startswith_search) ... ok
(0.000) db.rest_framework__searchfiltermodel.aggregate([{'$match': {'$expr': {'$or': [{'$regexMatch': {'input': {'$toString': '$title'}, 'regex': 'b', 'options': 'i'}}, {'$regexMatch': {'input': {'$toString': '$text'}, 'regex': {'$concat': ('^', 'b')}, 'options': 'i'}}]}}}])
----------------------------------------------------------------------

======================================================================
ERROR: test_search_field_with_additional_transforms (rest_framework_.test_filters.SearchFilterTests.test_search_field_with_additional_transforms)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-mongodb-backend/django_mongodb_backend/query.py", line 19, in wrapper
    return func(*args, **kwargs)
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-mongodb-backend/django_mongodb_backend/query.py", line 74, in get_cursor
    return self.compiler.collection.aggregate(self.get_pipeline())
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-mongodb-backend/django_mongodb_backend/utils.py", line 166, in wrapper
    duration, retval = self.profile_call(func, args, kwargs)
                       ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-mongodb-backend/django_mongodb_backend/utils.py", line 131, in profile_call
    retval = func(*args, **kwargs or {})
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/synchronous/collection.py", line 2978, in aggregate
    return self._aggregate(
           ~~~~~~~~~~~~~~~^
        _CollectionAggregationCommand,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<6 lines>...
        **kwargs,
        ^^^^^^^^^
    )
    ^
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/_csot.py", line 119, in csot_wrapper
    return func(self, *args, **kwargs)
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/synchronous/collection.py", line 2886, in _aggregate
    return self._database.client._retryable_read(
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        cmd.get_cursor,
        ^^^^^^^^^^^^^^^
    ...<3 lines>...
        operation=_Op.AGGREGATE,
        ^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/synchronous/mongo_client.py", line 1861, in _retryable_read
    return self._retry_internal(
           ~~~~~~~~~~~~~~~~~~~~^
        func,
        ^^^^^
    ...<7 lines>...
        operation_id=operation_id,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/_csot.py", line 119, in csot_wrapper
    return func(self, *args, **kwargs)
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/synchronous/mongo_client.py", line 1828, in _retry_internal
    ).run()
      ~~~^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/synchronous/mongo_client.py", line 2565, in run
    return self._read() if self._is_read else self._write()
           ~~~~~~~~~~^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/synchronous/mongo_client.py", line 2708, in _read
    return self._func(self._session, self._server, conn, read_pref)  # type: ignore
           ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/synchronous/aggregation.py", line 164, in get_cursor
    result = conn.command(
        self._database.name,
    ...<9 lines>...
        user_fields=self._user_fields,
    )
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/synchronous/helpers.py", line 47, in inner
    return func(*args, **kwargs)
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/synchronous/pool.py", line 536, in command
    return command(
        self,
    ...<20 lines>...
        write_concern=write_concern,
    )
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/synchronous/network.py", line 213, in command
    helpers_shared._check_command_response(
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        response_doc,
        ^^^^^^^^^^^^^
    ...<2 lines>...
        parse_write_concern_error=parse_write_concern_error,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/Users/alex.clark/Developer/django-mongodb-cli/.venv/lib/python3.13/site-packages/pymongo/helpers_shared.py", line 247, in _check_command_response
    raise OperationFailure(errmsg, code, response, max_wire_version)
pymongo.errors.OperationFailure: $trim only supports an object as an argument, found string, full error: {'ok': 0.0, 'errmsg': '$trim only supports an object as an argument, found string', 'code': 50696, 'codeName': 'Location50696'}

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-mongodb-backend/tests/rest_framework_/test_filters.py", line 224, in test_search_field_with_additional_transforms
    response = view(request)
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django/django/views/decorators/csrf.py", line 65, in _view_wrapper
    return view_func(request, *args, **kwargs)
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-rest-framework/rest_framework/views.py", line 515, in dispatch
    response = self.handle_exception(exc)
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-rest-framework/rest_framework/views.py", line 475, in handle_exception
    self.raise_uncaught_exception(exc)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-rest-framework/rest_framework/views.py", line 486, in raise_uncaught_exception
    raise exc
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-rest-framework/rest_framework/views.py", line 512, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-rest-framework/rest_framework/generics.py", line 203, in get
    return self.list(request, *args, **kwargs)
           ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-rest-framework/rest_framework/mixins.py", line 46, in list
    return Response(serializer.data)
                    ^^^^^^^^^^^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-rest-framework/rest_framework/serializers.py", line 797, in data
    ret = super().data
          ^^^^^^^^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-rest-framework/rest_framework/serializers.py", line 251, in data
    self._data = self.to_representation(self.instance)
                 ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-rest-framework/rest_framework/serializers.py", line 716, in to_representation
    self.child.to_representation(item) for item in iterable
                                                   ^^^^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django/django/db/models/query.py", line 400, in __iter__
    self._fetch_all()
    ~~~~~~~~~~~~~~~^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django/django/db/models/query.py", line 1928, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
                         ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django/django/db/models/query.py", line 91, in __iter__
    results = compiler.execute_sql(
        chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size
    )
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-mongodb-backend/django_mongodb_backend/compiler.py", line 254, in execute_sql
    cursor = query.get_cursor()
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-mongodb-backend/django_mongodb_backend/query.py", line 27, in wrapper
    raise DatabaseError from e
django.db.utils.DatabaseError

----------------------------------------------------------------------

======================================================================
ERROR: test_search_field_with_multiple_words (rest_framework_.test_filters.SearchFilterTests.test_search_field_with_multiple_words)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-mongodb-backend/tests/rest_framework_/test_filters.py", line 247, in test_search_field_with_multiple_words
    rendered_search_field = filters.SearchFilter().to_html(
        request=request, queryset=view.queryset, view=view
    )
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django-rest-framework/rest_framework/filters.py", line 186, in to_html
    template = loader.get_template(self.template)
  File "/Users/alex.clark/Developer/django-mongodb-cli/src/django/django/template/loader.py", line 19, in get_template
    raise TemplateDoesNotExist(template_name, chain=chain)
django.template.exceptions.TemplateDoesNotExist: rest_framework/filters/search.html

----------------------------------------------------------------------

----------------------------------------------------------------------
Ran 13 tests in 0.404s

FAILED (errors=2)
Destroying test database for alias 'default' ('test_djangotests')...

Can we include this here?

@timgraham
Copy link
Collaborator

We can't reasonably copy third-party test suites into this package. If we identify a bug in our backend during third-party library testing, we will write a regression test in this package for the problem that doesn't rely on that third-party package. If you need to run third-party test suites for some sort of integration testing, I think the way to proceed is to fork that package so you can make the necessary edits so that it will run with MongoDB, just as we did for Django's test suite. I'm unsure whether that sort of thing is worthwhile and necessary.

As for the test failure, the custom Trim transform would need to be adapted to work with MongoDB (if it can be). But I don't think this test would be testing anything that's not already tested in Django's test suite.

@aclark4life aclark4life deleted the INTPYTHON-506 branch February 28, 2025 23:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants