Skip to content

Commit

Permalink
add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
aaxelb committed Apr 21, 2023
1 parent 52d62cd commit 16e7cc4
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 191 deletions.
68 changes: 29 additions & 39 deletions tests/share/search/conftest.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,38 @@
import pytest

from share.search.index_strategy import IndexStrategy


@pytest.fixture(scope='session')
def elastic_test_index_name():
return 'test_share'

from unittest import mock

@pytest.fixture(params=['es5', 'es8'])
def elastic_test_cluster_url(request, settings):
if request.param == 'es5':
return settings.ELASTICSEARCH5_URL
if request.param == 'es8':
return settings.ELASTICSEARCH8_URL
raise ValueError(request.param)
import pytest


@pytest.fixture()
def actual_elasticsearch(elastic_test_index_name, elastic_test_cluster_url, settings):
old_elasticsearch_settings = settings.ELASTICSEARCH
@pytest.fixture
def fake_elastic_strategies(settings):
settings.ELASTICSEARCH = {
**old_elasticsearch_settings,
'TIMEOUT': 5,
'PRIMARY_INDEX': elastic_test_index_name,
'LEGACY_INDEX': elastic_test_index_name,
'BACKCOMPAT_INDEX': elastic_test_index_name,
'ACTIVE_INDEXES': [elastic_test_index_name],
**settings.ELASTICSEARCH,
'INDEX_STRATEGIES': {
elastic_test_index_name: {
'my_es5_strategy': {
'CLUSTER_SETTINGS': {'URL': 'blah'},
'INDEX_STRATEGY_CLASS': 'share.search.index_strategy.sharev2_elastic5.Sharev2Elastic5IndexStrategy',
'CLUSTER_SETTINGS': {
'URL': settings.ELASTICSEARCH5_URL,
},
},
'my_es8_strategy': {
'CLUSTER_SETTINGS': {'URL': 'bleh'},
'INDEX_STRATEGY_CLASS': 'share.search.index_strategy.sharev2_elastic8.Sharev2Elastic8IndexStrategy',
},
'another_es8_strategy': {
'CLUSTER_SETTINGS': {'URL': 'bluh'},
'INDEX_STRATEGY_CLASS': 'share.search.index_strategy.sharev2_elastic8.Sharev2Elastic8IndexStrategy',
},
},
}
index_strategy = IndexStrategy.get_by_name(elastic_test_index_name)
try:
index_strategy.pls_delete()
index_strategy.pls_setup()
try:
yield
finally:
index_strategy.pls_delete()
except Exception as error:
raise pytest.skip(f'Elasticsearch unavailable? (error: {error})')
return tuple(settings.ELASTICSEARCH['INDEX_STRATEGIES'].keys())


@pytest.fixture
def mock_elastic_clients(fake_elastic_strategies):
with mock.patch('share.search.index_strategy.sharev2_elastic5.elasticsearch5') as es5_mockpackage:
with mock.patch('share.search.index_strategy.elastic8.elasticsearch8') as es8_mockpackage:
es5_mockclient = es5_mockpackage.Elasticsearch.return_value
es8_mockclient = es8_mockpackage.Elasticsearch.return_value
yield {
'my_es5_strategy': es5_mockclient,
'my_es8_strategy': es8_mockclient,
'another_es8_strategy': es8_mockclient,
}

This file was deleted.

157 changes: 6 additions & 151 deletions tests/share/search/index_strategy/test_base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from unittest import mock

import pytest

from share.search.exceptions import IndexStrategyError
Expand All @@ -11,55 +9,21 @@


@pytest.fixture
def fake_elastic_settings(settings):
settings.ELASTICSEARCH = {
**settings.ELASTICSEARCH,
'INDEX_STRATEGIES': {
'my_es5_strategy': {
'CLUSTER_SETTINGS': {'URL': 'blah'},
'INDEX_STRATEGY_CLASS': 'share.search.index_strategy.sharev2_elastic5.Sharev2Elastic5IndexStrategy',
},
'my_es8_strategy': {
'CLUSTER_SETTINGS': {'URL': 'bleh'},
'INDEX_STRATEGY_CLASS': 'share.search.index_strategy.sharev2_elastic8.Sharev2Elastic8IndexStrategy',
},
'another_es8_strategy': {
'CLUSTER_SETTINGS': {'URL': 'bluh'},
'INDEX_STRATEGY_CLASS': 'share.search.index_strategy.sharev2_elastic8.Sharev2Elastic8IndexStrategy',
},
},
}


@pytest.fixture
def expected_strategy_classes(fake_elastic_settings):
def expected_strategy_classes(fake_elastic_strategies):
return {
'my_es5_strategy': sharev2_elastic5.Sharev2Elastic5IndexStrategy,
'my_es8_strategy': sharev2_elastic8.Sharev2Elastic8IndexStrategy,
'another_es8_strategy': sharev2_elastic8.Sharev2Elastic8IndexStrategy,
}


@pytest.fixture
def mock_es_clients(fake_elastic_settings):
with mock.patch('share.search.index_strategy.sharev2_elastic5.elasticsearch5') as es5_mockpackage:
with mock.patch('share.search.index_strategy.elastic8.elasticsearch8') as es8_mockpackage:
es5_mockclient = es5_mockpackage.Elasticsearch.return_value
es8_mockclient = es8_mockpackage.Elasticsearch.return_value
yield {
'my_es5_strategy': es5_mockclient,
'my_es8_strategy': es8_mockclient,
'another_es8_strategy': es8_mockclient,
}


class TestBaseIndexStrategy:
def test_get_by_name(self, mock_es_clients, expected_strategy_classes):
def test_get_by_name(self, mock_elastic_clients, expected_strategy_classes):
for strategy_name, expected_strategy_class in expected_strategy_classes.items():
index_strategy = IndexStrategy.get_by_name(strategy_name)
assert isinstance(index_strategy, expected_strategy_class)

def test_all_strategies(self, mock_es_clients, expected_strategy_classes):
def test_all_strategies(self, mock_elastic_clients, expected_strategy_classes):
all_strategys = tuple(IndexStrategy.all_strategies())
assert len(all_strategys) == len(expected_strategy_classes)
strategy_names = {index_strategy.name for index_strategy in all_strategys}
Expand All @@ -70,7 +34,7 @@ def test_all_strategies(self, mock_es_clients, expected_strategy_classes):
assert issubclass(index_strategy.SpecificIndex, IndexStrategy.SpecificIndex)
assert index_strategy.SpecificIndex is not IndexStrategy.SpecificIndex

def test_get_by_specific_indexname(self, mock_es_clients, expected_strategy_classes, fake_elastic_settings):
def test_get_by_specific_indexname(self, mock_elastic_clients, expected_strategy_classes, fake_elastic_strategies):
for strategy_name, expected_strategy_class in expected_strategy_classes.items():
indexname_prefix = IndexStrategy.get_by_name(strategy_name).indexname_prefix
specific_indexname = ''.join((indexname_prefix, 'foo'))
Expand All @@ -82,8 +46,8 @@ def test_get_by_specific_indexname(self, mock_es_clients, expected_strategy_clas
with pytest.raises(IndexStrategyError):
IndexStrategy.get_specific_index(bad_indexname)

def test_get_by_request(self, mock_es_clients, fake_elastic_settings):
for strategy_name in mock_es_clients.keys():
def test_get_by_request(self, mock_elastic_clients, fake_elastic_strategies):
for strategy_name in mock_elastic_clients.keys():
index_strategy = IndexStrategy.get_by_name(strategy_name)
good_requests = [
strategy_name,
Expand All @@ -105,112 +69,3 @@ def test_get_by_request(self, mock_es_clients, fake_elastic_settings):
IndexStrategy.get_for_searching()
with pytest.raises(ValueError):
IndexStrategy.get_for_searching(requested_name=None)

# def test_stream_actions(self, mock_es_clients):
# input_actions = [
# {'index': {'foo': 0}},
# {'delete': {'bar': 1}},
# ]
# response_stream = [
# (True, {'index': {'foo': 0}}),
# (True, {'delete': {'bar': 1}}),
# ]
# expected_return = [
# (True, 'index', {'foo': 0}),
# (True, 'delete', {'bar': 1}),
# ]
# with patch(
# 'share.search.elastic_manager.elastic_helpers.bulk',
# return_value=response_stream,
# ) as mock_streaming_bulk:
# actual_return = list(isolated_elastic_manager.stream_actions(input_actions))

# mock_streaming_bulk.assert_called_once_with(
# isolated_elastic_manager.es_client,
# input_actions,
# max_chunk_bytes=isolated_elastic_manager.MAX_CHUNK_BYTES,
# raise_on_error=False,
# )
# assert actual_return == expected_return

# def test_send_actions_sync(self, mock_es_clients):
# input_actions = [
# {'index': {'foo': 0}},
# {'delete': {'bar': 1}},
# ]
# with patch('share.search.elastic_manager.elastic_helpers.bulk') as bock_mulk:
# isolated_elastic_manager.send_actions_sync(input_actions)
# bock_mulk.assert_called_once_with(isolated_elastic_manager.es_client, input_actions)

# @pytest.mark.parametrize('index_names, expected_arg', [
# (['trove_index'], 'trove_index'),
# (['postrend_index'], 'postrend_index'),
# (['trove_index', 'postrend_index'], 'trove_index,postrend_index'),
# ])
# def test_refresh_indexes(self, mock_es_clients, index_names, expected_arg):
# mock_es_client = isolated_elastic_manager.es_client

# isolated_elastic_manager.refresh_indexes(index_names)

# mock_es_client.indices.refresh.assert_called_once_with(index=expected_arg)

# @pytest.mark.parametrize('index_name', [
# 'postrend_index',
# 'trove_index',
# ])
# def test_initial_update_primary_alias(self, mock_es_clients, index_name, settings):
# alias_name = settings.ELASTICSEARCH['PRIMARY_INDEX']
# mock_es_client = isolated_elastic_manager.es_client
# mock_es_client.configure_mock(**{
# 'indices.get_alias.side_effect': NotFoundError,
# })

# isolated_elastic_manager.update_primary_alias(index_name)

# mock_es_client.indices.get_alias.assert_called_once_with(name=alias_name)
# mock_es_client.indices.update_aliases.assert_called_once_with(
# body={'actions': [
# {'add': {'index': index_name, 'alias': alias_name}}
# ]}
# )

# @pytest.mark.parametrize('index_name', [
# 'postrend_index',
# 'trove_index',
# ])
# def test_update_primary_alias(self, mock_es_clients, index_name, settings):
# alias_name = settings.ELASTICSEARCH['PRIMARY_INDEX']
# mock_es_client = isolated_elastic_manager.es_client
# mock_es_client.configure_mock(**{
# 'indices.get_alias.return_value': {
# 'old_primary': {'alias': alias_name},
# },
# })

# isolated_elastic_manager.update_primary_alias(index_name)

# mock_es_client.indices.get_alias.assert_called_once_with(name=alias_name)
# mock_es_client.indices.update_aliases.assert_called_once_with(
# body={'actions': [
# {'remove': {'index': 'old_primary', 'alias': alias_name}},
# {'add': {'index': index_name, 'alias': alias_name}},
# ]}
# )

# @pytest.mark.parametrize('index_name', [
# 'postrend_index',
# 'trove_index',
# ])
# def test_unnecessary_update_primary_alias(self, mock_es_clients, index_name, settings):
# alias_name = settings.ELASTICSEARCH['PRIMARY_INDEX']
# mock_es_client = isolated_elastic_manager.es_client
# mock_es_client.configure_mock(**{
# 'indices.get_alias.return_value': {
# index_name: {'alias': alias_name},
# },
# })

# isolated_elastic_manager.update_primary_alias(index_name)

# mock_es_client.indices.get_alias.assert_called_once_with(name=alias_name)
# mock_es_client.indices.update_aliases.assert_not_called()
21 changes: 21 additions & 0 deletions tests/share/search/test_admin_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from unittest import mock

from django.test.client import Client
import pytest

from share.models import ShareUser
from share.search.index_strategy import IndexStrategy


@pytest.mark.django_db
def test_admin_search_indexes_view(fake_elastic_strategies, mock_elastic_clients):
credentials = {'username': 'test-test-test', 'password': 'password-password'}
ShareUser.objects.create_superuser(**credentials)
client = Client()
client.login(**credentials)
with mock.patch('share.search.index_strategy.elastic8.elasticsearch8'):
resp = client.get('/admin/search-indexes')
for strategy_name in fake_elastic_strategies:
index_strategy = IndexStrategy.get_by_name(strategy_name)
expected_header = f'<h3>current index: <i>{index_strategy.current_indexname}</i></h3>'
assert expected_header.encode() in resp.content
52 changes: 52 additions & 0 deletions tests/share/search/test_index_backfill.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from unittest import mock

import pytest

from share.models import IndexBackfill


@pytest.mark.django_db
class TestIndexBackfillMethods:
@pytest.fixture
def fake_strategy(self):
fake_strategy = mock.Mock()
fake_strategy.name = 'foo'
fake_strategy.for_current_index.return_value.indexname = 'foo_bar'
return fake_strategy

@pytest.fixture
def index_backfill(self, fake_strategy):
return IndexBackfill.objects.create(
index_strategy_name=fake_strategy.name,
)

def test_happypath(self, index_backfill, fake_strategy):
assert index_backfill.backfill_status == IndexBackfill.INITIAL
assert index_backfill.specific_indexname == ''
with mock.patch('share.tasks.schedule_index_backfill') as mock_task:
index_backfill.pls_start(fake_strategy)
mock_task.apply_async.assert_called_once_with((index_backfill.pk,))
assert index_backfill.backfill_status == IndexBackfill.WAITING
assert index_backfill.specific_indexname == 'foo_bar'
index_backfill.pls_note_scheduling_has_begun()
assert index_backfill.backfill_status == IndexBackfill.SCHEDULING
index_backfill.pls_note_scheduling_has_finished()
assert index_backfill.backfill_status == IndexBackfill.INDEXING
index_backfill.pls_mark_complete()
assert index_backfill.backfill_status == IndexBackfill.COMPLETE

def test_error(self, index_backfill):
assert index_backfill.backfill_status == IndexBackfill.INITIAL
assert index_backfill.error_type == ''
assert index_backfill.error_message == ''
assert index_backfill.error_context == ''
index_backfill.pls_mark_error(ValueError('hello'))
assert index_backfill.backfill_status == IndexBackfill.ERROR
assert index_backfill.error_type == 'ValueError'
assert index_backfill.error_message == 'hello'
assert index_backfill.error_context
index_backfill.pls_mark_error(None)
assert index_backfill.backfill_status == IndexBackfill.ERROR # clearing error does not change status
assert index_backfill.error_type == ''
assert index_backfill.error_message == ''
assert index_backfill.error_context == ''

0 comments on commit 16e7cc4

Please sign in to comment.