From 670f339f5c58af17d2422a0ce2939a6438c7b6d8 Mon Sep 17 00:00:00 2001 From: abram axel booth Date: Tue, 10 Sep 2024 17:12:53 -0400 Subject: [PATCH] avoid clobbering all indexes by running tests - rename the `es` pytest marker to `es_metrics` (for clarity) - update the effect of that marker: - patch a prefix to each metric class's index and template names - instead of deleting ALL indexes and index templates, delete only those with the patched prefix --- .../views/test_institution_department_list.py | 2 +- .../views/test_institution_summary_metrics.py | 2 +- .../test_institution_user_metric_list.py | 2 +- api_tests/metrics/test_composite_query.py | 2 +- api_tests/metrics/test_preprint_metrics.py | 2 +- api_tests/metrics/test_raw_metrics.py | 2 +- .../test_registries_moderation_metrics.py | 4 +- conftest.py | 49 ++++++++++++++----- .../management_commands/test_reindex_es6.py | 2 +- osf_tests/test_management_commands.py | 2 +- 10 files changed, 47 insertions(+), 22 deletions(-) diff --git a/api_tests/institutions/views/test_institution_department_list.py b/api_tests/institutions/views/test_institution_department_list.py index 5a22d17fdff8..f2a335eed85c 100644 --- a/api_tests/institutions/views/test_institution_department_list.py +++ b/api_tests/institutions/views/test_institution_department_list.py @@ -10,7 +10,7 @@ from osf.metrics import UserInstitutionProjectCounts -@pytest.mark.es +@pytest.mark.es_metrics @pytest.mark.django_db class TestInstitutionDepartmentList: diff --git a/api_tests/institutions/views/test_institution_summary_metrics.py b/api_tests/institutions/views/test_institution_summary_metrics.py index b29998d5561b..8fee209b7692 100644 --- a/api_tests/institutions/views/test_institution_summary_metrics.py +++ b/api_tests/institutions/views/test_institution_summary_metrics.py @@ -9,7 +9,7 @@ from osf.metrics import InstitutionProjectCounts -@pytest.mark.es +@pytest.mark.es_metrics @pytest.mark.django_db class TestInstitutionSummaryMetrics: diff --git a/api_tests/institutions/views/test_institution_user_metric_list.py b/api_tests/institutions/views/test_institution_user_metric_list.py index 225f876e3830..deec0cf365cd 100644 --- a/api_tests/institutions/views/test_institution_user_metric_list.py +++ b/api_tests/institutions/views/test_institution_user_metric_list.py @@ -14,7 +14,7 @@ from osf.metrics import UserInstitutionProjectCounts from api.base import settings -@pytest.mark.es +@pytest.mark.es_metrics @pytest.mark.django_db class TestInstitutionUserMetricList: diff --git a/api_tests/metrics/test_composite_query.py b/api_tests/metrics/test_composite_query.py index fd36c0c5f24b..0cd0b3bb180f 100644 --- a/api_tests/metrics/test_composite_query.py +++ b/api_tests/metrics/test_composite_query.py @@ -29,7 +29,7 @@ def base_url(): return f'/{API_BASE}metrics/preprints/' -@pytest.mark.es +@pytest.mark.es_metrics @pytest.mark.django_db class TestElasticSearch: diff --git a/api_tests/metrics/test_preprint_metrics.py b/api_tests/metrics/test_preprint_metrics.py index c3a24f4183eb..55a9ce350238 100644 --- a/api_tests/metrics/test_preprint_metrics.py +++ b/api_tests/metrics/test_preprint_metrics.py @@ -116,7 +116,7 @@ def test_custom_metric_malformed_query(self, mock_execute, app, user, base_url): assert res.status_code == 400 assert res.json['errors'][0]['detail'] == 'Malformed elasticsearch query.' - @pytest.mark.es + @pytest.mark.es_metrics def test_agg_query(self, app, user, base_url): post_url = f'{base_url}downloads/' diff --git a/api_tests/metrics/test_raw_metrics.py b/api_tests/metrics/test_raw_metrics.py index c7feb69426b9..452f87469a00 100644 --- a/api_tests/metrics/test_raw_metrics.py +++ b/api_tests/metrics/test_raw_metrics.py @@ -14,7 +14,7 @@ pytestmark = pytest.mark.django_db -@pytest.mark.es +@pytest.mark.es_metrics class TestRawMetrics: @pytest.fixture(autouse=True) diff --git a/api_tests/metrics/test_registries_moderation_metrics.py b/api_tests/metrics/test_registries_moderation_metrics.py index d8b78cdf5ad0..93cde9f1121a 100644 --- a/api_tests/metrics/test_registries_moderation_metrics.py +++ b/api_tests/metrics/test_registries_moderation_metrics.py @@ -22,7 +22,7 @@ def enable_elasticsearch_metrics(self): with override_switch(features.ELASTICSEARCH_METRICS, active=True): yield - @pytest.mark.es + @pytest.mark.es_metrics def test_record_transitions(self, registration): registration._write_registration_action( RegistrationModerationStates.INITIAL, @@ -70,7 +70,7 @@ def other_user(self): def base_url(self): return '/_/metrics/registries_moderation/transitions/' - @pytest.mark.es + @pytest.mark.es_metrics def test_registries_moderation_view(self, app, user, base_url, registration): registration._write_registration_action( RegistrationModerationStates.INITIAL, diff --git a/conftest.py b/conftest.py index 2eb51df076ed..18a0e10b3daa 100644 --- a/conftest.py +++ b/conftest.py @@ -1,3 +1,4 @@ +import contextlib from unittest import mock import logging import os @@ -5,7 +6,9 @@ from django.core.management import call_command from django.db import transaction +from elasticsearch import exceptions as es_exceptions from elasticsearch_dsl.connections import connections +from elasticsearch_metrics.metrics import Metric from faker import Factory import pytest import responses @@ -133,22 +136,44 @@ def es6_client(setup_connections): @pytest.fixture(scope='function', autouse=True) -def _es_marker(request): +def _es_metrics_marker(request): """Clear out all indices and index templates before and after - tests marked with ``es``. + tests marked with `es_metrics`. """ - marker = request.node.get_closest_marker('es') + marker = request.node.get_closest_marker('es_metrics') if marker: es6_client = request.getfixturevalue('es6_client') - - def teardown_es(): - es6_client.indices.delete(index='*') - es6_client.indices.delete_template('*') - - teardown_es() - call_command('sync_metrics') - yield - teardown_es() + _temp_prefix = 'temp_metrics_' + _temp_wildcard = f'{_temp_prefix}*' + + def _teardown_es_temps(): + es6_client.indices.delete(index=_temp_wildcard) + try: + es6_client.indices.delete_template(_temp_wildcard) + except es_exceptions.NotFoundError: + pass + + @contextlib.contextmanager + def _mock_metric_names(): + with contextlib.ExitStack() as _exit: + for _metric_class in Metric.__subclasses__(): + _exit.enter_context(mock.patch.object( + _metric_class, + '_template_name', + f'{_temp_prefix}{_metric_class._template_name}', + )) + _exit.enter_context(mock.patch.object( + _metric_class, + '_template', # actually a template-wildcard string + f'{_temp_prefix}{_metric_class._template}', + )) + yield + + _teardown_es_temps() + with _mock_metric_names(): + call_command('sync_metrics') + yield + _teardown_es_temps() else: yield diff --git a/osf_tests/management_commands/test_reindex_es6.py b/osf_tests/management_commands/test_reindex_es6.py index 2e881b8f0882..58a209ef9bb0 100644 --- a/osf_tests/management_commands/test_reindex_es6.py +++ b/osf_tests/management_commands/test_reindex_es6.py @@ -45,7 +45,7 @@ def admin(self): def url(self): return f'{settings.API_DOMAIN}_/metrics/preprints/downloads/' - @pytest.mark.es + @pytest.mark.es_metrics @pytest.mark.skipif(django_settings.TRAVIS_ENV, reason='Non-deterministic fails on travis') def test_reindexing(self, app, url, preprint, user, admin, es6_client): preprint_download = PreprintDownload.record_for_preprint( diff --git a/osf_tests/test_management_commands.py b/osf_tests/test_management_commands.py index 8f29e72bc93e..26e346016486 100644 --- a/osf_tests/test_management_commands.py +++ b/osf_tests/test_management_commands.py @@ -265,7 +265,7 @@ def test_data_storage_usage_command(self): assert (key, expected_summary_data[key]) == (key, actual_summary_data[key]) -@pytest.mark.es +@pytest.mark.es_metrics @pytest.mark.django_db class TestInstitutionMetricsUpdate: