From ebdf341e611693ab2576ed780ec13205552e342e Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Tue, 10 Dec 2024 16:51:56 +0000 Subject: [PATCH] =?UTF-8?q?Convert=20self.fail(=E2=80=A6)=20to=20pytest.fa?= =?UTF-8?q?il(=E2=80=A6)=20(#75)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #39. --------- Co-authored-by: Bruno Oliveira --- CHANGES.rst | 5 +++++ tests/fixtures/self_assert/fail_in.py | 18 ++++++++++++++++++ tests/fixtures/self_assert/fail_out.py | 19 +++++++++++++++++++ unittest2pytest/fixes/fix_self_assert.py | 22 +++++++++++++++------- 4 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 tests/fixtures/self_assert/fail_in.py create mode 100644 tests/fixtures/self_assert/fail_out.py diff --git a/CHANGES.rst b/CHANGES.rst index 70349ed..3895df2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,13 +4,18 @@ Changelog 0.5 (unreleased) ---------------- + +- Convert ``self.fail()`` to ``pytest.fail()`` (`#39`__). + - Python >=3.9 is now required. - Allow non-string keys when translating ``assertDictContainsSubset`` (`#54`_). +.. _#39: https://github.com/pytest-dev/unittest2pytest/issues/39 .. _#54: https://github.com/pytest-dev/unittest2pytest/issues/54 + 0.4 (2019-06-30) ---------------- diff --git a/tests/fixtures/self_assert/fail_in.py b/tests/fixtures/self_assert/fail_in.py new file mode 100644 index 0000000..c15e5b3 --- /dev/null +++ b/tests/fixtures/self_assert/fail_in.py @@ -0,0 +1,18 @@ +# required-method: fail + +class TestAssertTrue(TestCase): + def test_me(self): + self.fail(xxx+y) + self.fail(aaa % bbb) + self.fail(ccc or ddd) + + def test_everybody(self): + self.fail( 'abc' ) + + def test_message(self): + self.fail(msg='This is wrong!') + self.fail(error_message) + + def test_nothing(self): + self.fail() + self.fail(self.fail()) diff --git a/tests/fixtures/self_assert/fail_out.py b/tests/fixtures/self_assert/fail_out.py new file mode 100644 index 0000000..52d3be6 --- /dev/null +++ b/tests/fixtures/self_assert/fail_out.py @@ -0,0 +1,19 @@ +# required-method: fail + +import pytest +class TestAssertTrue(TestCase): + def test_me(self): + pytest.fail(xxx+y) + pytest.fail(aaa % bbb) + pytest.fail(ccc or ddd) + + def test_everybody(self): + pytest.fail( 'abc' ) + + def test_message(self): + pytest.fail(msg='This is wrong!') + pytest.fail(error_message) + + def test_nothing(self): + pytest.fail() + pytest.fail(pytest.fail()) diff --git a/unittest2pytest/fixes/fix_self_assert.py b/unittest2pytest/fixes/fix_self_assert.py index 0e96a9f..81a28ce 100644 --- a/unittest2pytest/fixes/fix_self_assert.py +++ b/unittest2pytest/fixes/fix_self_assert.py @@ -200,6 +200,10 @@ def RaisesRegexOp(context, designator, exceptionClass, expected_regex, else: return Node(syms.suite, [with_stmt]) +def FailOp(indent, kws, arglist, node): + new = node.clone() + new.set_child(0, Name('pytest')) + return new def add_import(import_name, node): suite = get_parent_of_type(node, syms.suite) @@ -290,6 +294,8 @@ def get_import_nodes(node): 'assertRaisesRegex': partial(RaisesRegexOp, 'pytest.raises', 'excinfo'), 'assertWarnsRegex': partial(RaisesRegexOp, 'pytest.warns', 'record'), + 'fail': FailOp, + #'assertLogs': -- not to be handled here, is an context handler only } @@ -376,7 +382,7 @@ class FixSelfAssert(BaseFix): PATTERN = """ power< 'self' trailer< '.' method=( %s ) > - trailer< '(' arglist=any ')' > + trailer< '(' [arglist=any] ')' > > """ % ' | '.join(map(repr, (set(_method_map.keys()) | set(_method_aliases.keys())))) @@ -422,8 +428,10 @@ def process_arg(arg): posargs = [] kwargs = {} - # This is either a "arglist" or a single argument - if results['arglist'].type == syms.arglist: + # This is either empty, an "arglist", or a single argument + if 'arglist' not in results: + pass + elif results['arglist'].type == syms.arglist: for arg in results['arglist'].children: process_arg(arg) else: @@ -437,17 +445,17 @@ def process_arg(arg): required_args, argsdict = utils.resolve_func_args(test_func, posargs, kwargs) - if method.startswith(('assertRaises', 'assertWarns')): + if method.startswith(('assertRaises', 'assertWarns')) or method == 'fail': n_stmt = _method_map[method](*required_args, indent=find_indentation(node), kws=argsdict, - arglist=results['arglist'], + arglist=results.get('arglist'), node=node) else: n_stmt = Node(syms.assert_stmt, [Name('assert'), _method_map[method](*required_args, kws=argsdict)]) - if argsdict.get('msg', None) is not None: + if argsdict.get('msg', None) is not None and method != 'fail': n_stmt.children.extend((Name(','), argsdict['msg'])) def fix_line_wrapping(x): @@ -463,7 +471,7 @@ def fix_line_wrapping(x): n_stmt.prefix = node.prefix # add necessary imports - if 'Raises' in method or 'Warns' in method: + if 'Raises' in method or 'Warns' in method or method == 'fail': add_import('pytest', node) if ('Regex' in method and not 'Raises' in method and not 'Warns' in method):