-
Notifications
You must be signed in to change notification settings - Fork 65
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
Faster tests by using wait_task #249
Comments
A complete different idea, why not just mock the call to the Example: from unittest.mock import patch, call
def test_save_signal(self):
with patch('algoliasearch.index.Index.save_object') as mocked_save_object:
Website.objects.create(name='Algolia', url='https://www.algolia.com')
Website.objects.create(name='Google', url='https://www.google.com')
Website.objects.create(name='Facebook', url='https://www.facebook.com')
mocked_save_object.assert_has_calls([
call({'name': 'Algolia'}),
...
]) This way, we avoid unnecessary calls to the API and avoid waiting for the answers. While I do think calling the API and check the responses are necessary in some cases (ie the indexes settings parameters checks), I don't think it's necessary in this kind of tests since the WDYT? |
@clemfromspace 💯, let's stop duplicating E2E tests for the sake of it. I'm all in for mocking everywhere we can! 🙂 This being said, I still believe exposing |
Indeed, as I said above, for some tests we do need to actually call the API, so the |
|
Would it be a good idea, in i.e. here replace Thanks! |
It'd also be great if Should I open a PR..? |
I had a similar issue trying to run tests that call the API while waiting synchronously. This was the solution I came up with
from algoliasearch_django import AlgoliaIndex
...
class CustomAlgoliaIndex(AlgoliaIndex):
...
def save_record(self, instance, update_fields=None, **kwargs):
"""Saves the record.
If `update_fields` is set, this method will use partial_update_object()
and will update only the given fields (never `_geoloc` and `_tags`).
For more information about partial_update_object:
https://github.com/algolia/algoliasearch-client-python#update-an-existing-object-in-the-index
"""
if not self._should_index(instance):
# Should not index, but since we don't now the state of the
# instance, we need to send a DELETE request to ensure that if
# the instance was previously indexed, it will be removed.
self.delete_record(instance)
return
obj = None
try:
if update_fields:
obj = self.get_raw_record(instance,
update_fields=update_fields)
result = self.__index.partial_update_object(obj).wait()
else:
obj = self.get_raw_record(instance)
result = self.__index.save_object(obj).wait()
logger.info('SAVE %s FROM %s', obj['objectID'], self.model)
return result
except AlgoliaException as e:
if DEBUG:
raise e
else:
logger.warning('%s FROM %s NOT SAVED: %s', obj['objectID'],
self.model, e)
def delete_record(self, instance):
"""Deletes the record."""
objectID = self.objectID(instance)
try:
self.__index.delete_object(objectID).wait()
logger.info('DELETE %s FROM %s', objectID, self.model)
except AlgoliaException as e:
if DEBUG:
raise e
else:
logger.warning('%s FROM %s NOT DELETED: %s', objectID,
self.model, e)
def clear_objects(self):
"""Clears all objects of an index."""
try:
self.__index.clear_objects().wait()
logger.info('CLEAR INDEX %s', self.index_name)
except AlgoliaException as e:
if DEBUG:
raise e
else:
logger.warning('%s NOT CLEARED: %s', self.model, e)
...
from algoliasearch_django.decorators import register
from .models import Company, User
from core.custom_algolia_index import CustomAlgoliaIndex
@register(User)
class UserIndex(CustomAlgoliaIndex):
fields = ('first_name', 'last_name', 'community', 'company_name')
settings = {'searchableAttributes': ['first_name', 'last_name', 'community', 'company_name']}
index_name = 'users'
from algoliasearch_django import algolia_engine, raw_search
from django.db.models.signals import post_save, post_delete
from django.test import TestCase
from core import settings
from users.index import UserIndex, CompanyIndex
from users.models import User, Company, index_object, delete_object_index
# TODO: test company indexing, mock the is_async_available lib
class UsersTestCase(TestCase):
def setUp(self):
algolia_settings = dict(settings.ALGOLIA)
algolia_settings['INDEX_PREFIX'] = 'test'
algolia_engine.reset(algolia_settings)
self.model_index_pairs = ((User, UserIndex), (Company, CompanyIndex))
for model, model_index in self.model_index_pairs:
algolia_engine.register(model, model_index, False)
post_save.disconnect(receiver=index_object, sender=model)
post_delete.disconnect(receiver=delete_object_index, sender=model)
self.user = User.objects.create(email='[email protected]', first_name='Angelina', last_name='Jolie')
def tearDown(self):
for model, model_index in self.model_index_pairs:
algolia_engine.clear_objects(model)
algolia_engine.reset(settings.ALGOLIA)
def test_save_user_index(self):
algolia_engine.save_record(self.user)
response = raw_search(User)
self.assertTrue(any(self.user.last_name == user_dict['last_name'] for user_dict in response['hits']))
def test_delete_user_index(self):
algolia_engine.save_record(self.user)
algolia_engine.delete_record(self.user)
response = raw_search(User)
self.assertTrue(not any(self.user.last_name == user_dict['last_name'] for user_dict in response['hits'])) I hope this helps someone! Note: I am running with |
Today, several of our tests are slowed down by forced sleeping:
We could replace the
sleep
call by leveragingwait_task
. This requires:AlgoliaEngine
__post_save_receiver
hook, we need to expose the last taskID somewhere likeAlgoliaEngine.last_taskID
so you can then refactor the previous code as:The text was updated successfully, but these errors were encountered: