microsoft / knack

Knack - A Python command line interface framework
https://pypi.python.org/pypi/knack
MIT License
344 stars 95 forks source link

Broken `examples/test_exapp`: TypeError: ScenarioTest.__init__() missing 1 required positional argument: 'method_name' #287

Open jiasli opened 1 month ago

jiasli commented 1 month ago

First of all, examples/test_exapp cannot be directly executed by pytest.

> pytest examples\test_exapp
================================================= test session starts =================================================
platform win32 -- Python 3.11.9, pytest-8.2.2, pluggy-1.5.0
rootdir: D:\cli\knack
plugins: forked-1.6.0, xdist-3.6.1
collected 0 items

================================================ no tests ran in 0.02s ================================================
ERROR: not found: D:\cli\knack\examples\test_exapp
(no match in any of [<Dir examples>])

After renaming it to test_exapp.py. pytest fails with

> pytest examples\test_exapp.py
================================================= test session starts =================================================
platform win32 -- Python 3.11.9, pytest-8.2.2, pluggy-1.5.0
rootdir: D:\cli\knack
plugins: forked-1.6.0, xdist-3.6.1
collected 3 items / 1 error

======================================================= ERRORS ========================================================
_______________________________________ ERROR collecting examples/test_exapp.py _______________________________________
..\py311\Lib\site-packages\_pytest\runner.py:341: in from_call
    result: Optional[TResult] = func()
..\py311\Lib\site-packages\_pytest\runner.py:389: in collect
    return list(collector.collect())
..\py311\Lib\site-packages\_pytest\unittest.py:90: in collect
    self.session._fixturemanager.parsefactories(self.newinstance(), self.nodeid)
..\py311\Lib\site-packages\_pytest\unittest.py:75: in newinstance
    return self.obj("runTest")
E   TypeError: ScenarioTest.__init__() missing 1 required positional argument: 'method_name'
=============================================== short test summary info ===============================================
ERROR examples/test_exapp.py::ScenarioTest - TypeError: ScenarioTest.__init__() missing 1 required positional argument: 'method_name'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
================================================== 1 error in 0.96s ===================================================
jiasli commented 1 month ago

I think the reason for the TypeError: ScenarioTest.__init__() missing 1 required positional argument: 'method_name' error is related to https://github.com/pytest-dev/pytest/issues/12289.

As ScenarioTest is imported into examples/test_exapp: https://github.com/microsoft/knack/blob/4acec273463deca92e579ca3141055a2923e3173/examples/test_exapp#L59

pytest treats ScenarioTest as a normal test class and calls its __init__ with method_name="runTest". However, knack.testsdk.base.ScenarioTest.__init__ requires 2 positional arguments:

https://github.com/microsoft/knack/blob/7ba23495c1a3dce5c7925449f6a09dc325b35f87/knack/testsdk/base.py#L82-L84

resulting in the error.

On the other hand, azure.cli.testsdk.base.ScenarioTest only has 1 positional argument:

https://github.com/Azure/azure-cli/blob/2750c65ea77638ecf699243555a5f2f7a1314ed4/src/azure-cli-testsdk/azure/cli/testsdk/base.py#L82-L85

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):

thus not having this issue.