-
Notifications
You must be signed in to change notification settings - Fork 14k
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
chore(tests): Remove unnecessary/problematic app contexts #28159
Conversation
bedac16
to
9d5b35e
Compare
f2c6f2e
to
5afbff9
Compare
|
||
|
||
@pytest.fixture() | ||
def load_unicode_dashboard_with_slice(load_unicode_data): | ||
slice_name = "Unicode Cloud" | ||
with app.app_context(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary due to fixture inheritance.
747acdc
to
5403487
Compare
dash = _create_unicode_dashboard(slice_name, position) | ||
yield | ||
_cleanup(dash, slice_name) | ||
dash = _create_unicode_dashboard(slice_name, position) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary due to fixture inheritance.
@@ -81,36 +81,6 @@ | |||
SCHEMA_ACCESS_ROLE = "schema_access_role" | |||
|
|||
|
|||
class TestRequestAccess(SupersetTestCase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class had no tests associated with it and thus is obsolete.
83d7d10
to
f7ec362
Compare
@@ -58,39 +58,36 @@ | |||
class TestDashboard(SupersetTestCase): | |||
@pytest.fixture | |||
def load_dashboard(self): | |||
with app.app_context(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The app context is not needed within the confines of a derived Flask-Testing class.
f7ec362
to
3eb6f97
Compare
@@ -37,39 +37,36 @@ | |||
class TestDashboardDatasetSecurity(DashboardTestCase): | |||
@pytest.fixture | |||
def load_dashboard(self): | |||
with app.app_context(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The app context is not needed within the confines of a derived Flask-Testing class.
data_loader.load_table(birth_names_table) | ||
yield | ||
data_loader.remove_table(birth_names_table.table_name) | ||
with app.app_context(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to inheritance of fixtures only the outer fixture requires instantiating the app context.
@@ -96,16 +97,14 @@ def get_upload_db(): | |||
return db.session.query(Database).filter_by(database_name=CSV_UPLOAD_DATABASE).one() | |||
|
|||
|
|||
@pytest.fixture(scope="function") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function
scope is the default scope.
3eb6f97
to
c8cb69b
Compare
get_user, | ||
) -> None: | ||
from superset.commands.report.alert import AlertCommand | ||
from superset.reports.models import ReportSchedule | ||
|
||
with app.app_context(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pushed app context is already being leveraged via the app_context
fixture specified on line 65.
c8cb69b
to
3ea1b33
Compare
@@ -35,150 +35,144 @@ def owners(get_user) -> list[User]: | |||
return [get_user("admin")] | |||
|
|||
|
|||
@pytest.mark.usefixtures("owners") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to both specify the use of the fixture here in addition to passing it in to the function.
@@ -685,20 +685,19 @@ def test_parse_js_uri_path_items_item_optional(self): | |||
self.assertIsNotNone(parse_js_uri_path_item("item")) | |||
|
|||
def test_get_stacktrace(self): | |||
with app.app_context(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The app context is not needed within the confines of a derived Flask-Testing class.
@@ -82,5 +82,4 @@ def test_form_data_to_adhoc_incorrect_clause_type(): | |||
form_data = {"where": "1 = 1", "having": "count(*) > 1"} | |||
|
|||
with pytest.raises(ValueError): | |||
with app.app_context(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for an app context to remap the form-data.
@@ -84,10 +84,9 @@ | |||
def test_check_sqlalchemy_uri( | |||
sqlalchemy_uri: str, error: bool, error_message: Optional[str] | |||
): | |||
with app.app_context(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary.
738334f
to
fba2cf2
Compare
@@ -70,36 +68,35 @@ def _insert_annotation( | |||
|
|||
|
|||
@pytest.fixture() | |||
def create_annotation_layers(): | |||
def create_annotation_layers(app_context: AppContext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse existing fixture.
816fe2a
to
3fa7f7c
Compare
with app.app_context(): | ||
if backend() == "hive": | ||
pytest.skip("Skipping tests for Hive backend") | ||
def skip_by_backend(app_context: AppContext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse existing fixture.
# relying on `tests.integration_tests.test_app.app` leveraging an `app` fixture which is purposely | ||
# scoped to the function level to ensure tests remain idempotent. | ||
# relying on `tests.integration_tests.test_app.app` leveraging an `app` fixture | ||
# which is purposely scoped to the function level to ensure tests remain idempotent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing app_context
fixture cannot be used due to different scopes.
3fa7f7c
to
914170b
Compare
with app.app_context(): | ||
yield from _setup_csv_upload() | ||
@pytest.fixture() | ||
def setup_csv_upload_with_context(app_context: AppContext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse existing fixture.
with app.app_context(): | ||
yield from _setup_csv_upload(["public"]) | ||
@pytest.fixture() | ||
def setup_csv_upload_with_context_schema(app_context: AppContext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse existing fixture.
with app.app_context(): | ||
yield from _setup_excel_upload() | ||
@pytest.fixture() | ||
def setup_excel_upload_with_context(app_context: AppContext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse existing fixture.
with app.app_context(): | ||
yield from _setup_excel_upload(["public"]) | ||
@pytest.fixture() | ||
def setup_excel_upload_with_context_schema(app_context: AppContext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse existing fixture.
914170b
to
97e23ce
Compare
with app.app_context(): | ||
cache_manager.data_cache.clear() | ||
yield | ||
def clear_data_cache(self, app_context: AppContext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse existing fixture. That said I'm not entirely sure why it's needed given it's in a class derived from Flask-Testing's TestCase
class.
3896f55
to
8449636
Compare
@@ -41,9 +41,7 @@ def create_old_role(pvm_map: PvmMigrationMapType, external_pvms): | |||
pvms = [] | |||
for old_pvm, new_pvms in pvm_map.items(): | |||
pvms.append( | |||
security_manager.add_permission_view_menu( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Black formatting.
8449636
to
8ec3857
Compare
sqllab_role = ( | ||
db.session.query(Role).filter(Role.name == "sql_lab").one_or_none() | ||
) | ||
def create_gamma_sqllab_no_data(app_context: AppContext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse existing fixture.
with app.app_context(): | ||
app.config["PUBLIC_ROLE_LIKE"] = "Gamma" | ||
security_manager.sync_role_definitions() | ||
def public_role_like_gamma(app_context: AppContext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse existing fixture.
with app.app_context(): | ||
app.config["PUBLIC_ROLE_LIKE"] = "TestRole" | ||
security_manager.sync_role_definitions() | ||
def public_role_like_test_role(app_context: AppContext): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reuse existing fixture.
@@ -35,150 +35,144 @@ def owners(get_user) -> list[User]: | |||
return [get_user("admin")] | |||
|
|||
|
|||
@pytest.mark.usefixtures("owners") | |||
@pytest.mark.usefixtures("app_context") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use existing fixture.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Left a comment about having a consistent way to pass the app context.
@@ -22,12 +22,12 @@ | |||
|
|||
|
|||
@pytest.fixture | |||
@pytest.mark.usefixtures("app_context") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not pass app_context
as an argument, like in other places, for consistency?
@@ -34,28 +36,28 @@ | |||
downgrade = migration_module.do_downgrade | |||
|
|||
|
|||
@pytest.mark.usefixtures("app_context") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, should we standardize on either using usefixtures
or passing app_context
to the test function/fixture?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@betodealmeida I tried to standardize this. It seems that:
- If you want to use a fixture in a test you can either pass it as an argument or via @pytest.mark.usefixtures if test functions do not directly need access to a fixture object. Personally I find the later more readable as otherwise when you're reading through the code it feels like a potentially unused argument.
- Somewhat cryptic, but if you want to use a fixture in another fixture you have to pass it as an argument*.
- Per here it states,
Warning: Note this mark has no effect in fixture functions. For example, this will not work as expected:
@pytest.mark.usefixtures("my_other_fixture") @pytest.fixture def my_fixture_that_sadly_wont_use_my_other_fixture(): ...Currently this will not generate any error or warning, but this is intended to be handled by issue #3664.
Maybe sticking with one pattern throughout is cleaner though—passing it as a function argument. I'm open to suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spoke with @michael-s-molina offline and it seems like he's supportive of the approach I've taken here so I'm going to go ahead and merge this. I think as a follow up it would be good to use the @pytest.mark.usefixtures
decorator where possible.
1706639
to
369b5a5
Compare
SUMMARY
As part of a large change related to [SIP-99B] Proposal for (re)defining a "unit of work", I'm in the process of creating some PRs to clean up some unnecessary/problematic logic to aid with future testing/debugging.
Specifically it seems like at times we're overly pushing an application context where, per the documentation, it states:
This is likely the cause of a number of issues I was running into with expired objects in the session not being refreshed.
Finally this PR removes all
db.session.expire_all()
statements which are not needed. Per my previous statement, these likely were added due to some inconsistencies with how the session was being managed during testing.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
TESTING INSTRUCTIONS
CI.
ADDITIONAL INFORMATION