Skip to content

Commit

Permalink
Merge pull request #935 from DanielArndt/update-async-tests
Browse files Browse the repository at this point in the history
#935

#### Description

As of Python 3.8, `AsyncMock` and many other async testing tools are available as standard libraries. This PR removes the third-party library `asynctest` and replaces it with those available in the standard python library.

As part of this, the tests will now run on Python 3.11, which they previously did not.

Additionally, warnings during tests are significantly reduced (from hundreds, to tens).

#### QA Steps

Running the unit and integration tests is hopefully sufficient

#### Notes & Discussion

I went down a rabbit hole here while investigating something totally unrelated. I understand if this change needs a more thorough review which there may or may not be time for, but I thought I'd put up the change since I was having some fun digging in.
  • Loading branch information
jujubot authored Aug 24, 2023
2 parents 28f31fa + 42648d0 commit f21bc42
Show file tree
Hide file tree
Showing 23 changed files with 92 additions and 291 deletions.
7 changes: 0 additions & 7 deletions tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
from contextlib import contextmanager
from pathlib import Path

import mock

import pytest
from juju.client.jujudata import FileJujuData
from juju.controller import Controller
Expand Down Expand Up @@ -147,11 +145,6 @@ def models(self):
return all_models


class AsyncMock(mock.MagicMock):
async def __call__(self, *args, **kwargs):
return super().__call__(*args, **kwargs)


