Skip to content
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

{testsdk} Initialize random config dir in setUp #28849

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

jiasli
Copy link
Member

@jiasli jiasli commented Apr 28, 2024

Fix #28848

Description
According to https://docs.python.org/3/library/unittest.html#unittest.TestCase.tearDown, tearDown is a counterpart of setUp, meaning anything that is done in tearDown should have its equivalent in setUp.

This PR solves 2 problems:

  1. config_dir leak: By injecting print(os.getpid(), method_name) into azure.cli.testsdk.base.ScenarioTest.__init__ and running azdev test in --series mode , we can see pytest first creates a unittest.TestCase with method_name="runTest", and runs no test with it:

    $ azdev test test_containerapp_manualjob_withsecret_crudoperations_e2e --series
    ...
    collecting ... 1098 runTest
    1098 test_containerapp_manualjob_withsecret_crudoperations_e2e
    collected 1 item
    
    src/azure-cli/azure/cli/command_modules/containerapp/tests/latest/test_containerappjob_with_secrets. py::ContainerAppJobsSecretsOperationsTest::test_containerapp_manualjob_withsecret_crudoperations_e2e PASSED [100%]
    

    As no test method is run for runTest, tearDown is not called, leading to random config dir not being deleted.

  2. patch.dict pollution: From the above log, we can see azure.cli.testsdk.base.ScenarioTest.__init__ is run at pytest's collecting staging, in the same process (1098), but tearDown is executed after test methods have been finished. Therefore, this patch.dict(os.environ, {'AZURE_CONFIG_DIR': config_dir}) statement pollutes other test classes' __init__ methods while pytest collects them.

Related:

Copy link

azure-client-tools-bot-prd bot commented Apr 28, 2024

❌AzureCLI-FullTest
️✔️acr
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️acs
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️advisor
️✔️latest
️✔️3.11
️✔️3.9
️✔️ams
️✔️latest
️✔️3.11
️✔️3.9
️✔️apim
️✔️latest
️✔️3.11
️✔️3.9
️✔️appconfig
️✔️latest
️✔️3.11
️✔️3.9
️✔️appservice
️✔️latest
️✔️3.11
️✔️3.9
️✔️aro
️✔️latest
️✔️3.11
️✔️3.9
️✔️backup
️✔️latest
️✔️3.11
️✔️3.9
️✔️batch
️✔️latest
️✔️3.11
️✔️3.9
️✔️batchai
️✔️latest
️✔️3.11
️✔️3.9
️✔️billing
️✔️latest
️✔️3.11
️✔️3.9
️✔️botservice
️✔️latest
️✔️3.11
️✔️3.9
️✔️cdn
️✔️latest
️✔️3.11
️✔️3.9
️✔️cloud
️✔️latest
️✔️3.11
️✔️3.9
️✔️cognitiveservices
️✔️latest
️✔️3.11
️✔️3.9
️✔️compute_recommender
️✔️latest
️✔️3.11
️✔️3.9
️✔️config
️✔️latest
️✔️3.11
️✔️3.9
❌configure
❌latest
❌3.11
Type Test Case Error Message Line
Failed test_configure_global_defaults self = <azure.cli.command_modules.configure.tests.latest.test_configure.ConfigureGlobalDefaultsTest testMethod=test_configure_global_defaults>

    def test_configure_global_defaults(self):
        # setiing the az configure defaults
>       self.cmd('configure --defaults global=global1')

src/azure-cli/azure/cli/command_modules/configure/tests/latest/test_configure.py:41: 
                                        

self = <azure.cli.command_modules.configure.tests.latest.test_configure.ConfigureGlobalDefaultsTest testMethod=test_configure_global_defaults>
command = 'configure --defaults global=global1', checks = None
expect_failure = False

    def cmd(self, command, checks=None, expect_failure=False):
        command = self._apply_kwargs(command)
>       return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
E       AttributeError: 'ConfigureGlobalDefaultsTest' object has no attribute 'cli_ctx'

src/azure-cli-testsdk/azure/cli/testsdk/base.py:200: AttributeError
azure/cli/command_modules/configure/tests/latest/test_configure.py:38
❌3.9
Type Test Case Error Message Line
Failed test_configure_global_defaults self = <azure.cli.command_modules.configure.tests.latest.test_configure.ConfigureGlobalDefaultsTest testMethod=test_configure_global_defaults>

    def test_configure_global_defaults(self):
        # setiing the az configure defaults
>       self.cmd('configure --defaults global=global1')

src/azure-cli/azure/cli/command_modules/configure/tests/latest/test_configure.py:41: 
                                        

self = <azure.cli.command_modules.configure.tests.latest.test_configure.ConfigureGlobalDefaultsTest testMethod=test_configure_global_defaults>
command = 'configure --defaults global=global1', checks = None
expect_failure = False

    def cmd(self, command, checks=None, expect_failure=False):
        command = self._apply_kwargs(command)
>       return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
E       AttributeError: 'ConfigureGlobalDefaultsTest' object has no attribute 'cli_ctx'

