Is it possible to disable django haystack for some tests?
Asked Answered
K

1

8

We use django-haystack as our search index. Generally great, but during tests it adds overhead to every model object creation and save, and for most tests it is not required. So I would like to avoid it. So I thought I'd use override_settings to use a dummy that did nothing. But I've now tried both the BaseSignalProcessor and the SimpleEngine and I can still see our search index (elasticsearch) getting hit a lot.

The two version I have tried are:

First using the SimpleEngine which does no data preparation:

from django.test import TestCase
from django.test.utils import override_settings

HAYSTACK_DUMMY_INDEX = {
    'default': {
        'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
    }
}

@override_settings(HAYSTACK_CONNECTIONS=HAYSTACK_DUMMY_INDEX)
class TestAllTheThings(TestCase):
    # ...

and then using the BaseSignalProcessor which should mean that the signals to save are not hooked up:

from django.test import TestCase
from django.test.utils import override_settings

@override_settings(HAYSTACK_SIGNAL_PROCESSOR='haystack.signals.BaseSignalProcessor')
class TestAllTheThings(TestCase):
    # ...

I am using pytest as the test runner in case that matters.

Any idea if there is something I am missing?

Kneepad answered 13/10, 2015 at 17:7 Comment(1)
For the first part that you tried, did you have a call to haystack.connections.reload('default') in the setUp of TestAllTheThings?Subdominant
T
5

The settings are only accessed once so overriding it after the fact won't change anything.

Instead, you can subclass the signal processor and stick in some logic to conditionally disable it like so:

from django.conf import settings

from haystack.signals import BaseSignalProcessor


class TogglableSignalProcessor(BaseSignalProcessor):
    settings_key = 'HAYSTACK_DISABLE'

    def handle_save(self, sender, instance, **kwargs):
        if not getattr(settings, self.settings_key, False):
            super().handle_save(sender, instance, **kwargs)

    def handle_delete(self, sender, instance, **kwargs):
        if not getattr(settings, self.settings_key, False):
            super().handle_delete(sender, instance, **kwargs)

Now if you configure that as your signal processor then you can easily disable it in tests. The settings key can be set with an environment variable if you're just using manage.py test and not a custom runner. Otherwise you should know where to stick it.

import os

HAYSTACK_DISABLE = 'IS_TEST' in os.environ

And run it with

IS_TEST=1 python manage.py test

And for the few tests where you want it enabled, use override_settings() like you have already tried:

class MyTest(TestCase):
    @override_settings(HAYSTACK_ENABLE=True)
    def that_one_test_where_its_needed(self):
       pass

Of course you can go even further and have conditional settings for the signal processor class so if you have a busy site then my conditional checks don't slow it down when it's running live.

Trioecious answered 13/10, 2018 at 3:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.