@contextmanager
def patch_file(filename):
"""
Expand Down
16 changes: 0 additions & 16 deletions tests/integration/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@


@base.bootstrapped
@pytest.mark.asyncio
async def test_action(event_loop):
async with base.CleanModel() as model:
app = await model.deploy('juju-qa-test')
Expand All @@ -26,7 +25,6 @@ async def test_action(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_get_set_config(event_loop):
async with base.CleanModel() as model:
app = await model.deploy(
Expand All @@ -51,7 +49,6 @@ async def test_get_set_config(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('Update charm')
async def test_status_is_not_unset(event_loop):
async with base.CleanModel() as model:
Expand All @@ -66,7 +63,6 @@ async def test_status_is_not_unset(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('Update charm')
async def test_status(event_loop):
async with base.CleanModel() as model:
Expand All @@ -82,7 +78,6 @@ def app_ready():


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('Update charm')
async def test_add_units(event_loop):
from juju.unit import Unit
Expand All @@ -102,7 +97,6 @@ async def test_add_units(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_deploy_charmhub_charm(event_loop):
async with base.CleanModel() as model:
app = await model.deploy('ubuntu')
Expand All @@ -112,7 +106,6 @@ async def test_deploy_charmhub_charm(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('Skip until a similar k8s solution is found')
async def test_upgrade_charm_switch_channel(event_loop):
# Note for future:
Expand Down Expand Up @@ -157,7 +150,6 @@ async def test_upgrade_charm_switch_channel(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('Update charm')
async def test_upgrade_charm_revision(event_loop):
async with base.CleanModel() as model:
Expand All @@ -170,7 +162,6 @@ async def test_upgrade_charm_revision(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('Update charm')
async def test_upgrade_charm_switch(event_loop):
async with base.CleanModel() as model:
Expand All @@ -185,7 +176,6 @@ async def test_upgrade_charm_switch(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_upgrade_local_charm(event_loop):
async with base.CleanModel() as model:
tests_dir = Path(__file__).absolute().parent
Expand All @@ -199,7 +189,6 @@ async def test_upgrade_local_charm(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_upgrade_local_charm_resource(event_loop):
async with base.CleanModel() as model:
tests_dir = Path(__file__).absolute().parent
Expand All @@ -219,7 +208,6 @@ async def test_upgrade_local_charm_resource(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_upgrade_charm_resource_same_rev_no_update(event_loop):
async with base.CleanModel() as model:
app = await model.deploy('keystone', channel='victoria/stable')
Expand All @@ -230,7 +218,6 @@ async def test_upgrade_charm_resource_same_rev_no_update(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_trusted(event_loop):
async with base.CleanModel() as model:
await model.deploy('ubuntu', trust=True)
Expand All @@ -245,7 +232,6 @@ async def test_trusted(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_app_destroy(event_loop):
async with base.CleanModel() as model:
app = await model.deploy('ubuntu')
Expand All @@ -261,7 +247,6 @@ async def test_app_destroy(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_app_remove_wait_flag(event_loop):
async with base.CleanModel() as model:
app = await model.deploy('ubuntu')
Expand All @@ -273,7 +258,6 @@ async def test_app_remove_wait_flag(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_app_charm_name(event_loop):
async with base.CleanModel() as model:
app = await model.deploy('ubuntu')
Expand Down
9 changes: 0 additions & 9 deletions tests/integration/test_charmhub.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@


@base.bootstrapped
@pytest.mark.asyncio
async def test_info(event_loop):
async with base.CleanModel() as model:
_, name = await model.charmhub.get_charm_id("ubuntu")
Expand All @@ -31,7 +30,6 @@ async def test_info(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_info_with_channel(event_loop):
async with base.CleanModel() as model:
charm_info = await model.charmhub.info("juju-qa-test", "2.0/stable")
Expand All @@ -50,7 +48,6 @@ async def test_info_with_channel(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_info_not_found(event_loop):
async with base.CleanModel() as model:
with pytest.raises(JujuError) as err:
Expand All @@ -59,7 +56,6 @@ async def test_info_not_found(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('CharmHub facade no longer exists')
async def test_find(event_loop):
async with base.CleanModel() as model:
Expand All @@ -72,7 +68,6 @@ async def test_find(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('CharmHub facade no longer exists')
async def test_find_bundles(event_loop):
async with base.CleanModel() as model:
Expand All @@ -85,7 +80,6 @@ async def test_find_bundles(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('CharmHub facade no longer exists')
async def test_find_all(event_loop):
async with base.CleanModel() as model:
Expand All @@ -98,7 +92,6 @@ async def test_find_all(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('This tries to test juju controller logic')
async def test_subordinate_charm_zero_units(event_loop):
# normally in pylibjuju deploy num_units defaults to 1, we switch
Expand Down Expand Up @@ -126,15 +119,13 @@ async def test_subordinate_charm_zero_units(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_subordinate_false_field_exists(event_loop):
async with base.CleanModel() as model:
assert await model.charmhub.is_subordinate("rsyslog-forwarder-ha")
assert not await model.charmhub.is_subordinate("mysql-innodb-cluster")


@base.bootstrapped
@pytest.mark.asyncio
async def test_list_resources(event_loop):
async with base.CleanModel() as model:
resources = await model.charmhub.list_resources('hello-kubecon')
Expand Down
3 changes: 0 additions & 3 deletions tests/integration/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@

from juju.client import client

import pytest

from .. import base


@base.bootstrapped
@pytest.mark.asyncio
async def test_user_info(event_loop):
async with base.CleanModel() as model:
controller_conn = await model.connection().controller()
Expand Down
6 changes: 0 additions & 6 deletions tests/integration/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@


@base.bootstrapped
@pytest.mark.asyncio
async def test_monitor(event_loop):
async with base.CleanModel() as model:
conn = model.connection()
Expand All @@ -36,7 +35,6 @@ async def test_monitor(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_monitor_catches_error(event_loop):

async with base.CleanModel() as model:
Expand All @@ -57,7 +55,6 @@ async def test_monitor_catches_error(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('Update charm')
async def test_full_status(event_loop):
async with base.CleanModel() as model:
Expand All @@ -74,7 +71,6 @@ async def test_full_status(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_reconnect(event_loop):
async with base.CleanModel() as model:
kwargs = model.connection().connect_params()
Expand All @@ -90,7 +86,6 @@ async def test_reconnect(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
@pytest.mark.skip('tests the websocket protocol, not pylibjuju, needs to be revised')
async def test_redirect(event_loop):
controller = Controller()
Expand Down Expand Up @@ -238,7 +233,6 @@ def _find_free_port(self):


@base.bootstrapped
@pytest.mark.asyncio
async def test_verify_controller_cert(event_loop):
jujudata = FileJujuData()
controller_name = jujudata.current_controller()
Expand Down
12 changes: 0 additions & 12 deletions tests/integration/test_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@


@base.bootstrapped
@pytest.mark.asyncio
async def test_add_remove_user(event_loop):
async with base.CleanController() as controller:
username = 'test{}'.format(uuid.uuid4())
Expand All @@ -36,7 +35,6 @@ async def test_add_remove_user(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_disable_enable_user(event_loop):
async with base.CleanController() as controller:
username = 'test-disable{}'.format(uuid.uuid4())
Expand All @@ -60,7 +58,6 @@ async def test_disable_enable_user(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_change_user_password(event_loop):
async with base.CleanController() as controller:
username = 'test-password{}'.format(uuid.uuid4())
Expand All @@ -81,7 +78,6 @@ async def test_change_user_password(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_reset_user_password(event_loop):
async with base.CleanController() as controller:
username = 'test{}'.format(uuid.uuid4())
Expand Down Expand Up @@ -110,7 +106,6 @@ async def test_reset_user_password(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_list_models(event_loop):
async with base.CleanController() as controller:
async with base.CleanModel() as model:
Expand All @@ -119,7 +114,6 @@ async def test_list_models(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_get_model(event_loop):
async with base.CleanController() as controller:
by_name, by_uuid = None, None
Expand Down Expand Up @@ -153,7 +147,6 @@ async def _wait_for_model_gone(controller, model_name):


@base.bootstrapped
@pytest.mark.asyncio
async def test_destroy_model_by_name(event_loop):
async with base.CleanController() as controller:
model_name = 'test-{}'.format(uuid.uuid4())
Expand All @@ -169,7 +162,6 @@ async def test_destroy_model_by_name(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_add_destroy_model_by_uuid(event_loop):
async with base.CleanController() as controller:
model_name = 'test-{}'.format(uuid.uuid4())
Expand All @@ -186,7 +178,6 @@ async def test_add_destroy_model_by_uuid(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_add_remove_cloud(event_loop):
async with base.CleanController() as controller:
cloud_name = 'test-{}'.format(uuid.uuid4())
Expand All @@ -204,7 +195,6 @@ async def test_add_remove_cloud(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_secrets_backend_lifecycle(event_loop):
"""Testing the add_secret_backends is particularly
costly in term of resources. This test sets a vault
Expand Down Expand Up @@ -282,7 +272,6 @@ async def test_secrets_backend_lifecycle(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_grant_revoke_controller_access(event_loop):
async with base.CleanController() as controller:
username = 'test-grant{}'.format(uuid.uuid4())
Expand Down Expand Up @@ -310,7 +299,6 @@ async def test_grant_revoke_controller_access(event_loop):


@base.bootstrapped
@pytest.mark.asyncio
async def test_grant_revoke_model_access(event_loop):
async with base.CleanController() as controller:
username = 'test-grant{}'.format(uuid.uuid4())
Expand Down
Loading

0 comments on commit f21bc42

Please sign in to comment.