src/azure-cli-testsdk/azure/cli/testsdk/base.py:200: AttributeError
azure/cli/command_modules/configure/tests/latest/test_configure.py:38
️✔️consumption
️✔️latest
️✔️3.11
️✔️3.9
️✔️container
️✔️latest
️✔️3.11
️✔️3.9
️✔️containerapp
️✔️latest
️✔️3.11
️✔️3.9
️✔️core
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️cosmosdb
️✔️latest
️✔️3.11
️✔️3.9
️✔️databoxedge
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️dla
️✔️latest
️✔️3.11
️✔️3.9
️✔️dls
️✔️latest
️✔️3.11
️✔️3.9
️✔️dms
️✔️latest
️✔️3.11
️✔️3.9
️✔️eventgrid
️✔️latest
️✔️3.11
️✔️3.9
️✔️eventhubs
️✔️latest
️✔️3.11
️✔️3.9
️✔️feedback
️✔️latest
️✔️3.11
️✔️3.9
️✔️find
️✔️latest
️✔️3.11
️✔️3.9
️✔️hdinsight
️✔️latest
️✔️3.11
️✔️3.9
️✔️identity
️✔️latest
️✔️3.11
️✔️3.9
️✔️iot
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️keyvault
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️kusto
️✔️latest
️✔️3.11
️✔️3.9
️✔️lab
️✔️latest
️✔️3.11
️✔️3.9
️✔️managedservices
️✔️latest
️✔️3.11
️✔️3.9
️✔️maps
️✔️latest
️✔️3.11
️✔️3.9
️✔️marketplaceordering
️✔️latest
️✔️3.11
️✔️3.9
️✔️monitor
️✔️latest
️✔️3.11
️✔️3.9
️✔️mysql
️✔️latest
️✔️3.11
️✔️3.9
️✔️netappfiles
️✔️latest
️✔️3.11
️✔️3.9
️✔️network
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️policyinsights
️✔️latest
️✔️3.11
️✔️3.9
️✔️privatedns
️✔️latest
️✔️3.11
️✔️3.9
️✔️profile
️✔️latest
️✔️3.11
️✔️3.9
️✔️rdbms
️✔️latest
️✔️3.11
️✔️3.9
️✔️redis
️✔️latest
️✔️3.11
️✔️3.9
️✔️relay
️✔️latest
️✔️3.11
️✔️3.9
️✔️resource
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️role
️✔️latest
️✔️3.11
️✔️3.9
️✔️search
️✔️latest
️✔️3.11
️✔️3.9
️✔️security
️✔️latest
️✔️3.11
️✔️3.9
️✔️servicebus
️✔️latest
️✔️3.11
️✔️3.9
️✔️serviceconnector
️✔️latest
️✔️3.11
️✔️3.9
️✔️servicefabric
️✔️latest
️✔️3.11
️✔️3.9
️✔️signalr
️✔️latest
️✔️3.11
️✔️3.9
️✔️sql
️✔️latest
️✔️3.11
️✔️3.9
️✔️sqlvm
️✔️latest
️✔️3.11
️✔️3.9
️✔️storage
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️synapse
️✔️latest
️✔️3.11
️✔️3.9
🔄telemetry
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
🔄latest
🔄3.11
🔄3.9
️✔️util
️✔️latest
️✔️3.11
️✔️3.9
️✔️vm
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9

Copy link

azure-client-tools-bot-prd bot commented Apr 28, 2024

️✔️AzureCLI-BreakingChangeTest
️✔️Non Breaking Changes

@yonzhan
Copy link
Collaborator

yonzhan commented Apr 28, 2024

testsdk

# get_config_dir directly. We need to set the env to make sure the config_dir is used.
env_patch = patch.dict(os.environ, {'AZURE_CONFIG_DIR': config_dir})
env_patch.start()
self.addCleanup(env_patch.stop)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The official doc of unittest.mock also prefers addCleanup over tearDown: https://docs.python.org/3/library/unittest.mock.html#patch-methods-start-and-stop

image


# In recording mode, copy login credentials from global config dir to the dummy config dir
if os.getenv(ENV_VAR_TEST_LIVE, '').lower() == 'true':
if os.path.exists(GLOBAL_CONFIG_DIR):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GLOBAL_CONFIG_DIR will always exist.

Copy link
Contributor

@bebound bebound Apr 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice, if the user is using --live, .azure should exist.

But from the code, .azure is created by AzCli:

azure_folder = self.config.config_dir
ensure_dir(azure_folder)

The super().__init__() is not called yet when this line is executed, and the folder might not exist.

def tearDown(self):
for processor in self._processors_to_reset:
processor.reset()
if self.random_config_dir:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if block is also eliminated by using addCleanup.

@@ -83,7 +83,6 @@ class ScenarioTest(ReplayableTest, CheckerMixin, unittest.TestCase):
def __init__(self, method_name, config_file=None, recording_name=None,
recording_processors=None, replay_processors=None, recording_patches=None, replay_patches=None,
random_config_dir=False):
self.cli_ctx = get_dummy_cli(random_config_dir=random_config_dir)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some tests reported the following errors:
AttributeError: 'xxxScenarioTest' object has no attribute 'cli_ctx'
https://dev.azure.com/azclitools/public/_build/results?buildId=153167&view=logs&j=9ccb9437-6abb-5c1a-b909-dd7aa8d5d916&t=da342424-93bf-5216-b53c-16ba29f2062e&l=674

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cli_ctx is moved to setUp mothod, which is executed after __init__.
If cli_ctx is used in __init__, this error is raised.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants