From 1654b77ca0febbe047a56cdce59e14755064b3e6 Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Sun, 14 Oct 2018 19:13:00 +0300 Subject: [PATCH 01/13] [#3191] Set up tests to confirm warnings --- testing/test_warnings.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 53d9c71cd..9dbe7f0d6 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -623,3 +623,38 @@ def test_removed_in_pytest4_warning_as_error(testdir, change_default): else: assert change_default in ("ini", "cmdline") result.stdout.fnmatch_lines(["* 1 passed in *"]) +class TestAssertionWarnings: + def test_tuple_warning(self, testdir): + testdir.makepyfile( + """ + def test_foo(): + assert (1,2) + """ + ) + with pytest.warns(pytest.PytestWarning): + testdir.runpytest_subprocess() + + def create_file(self, testdir, return_none): + testdir.makepyfile( + """ + def foo(return_none): + if return_none: + return None + else: + return False + + def test_foo(): + assert foo({return_none}) + """.format( + return_none=return_none + ) + ) + + def test_none_function_warns(self, testdir): + self.create_file(testdir, True) + with pytest.warns(pytest.PytestWarning): + testdir.runpytest_subprocess() + + def test_false_function_no_warn(self, testdir): + self.create_file(testdir, False) + testdir.runpytest_subprocess("-W error:PytestWarning") From 9fc9b2926f35915b6e7fd9bebe1855e47554db04 Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Mon, 15 Oct 2018 10:53:27 +0300 Subject: [PATCH 02/13] Fix tests and add aditional cases As requested by review. :ok_hand: Address code review for tests --- testing/test_warnings.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 9dbe7f0d6..ff1697502 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -624,6 +624,10 @@ def test_removed_in_pytest4_warning_as_error(testdir, change_default): assert change_default in ("ini", "cmdline") result.stdout.fnmatch_lines(["* 1 passed in *"]) class TestAssertionWarnings: + @staticmethod + def result_warns(result): + return result.stdout.fnmatch_lines(["*PytestWarning*"]) + def test_tuple_warning(self, testdir): testdir.makepyfile( """ @@ -631,10 +635,11 @@ class TestAssertionWarnings: assert (1,2) """ ) - with pytest.warns(pytest.PytestWarning): - testdir.runpytest_subprocess() + result = testdir.runpytest() + assert self.result_warns(result) - def create_file(self, testdir, return_none): + @staticmethod + def create_file(testdir, return_none): testdir.makepyfile( """ def foo(return_none): @@ -652,9 +657,27 @@ class TestAssertionWarnings: def test_none_function_warns(self, testdir): self.create_file(testdir, True) - with pytest.warns(pytest.PytestWarning): - testdir.runpytest_subprocess() + result = testdir.runpytest() + assert self.result_warns(result) + + def test_assert_is_none_no_warn(self, testdir): + """Tests a more simple case of `test_none_function_warns` where `assert None` is explicitly called""" + testdir.makepyfile( + """ + def foo(return_none): + if return_none: + return None + else: + return False + + def test_foo(): + assert foo(True) is None + """ + ) + result = testdir.runpytest() + assert not self.result_warns(result) def test_false_function_no_warn(self, testdir): self.create_file(testdir, False) - testdir.runpytest_subprocess("-W error:PytestWarning") + result = testdir.runpytest() + assert not self.result_warns(result) From 59a11b6a5d4e9a93eba71c39b9f523e2b8380f39 Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Thu, 25 Oct 2018 00:05:20 +0300 Subject: [PATCH 03/13] Check for 'assert None' and warn appropriately :bug:Fix warn ast bugs :bug:Fix inner-ast imports by using importFrom Alternetavly ast_call_helper could be retooled to use ast.attribute(...) --- src/_pytest/assertion/rewrite.py | 58 ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index d1231b774..4d04dfc1a 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -51,6 +51,19 @@ else: return ast.Call(a, b, c, None, None) +def ast_Call_helper(func_name, *args, **kwargs): + """ + func_name: str + args: Iterable[ast.expr] + kwargs: Dict[str,ast.expr] + """ + return ast.Call( + ast.Name(func_name, ast.Load()), + list(args), + [ast.keyword(key, val) for key, val in kwargs.items()], + ) + + class AssertionRewritingHook(object): """PEP302 Import hook which rewrites asserts.""" @@ -828,6 +841,12 @@ class AssertionRewriter(ast.NodeVisitor): self.push_format_context() # Rewrite assert into a bunch of statements. top_condition, explanation = self.visit(assert_.test) + # Check if directly asserting None, in order to warn [Issue #3191] + self.statements.append( + self.warn_about_none_ast( + top_condition, module_path=self.module_path, lineno=assert_.lineno + ) + ) # Create failure message. body = self.on_failure negation = ast.UnaryOp(ast.Not(), top_condition) @@ -858,6 +877,45 @@ class AssertionRewriter(ast.NodeVisitor): set_location(stmt, assert_.lineno, assert_.col_offset) return self.statements + def warn_about_none_ast(self, node, module_path, lineno): + """Returns an ast warning if node is None with the following statement: + if node is None: + from _pytest.warning_types import PytestWarning + import warnings + warnings.warn_explicit( + PytestWarning('assertion the value None, Please use "assert is None"'), + category=None, + # filename=str(self.module_path), + filename=__file__ + lineno=node.lineno, + ) + """ + + warning_msg = ast.Str( + 'Asserting the value None directly, Please use "assert is None" to eliminate ambiguity' + ) + AST_NONE = ast.NameConstant(None) + val_is_none = ast.Compare(node, [ast.Is()], [AST_NONE]) + import_warnings = ast.ImportFrom( + module="warnings", names=[ast.alias("warn_explicit", None)], level=0 + ) + import_pytest_warning = ast.ImportFrom( + module="pytest", names=[ast.alias("PytestWarning", None)], level=0 + ) + pytest_warning = ast_Call_helper("PytestWarning", warning_msg) + # This won't work because this isn't the same "self" as an AssertionRewriter! + # ast_filename = improved_ast_Call('str',ast.Attribute('self','module_path',ast.Load).module_path) + warn = ast_Call_helper( + "warn_explicit", + pytest_warning, + category=AST_NONE, + filename=ast.Str(str(module_path)), + lineno=ast.Num(lineno), + ) + return ast.If( + val_is_none, [import_warnings, import_pytest_warning, ast.Expr(warn)], [] + ) + def visit_Name(self, name): # Display the repr of the name if it's a local variable or # _should_repr_global_name() thinks it's acceptable. From e0c2ab19017d38cd957b96aff873e6fe97acbeef Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Thu, 25 Oct 2018 13:47:30 +0300 Subject: [PATCH 04/13] Fix tests not to assert a function that already asserts Maybe there should be a warning about that too? --- testing/test_warnings.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/testing/test_warnings.py b/testing/test_warnings.py index ff1697502..5369416ad 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -625,8 +625,8 @@ def test_removed_in_pytest4_warning_as_error(testdir, change_default): result.stdout.fnmatch_lines(["* 1 passed in *"]) class TestAssertionWarnings: @staticmethod - def result_warns(result): - return result.stdout.fnmatch_lines(["*PytestWarning*"]) + def assert_result_warns(result): + result.stdout.fnmatch_lines(["*PytestWarning*"]) def test_tuple_warning(self, testdir): testdir.makepyfile( @@ -636,7 +636,7 @@ class TestAssertionWarnings: """ ) result = testdir.runpytest() - assert self.result_warns(result) + self.assert_result_warns(result) @staticmethod def create_file(testdir, return_none): @@ -658,26 +658,25 @@ class TestAssertionWarnings: def test_none_function_warns(self, testdir): self.create_file(testdir, True) result = testdir.runpytest() - assert self.result_warns(result) + self.assert_result_warns(result) + @pytest.mark.xfail(strict=True) def test_assert_is_none_no_warn(self, testdir): """Tests a more simple case of `test_none_function_warns` where `assert None` is explicitly called""" testdir.makepyfile( """ - def foo(return_none): - if return_none: - return None - else: - return False + def foo(): + return None def test_foo(): - assert foo(True) is None + assert foo() is None """ ) result = testdir.runpytest() - assert not self.result_warns(result) + self.assert_result_warns(result) + @pytest.mark.xfail(strict=True) def test_false_function_no_warn(self, testdir): self.create_file(testdir, False) result = testdir.runpytest() - assert not self.result_warns(result) + self.assert_result_warns(result) From aaf7f7fcca0721941b8633e190065759818fd5ea Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Thu, 25 Oct 2018 14:09:50 +0300 Subject: [PATCH 05/13] Update changelog --- changelog/3191.feature.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/3191.feature.rst diff --git a/changelog/3191.feature.rst b/changelog/3191.feature.rst new file mode 100644 index 000000000..3eedf8dfc --- /dev/null +++ b/changelog/3191.feature.rst @@ -0,0 +1 @@ +Add warning when asserting ``None`` directly From 3e6f1fa2db20eb2fd751a778dc42dd126a9e778d Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Thu, 25 Oct 2018 15:48:39 +0300 Subject: [PATCH 06/13] Simplify warning creation by using ast.parse in py2 it's a ast.Name where in py3 it's a ast.NamedConstant Fixes namespace by using import from --- src/_pytest/assertion/rewrite.py | 40 ++++++++++++++------------------ 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 4d04dfc1a..7603eb497 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -891,30 +891,24 @@ class AssertionRewriter(ast.NodeVisitor): ) """ - warning_msg = ast.Str( - 'Asserting the value None directly, Please use "assert is None" to eliminate ambiguity' - ) - AST_NONE = ast.NameConstant(None) + # using parse because it's different between py2 py3 + AST_NONE = ast.parse("None").body[0].value val_is_none = ast.Compare(node, [ast.Is()], [AST_NONE]) - import_warnings = ast.ImportFrom( - module="warnings", names=[ast.alias("warn_explicit", None)], level=0 - ) - import_pytest_warning = ast.ImportFrom( - module="pytest", names=[ast.alias("PytestWarning", None)], level=0 - ) - pytest_warning = ast_Call_helper("PytestWarning", warning_msg) - # This won't work because this isn't the same "self" as an AssertionRewriter! - # ast_filename = improved_ast_Call('str',ast.Attribute('self','module_path',ast.Load).module_path) - warn = ast_Call_helper( - "warn_explicit", - pytest_warning, - category=AST_NONE, - filename=ast.Str(str(module_path)), - lineno=ast.Num(lineno), - ) - return ast.If( - val_is_none, [import_warnings, import_pytest_warning, ast.Expr(warn)], [] - ) + send_warning = ast.parse( + """ +from _pytest.warning_types import PytestWarning +from warnings import warn_explicit +warn_explicit( + PytestWarning('assertion the value None, Please use "assert is None"'), + category=None, + filename='{filename}', + lineno={lineno}, +) + """.format( + filename=str(module_path), lineno=lineno + ) + ).body + return ast.If(val_is_none, send_warning, []) def visit_Name(self, name): # Display the repr of the name if it's a local variable or From 26d27df6fce16904ed9fb27e27e16dc9620d9569 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 30 Oct 2018 16:15:03 -0300 Subject: [PATCH 07/13] Improve changelog message --- changelog/3191.feature.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/changelog/3191.feature.rst b/changelog/3191.feature.rst index 3eedf8dfc..d62301a0c 100644 --- a/changelog/3191.feature.rst +++ b/changelog/3191.feature.rst @@ -1 +1,11 @@ -Add warning when asserting ``None`` directly +A warning is now issued when assertions are made directly against ``None``. + +This is a common source of confusion among new users, which write:: + + assert mocked_object.assert_called_with(3, 4, 5, key='value') + +When they should write:: + + mocked_object.assert_called_with(3, 4, 5, key='value') + +Because the ``assert_called_with`` method of mock objects already executes an assertion. From e1e4b226c6aa7ea81bf18eb192a6f979275d7097 Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Mon, 5 Nov 2018 10:13:37 +0200 Subject: [PATCH 08/13] :ok_hand: Address code review Edited the changelog for extra clarity, and to fire off auto-formatting Oddly enough, keeping `filename='{filename!r}'` caused an error while collecting tests, but getting rid of the single ticks fixed it Hopefully closes #3191 --- changelog/3191.feature.rst | 9 +++++++-- src/_pytest/assertion/rewrite.py | 2 +- testing/test_warnings.py | 8 ++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/changelog/3191.feature.rst b/changelog/3191.feature.rst index d62301a0c..13d2049bf 100644 --- a/changelog/3191.feature.rst +++ b/changelog/3191.feature.rst @@ -3,9 +3,14 @@ A warning is now issued when assertions are made directly against ``None``. This is a common source of confusion among new users, which write:: assert mocked_object.assert_called_with(3, 4, 5, key='value') - -When they should write:: + +When they should write:: mocked_object.assert_called_with(3, 4, 5, key='value') Because the ``assert_called_with`` method of mock objects already executes an assertion. + +This warning will not be issued when ``None`` is explicitly checked + assert none_returning_fun() is None + +will not issue the warning diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 7603eb497..bfb81cf85 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -901,7 +901,7 @@ from warnings import warn_explicit warn_explicit( PytestWarning('assertion the value None, Please use "assert is None"'), category=None, - filename='{filename}', + filename={filename!r}, lineno={lineno}, ) """.format( diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 5369416ad..8fa1a96ef 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -623,6 +623,8 @@ def test_removed_in_pytest4_warning_as_error(testdir, change_default): else: assert change_default in ("ini", "cmdline") result.stdout.fnmatch_lines(["* 1 passed in *"]) + + class TestAssertionWarnings: @staticmethod def assert_result_warns(result): @@ -660,7 +662,6 @@ class TestAssertionWarnings: result = testdir.runpytest() self.assert_result_warns(result) - @pytest.mark.xfail(strict=True) def test_assert_is_none_no_warn(self, testdir): """Tests a more simple case of `test_none_function_warns` where `assert None` is explicitly called""" testdir.makepyfile( @@ -673,10 +674,9 @@ class TestAssertionWarnings: """ ) result = testdir.runpytest() - self.assert_result_warns(result) + result.stdout.fnmatch_lines(["*1 passed in*"]) - @pytest.mark.xfail(strict=True) def test_false_function_no_warn(self, testdir): self.create_file(testdir, False) result = testdir.runpytest() - self.assert_result_warns(result) + result.stdout.fnmatch_lines(["*1 failed in*"]) From 41031fce2fc64d36abfbbf5b140325759af94383 Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Wed, 5 Dec 2018 17:18:57 +0200 Subject: [PATCH 09/13] Address code review --- changelog/3191.feature.rst | 5 +++-- src/_pytest/assertion/rewrite.py | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/changelog/3191.feature.rst b/changelog/3191.feature.rst index 13d2049bf..4b1626eed 100644 --- a/changelog/3191.feature.rst +++ b/changelog/3191.feature.rst @@ -10,7 +10,8 @@ When they should write:: Because the ``assert_called_with`` method of mock objects already executes an assertion. -This warning will not be issued when ``None`` is explicitly checked - assert none_returning_fun() is None +This warning will not be issued when ``None`` is explicitly checked. An assertion like:: + + assert variable is None will not issue the warning diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index bfb81cf85..e819b8da2 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -885,8 +885,7 @@ class AssertionRewriter(ast.NodeVisitor): warnings.warn_explicit( PytestWarning('assertion the value None, Please use "assert is None"'), category=None, - # filename=str(self.module_path), - filename=__file__ + filename=str, lineno=node.lineno, ) """ @@ -905,7 +904,7 @@ warn_explicit( lineno={lineno}, ) """.format( - filename=str(module_path), lineno=lineno + filename=module_path.strpath, lineno=lineno ) ).body return ast.If(val_is_none, send_warning, []) From 7a7ad0c12076f5dad281bbac064b95ba48dfb24e Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Wed, 5 Dec 2018 17:47:34 +0200 Subject: [PATCH 10/13] Shorten docstring for warn_about_none_ast --- src/_pytest/assertion/rewrite.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index e819b8da2..8b5ff5ad6 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -878,16 +878,10 @@ class AssertionRewriter(ast.NodeVisitor): return self.statements def warn_about_none_ast(self, node, module_path, lineno): - """Returns an ast warning if node is None with the following statement: - if node is None: - from _pytest.warning_types import PytestWarning - import warnings - warnings.warn_explicit( - PytestWarning('assertion the value None, Please use "assert is None"'), - category=None, - filename=str, - lineno=node.lineno, - ) + """ + Returns an ast issuing a warning if the value of node is `None` + This is used to warn the user when asserting a function that asserts internally. + See issue #3191 for more details """ # using parse because it's different between py2 py3 From 8fd60483efec91cdf410afc54ce9a95d76a8a2c9 Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Wed, 5 Dec 2018 19:49:54 +0200 Subject: [PATCH 11/13] Don't insert warnings when not in a module --- src/_pytest/assertion/rewrite.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 8b5ff5ad6..90724142a 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -841,12 +841,13 @@ class AssertionRewriter(ast.NodeVisitor): self.push_format_context() # Rewrite assert into a bunch of statements. top_condition, explanation = self.visit(assert_.test) - # Check if directly asserting None, in order to warn [Issue #3191] - self.statements.append( - self.warn_about_none_ast( - top_condition, module_path=self.module_path, lineno=assert_.lineno + # If in a test module, check if directly asserting None, in order to warn [Issue #3191] + if self.module_path is not None: + self.statements.append( + self.warn_about_none_ast( + top_condition, module_path=self.module_path, lineno=assert_.lineno + ) ) - ) # Create failure message. body = self.on_failure negation = ast.UnaryOp(ast.Not(), top_condition) From 8a0ed7e2b33a33f29f81314dce587d05c6425c0a Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 5 Dec 2018 19:14:41 +0100 Subject: [PATCH 12/13] Revisit changelog entry [ci skip] --- changelog/3191.feature.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog/3191.feature.rst b/changelog/3191.feature.rst index 4b1626eed..7eb4c3a15 100644 --- a/changelog/3191.feature.rst +++ b/changelog/3191.feature.rst @@ -1,4 +1,4 @@ -A warning is now issued when assertions are made directly against ``None``. +A warning is now issued when assertions are made for ``None``. This is a common source of confusion among new users, which write:: @@ -14,4 +14,4 @@ This warning will not be issued when ``None`` is explicitly checked. An assertio assert variable is None -will not issue the warning +will not issue the warning. From 5ebacc49c630178413a38deb6e344fc07f284be3 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 5 Dec 2018 19:22:44 +0100 Subject: [PATCH 13/13] Harden tests, fix doc/msg --- src/_pytest/assertion/rewrite.py | 11 ++++++----- testing/test_warnings.py | 13 ++++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 90724142a..78b8edcd8 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -880,12 +880,13 @@ class AssertionRewriter(ast.NodeVisitor): def warn_about_none_ast(self, node, module_path, lineno): """ - Returns an ast issuing a warning if the value of node is `None` - This is used to warn the user when asserting a function that asserts internally. - See issue #3191 for more details + Returns an AST issuing a warning if the value of node is `None`. + This is used to warn the user when asserting a function that asserts + internally already. + See issue #3191 for more details. """ - # using parse because it's different between py2 py3 + # Using parse because it is different between py2 and py3. AST_NONE = ast.parse("None").body[0].value val_is_none = ast.Compare(node, [ast.Is()], [AST_NONE]) send_warning = ast.parse( @@ -893,7 +894,7 @@ class AssertionRewriter(ast.NodeVisitor): from _pytest.warning_types import PytestWarning from warnings import warn_explicit warn_explicit( - PytestWarning('assertion the value None, Please use "assert is None"'), + PytestWarning('asserting the value None, please use "assert is None"'), category=None, filename={filename!r}, lineno={lineno}, diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 8fa1a96ef..655c89f4c 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -627,8 +627,8 @@ def test_removed_in_pytest4_warning_as_error(testdir, change_default): class TestAssertionWarnings: @staticmethod - def assert_result_warns(result): - result.stdout.fnmatch_lines(["*PytestWarning*"]) + def assert_result_warns(result, msg): + result.stdout.fnmatch_lines(["*PytestWarning: %s*" % msg]) def test_tuple_warning(self, testdir): testdir.makepyfile( @@ -638,7 +638,9 @@ class TestAssertionWarnings: """ ) result = testdir.runpytest() - self.assert_result_warns(result) + self.assert_result_warns( + result, "assertion is always true, perhaps remove parentheses?" + ) @staticmethod def create_file(testdir, return_none): @@ -660,10 +662,11 @@ class TestAssertionWarnings: def test_none_function_warns(self, testdir): self.create_file(testdir, True) result = testdir.runpytest() - self.assert_result_warns(result) + self.assert_result_warns( + result, 'asserting the value None, please use "assert is None"' + ) def test_assert_is_none_no_warn(self, testdir): - """Tests a more simple case of `test_none_function_warns` where `assert None` is explicitly called""" testdir.makepyfile( """ def foo():