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

Methods for comparison of Django Q objects #34

Open
stevekm opened this issue Apr 27, 2020 · 1 comment
Open

Methods for comparison of Django Q objects #34

stevekm opened this issue Apr 27, 2020 · 1 comment
Labels
blog comment Comments and feedback on articles

Comments

@stevekm
Copy link

stevekm commented Apr 27, 2020

In your page here:

https://jamescooke.info/comparing-django-q-objects.html

https://github.com/jamescooke/blog/blob/d31e4ef3abed4985fa9cc9c567590e9cdfda13b4/content/1603-comparing-django-q-objects.rst

On the discussion of how to compare Q objects in Django unit tests, there are some alternative methods that can be used which you do not cover.

Here are some examples where you can test the contents of a Django Q object for single Q objects, compound AND/OR Q objects, and you can also test the contents of a Q object in case you have a situation where the order of the results are non-deterministic (e.g. you are using a set to hold some values that build the object).

In these examples, the Q object is being returned by an external query builder function based on a list of values.

from django.db.models import Q
from django.test import TestCase

class TestRetrieveSamplesByQuery(TestCase):
    def test_single_query(self):
        values = ["foo"]

        query = function_that_returns_Q_object(values)
        # (AND: (('value', 'bar'))

        expected_query = Q(value='bar')
        self.assertEqual(query, expected_query)

    def test_multiple_queries(self):
        values = ["foo", "bar"]

        query = function_that_returns_Q_object(values)
        # (OR: ('value', 'baz'), ('value', 'bar'))

        expected_query = Q(value='bar') | Q(value='baz')
        self.assertEqual(query, expected_query)

    def test_multiple_queries_indeterminate_order(self):
        values = ["foo", "bar"]

        query = another_function_that_returns_Q_object(values)
        # might return either:
        # (OR: ('value', 'baz'), ('value', 'bar'))
        # or: 
        # (OR: ('value', 'bar'), ('value', 'baz'))

        # query.__dict__
        # {'children': [('value', 'baz'), ('value', 'bar')], 'connector': 'OR', 'negated': False}

        self.assertTrue( ('value', 'baz') in query.__dict__['children'] )
        self.assertTrue( ('value', 'bar') in query.__dict__['children'] )
        self.assertEqual( len(query.__dict__['children']), 2 )
        self.assertTrue( query.__dict__['connector'] == 'OR' )
        self.assertTrue( query.__dict__['negated'] == False )
@jamescooke jamescooke added the blog comment Comments and feedback on articles label Apr 29, 2020
@jamescooke
Copy link
Owner

Thanks @stevekm for the comments.

What version of Django are you using? These posts were written about the time of Django 1.8 when Q objects did not implement __cmp__ and so using assertEqual() would not work - hence the reason for the post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blog comment Comments and feedback on articles
Projects
None yet
Development

No branches or pull requests

2 participants