Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to disable django haystack for some tests?

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?

like image 360
Hamish Downer Avatar asked Oct 13 '15 17:10

Hamish Downer


People also ask

What is Django haystack?

Haystack provides modular search for Django. It features a unified, familiar API that allows you to plug in different search backends (such as Solr, Elasticsearch, Whoosh, Xapian, etc.) without having to modify your code.

What is test case in Django?

The best base class for most tests is django. test. TestCase. This test class creates a clean database before its tests are run, and runs every test function in its own transaction. The class also owns a test Client that you can use to simulate a user interacting with the code at the view level.

What is self client in Django?

self. client , is the built-in Django test client. This isn't a real browser, and doesn't even make real requests. It just constructs a Django HttpRequest object and passes it through the request/response process - middleware, URL resolver, view, template - and returns whatever Django produces.


1 Answers

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.

like image 134
Anonymous Avatar answered Oct 26 '22 15:10

Anonymous