Stop a settings test depending on which tests ran before it
CI failed one test that passes here: "no such table: settings", seeding a
Setting into a database with no tables. The test was not wrong about the
product, it was asking the process-wide plugin_manager to do the work.
create_app() re-points that singleton, and eight test modules build their own
app, so it belongs to whichever ran last on the xdist worker.
_seed_plugin_settings then opens `with self._app.app_context()` on a different
app's in-memory SQLite. A sibling symptom is the registry coming back None
("'NoneType' object has no attribute 'get_all'"). Both land on whichever test
follows, never on the module that caused them, so they move with the split -
green on one machine, red on another.
The test now builds a manager for itself, sets _app and _db, and calls
_seed_plugin_settings directly. That is the routine `flask plugin upgrade-all`
runs, so what is under test has not changed, and the assertion no longer depends
on worker order. init_app is deliberately not called: it re-registers the plugin
blueprints and a second call on one app raises "The name 'backups' is already
registered".
This does NOT fix the underlying fragility, and that is a separate decision.
Running tests/test_plugins serially today gives 115 failed and 542 errors, from
the same cause; under -n auto it is nearly invisible because modules land in
separate processes. The repair is to stop create_app mutating a module-level
singleton, and it belongs in its own change rather than riding along here.
This commit is contained in:
@@ -74,13 +74,30 @@ def test_the_declared_defaults_match_what_the_code_reads_with_no_row(db):
|
|||||||
def test_the_upgrade_pass_seeds_them_on_a_site_that_installed_earlier(app, db):
|
def test_the_upgrade_pass_seeds_them_on_a_site_that_installed_earlier(app, db):
|
||||||
"""install/enable fire only on a state transition, so a fleet already
|
"""install/enable fire only on a state transition, so a fleet already
|
||||||
running this plugin gets these rows from `flask plugin upgrade-all`, which
|
running this plugin gets these rows from `flask plugin upgrade-all`, which
|
||||||
calls sync_all_plugin_settings."""
|
calls sync_all_plugin_settings -> _seed_plugin_settings.
|
||||||
pm = app.extensions.get('plugin_manager')
|
|
||||||
if pm is None:
|
This drives _seed_plugin_settings on a manager built for this test rather
|
||||||
pytest.skip('no plugin manager in this build')
|
than the process-wide plugin_manager singleton, and that is deliberate.
|
||||||
|
create_app() re-points that singleton, eight test modules build their own
|
||||||
|
app, and whatever ran last on this xdist worker owns it: the symptoms are
|
||||||
|
"no such table: settings" (seeding against another app's in-memory SQLite)
|
||||||
|
and "'NoneType' object has no attribute 'get_all'" (registry left None).
|
||||||
|
Both land on whichever test follows, so they move with the split - this one
|
||||||
|
passed locally and failed on CI for exactly that reason.
|
||||||
|
|
||||||
|
init_app is not called here either: it re-registers the plugin blueprints,
|
||||||
|
and twice on one app raises "The name 'backups' is already registered".
|
||||||
|
Setting _app and _db is all the seeding routine reads.
|
||||||
|
"""
|
||||||
|
from shopdb.plugins import PluginManager
|
||||||
|
from plugins.endpoints.plugin import EndpointsPlugin
|
||||||
|
|
||||||
assert Setting.query.filter_by(key=QUERY_KEY).first() is None
|
assert Setting.query.filter_by(key=QUERY_KEY).first() is None
|
||||||
|
|
||||||
pm.sync_all_plugin_settings()
|
manager = PluginManager()
|
||||||
|
manager._app = app
|
||||||
|
manager._db = db
|
||||||
|
assert manager._seed_plugin_settings(EndpointsPlugin()) is True
|
||||||
|
|
||||||
for key, value in ((REVOKED_KEY, False), (QUERY_KEY, True)):
|
for key, value in ((REVOKED_KEY, False), (QUERY_KEY, True)):
|
||||||
row = Setting.query.filter_by(key=key).one()
|
row = Setting.query.filter_by(key=key).one()
|
||||||
|
|||||||
Reference in New Issue
Block a user