From 99f8be6a1298e9da7c46616d28b19e1963b33a17 Mon Sep 17 00:00:00 2001 From: Riken Shah Date: Wed, 24 Mar 2021 16:55:30 +0530 Subject: [PATCH] puppeteer_tests: Reset test environment after each run. When running some tests multiple times in the same call, were failing because of the data duplication. This commit resolves that issue by resetting the test environment (i.e: Re-cloning test database and clearing cache) after each run. Fixes #17607. --- tools/test-js-with-puppeteer | 10 ++++++++ zerver/lib/test_fixtures.py | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/tools/test-js-with-puppeteer b/tools/test-js-with-puppeteer index 891c78fe79..e8497bc712 100755 --- a/tools/test-js-with-puppeteer +++ b/tools/test-js-with-puppeteer @@ -5,10 +5,13 @@ import shlex import subprocess import sys +import requests + sys.path.append(os.path.join(os.path.dirname(__file__), "..")) from scripts.lib.zulip_tools import ENDC, FAIL, OKGREEN ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +from zerver.lib.test_fixtures import reset_zulip_test_database # Request the special webpack setup for frontend integration tests, # where webpack assets are compiled up front rather than running in @@ -83,6 +86,13 @@ def run_tests(files: Iterable[str], external_host: str) -> None: flush=True, ) ret = subprocess.call(cmd) + + # Resetting test environment. + reset_zulip_test_database() + # We are calling to /flush_caches to remove all the server-side caches. + response = requests.get("http://zulip.zulipdev.com:9981/flush_caches") + assert response.status_code == 200 + if ret != 0: return ret, current_test_num current_test_num += 1 diff --git a/zerver/lib/test_fixtures.py b/zerver/lib/test_fixtures.py index 716c537c1c..3db3a1d2a0 100644 --- a/zerver/lib/test_fixtures.py +++ b/zerver/lib/test_fixtures.py @@ -386,3 +386,49 @@ def remove_test_run_directories(expiry_time: int = 60 * 60) -> int: except FileNotFoundError: pass return removed + + +def reset_zulip_test_database() -> None: + """ + This function is used to reset the zulip_test database fastest way possible, + i.e. First, it deletes the database and then clones it from zulip_test_template. + This function is used with puppeteer tests, so it can quickly reset the test + database after each run. + """ + from zerver.lib.test_runner import destroy_test_databases + + # Make sure default database is 'zulip_test'. + assert connections["default"].settings_dict["NAME"] == "zulip_test" + + # Clearing all the active PSQL sessions with 'zulip_test'. + run( + [ + "env", + "PGHOST=localhost", + "PGUSER=zulip_test", + "scripts/setup/terminate-psql-sessions", + "zulip_test", + ] + ) + + destroy_test_databases() + # Pointing default database to test database template, so we can instantly clone it. + settings.DATABASES["default"]["NAME"] = settings.BACKEND_DATABASE_TEMPLATE + connection = connections["default"] + clone_database_suffix = "clone" + connection.creation.clone_test_db( + suffix=clone_database_suffix, + ) + settings_dict = connection.creation.get_test_db_clone_settings(clone_database_suffix) + # We manually rename the clone database to 'zulip_test' because when cloning it, + # its name is set to original database name + some suffix. + # Also, we need it to be 'zulip_test' so that our running server can recognize it. + with connection.cursor() as cursor: + cursor.execute("ALTER DATABASE zulip_test_template_clone RENAME TO zulip_test;") + settings_dict["NAME"] = "zulip_test" + # connection.settings_dict must be updated in place for changes to be + # reflected in django.db.connections. If the following line assigned + # connection.settings_dict = settings_dict, new threads would connect + # to the default database instead of the appropriate clone. + connection.settings_dict.update(settings_dict) + connection.close()