diff options
author | Takashi Natsume <takanattie@gmail.com> | 2020-09-28 22:35:00 +0900 |
---|---|---|
committer | Takashi Natsume <takanattie@gmail.com> | 2020-09-28 23:08:15 +0900 |
commit | 8d3c2ce92bcaf8cf777bf29fd46275572da61547 (patch) | |
tree | b13754b5b56b7607af61705da5d5212ffa6bdfb9 | |
parent | 4acc112a308d0cedd5bfc00eb0621aba99e0d910 (diff) | |
download | nova-8d3c2ce92bcaf8cf777bf29fd46275572da61547.tar.gz |
Add a hacking rule for assert_has_calls
Add the following hacking rule.
* N366: The assert_has_calls is a method rather than a variable.
Not correct: mock_method.assert_has_calls = [mock.call(0)]
Correct: mock_method.assert_has_calls([mock.call(0)])
This patch is a follow-up patch for
Id094dd90efde09b9a835d4492f4a92b8f8ad296e.
Change-Id: I892f8c23ee44f2b3518776a9705e3543f3115cae
Signed-off-by: Takashi Natsume <takanattie@gmail.com>
-rw-r--r-- | HACKING.rst | 1 | ||||
-rw-r--r-- | nova/hacking/checks.py | 17 | ||||
-rw-r--r-- | nova/tests/unit/test_hacking.py | 24 | ||||
-rw-r--r-- | tox.ini | 1 |
4 files changed, 43 insertions, 0 deletions
diff --git a/HACKING.rst b/HACKING.rst index 6678328fd2..76ff4b6c22 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -67,6 +67,7 @@ Nova Specific Commandments - [N363] Disallow ``(not_a_tuple)`` because you meant ``(a_tuple_of_one,)``. - [N364] Check non-existent mock assertion methods and attributes. - [N365] Check misuse of assertTrue/assertIsNone. +- [N366] The assert_has_calls is a method rather than a variable. Creating Unit Tests ------------------- diff --git a/nova/hacking/checks.py b/nova/hacking/checks.py index 65a63f1eb5..4bdba6991b 100644 --- a/nova/hacking/checks.py +++ b/nova/hacking/checks.py @@ -127,6 +127,8 @@ mock_attribute_re = re.compile(r"[\.\(](retrun_value)[,=\s]") # Regex for useless assertions useless_assertion_re = re.compile( r"\.((assertIsNone)\(None|(assertTrue)\((True|\d+|'.+'|\".+\")),") +# Regex for misuse of assert_has_calls +mock_assert_has_calls_re = re.compile(r"\.assert_has_calls\s?=") class BaseASTChecker(ast.NodeVisitor): @@ -922,3 +924,18 @@ def useless_assertion(logical_line, filename): match = useless_assertion_re.search(logical_line) if match: yield (0, msg % (match.group(2) or match.group(3))) + + +@core.flake8ext +def check_assert_has_calls(logical_line, filename): + """Check misuse of assert_has_calls. + + Not correct: mock_method.assert_has_calls = [mock.call(0)] + Correct: mock_method.assert_has_calls([mock.call(0)]) + + N366 + """ + msg = "N366: The assert_has_calls is a method rather than a variable." + if ('nova/tests/' in filename and + mock_assert_has_calls_re.search(logical_line)): + yield (0, msg) diff --git a/nova/tests/unit/test_hacking.py b/nova/tests/unit/test_hacking.py index 9222daa451..78b948fbb2 100644 --- a/nova/tests/unit/test_hacking.py +++ b/nova/tests/unit/test_hacking.py @@ -909,3 +909,27 @@ class HackingTestCase(test.NoDBTestCase): self._assert_has_no_errors( code, checks.useless_assertion, filename="nova/tests/unit/test_context.py") + + def test_check_assert_has_calls(self): + code = """ + mock_method.assert_has_calls = [mock.call(1)] + mock_method2.assert_has_calls = [ + mock.call(1), mock.call(2)] + """ + errors = [(x + 1, 0, 'N366') for x in range(2)] + # Check errors in 'nova/tests' directory. + self._assert_has_errors( + code, checks.check_assert_has_calls, + expected_errors=errors, filename="nova/tests/unit/test_context.py") + # Check no errors in other than 'nova/tests' directory. + self._assert_has_no_errors( + code, checks.check_assert_has_calls, + filename="nova/compute/api.py") + code = """ + mock_method.assert_has_calls([mock.call(1)]) + mock_method2.assert_has_calls([ + mock.call(1), mock.call(2)]) + """ + self._assert_has_no_errors( + code, checks.check_assert_has_calls, + filename="nova/tests/unit/test_context.py") @@ -314,6 +314,7 @@ extension = N363 = checks:did_you_mean_tuple N364 = checks:nonexistent_assertion_methods_and_attributes N365 = checks:useless_assertion + N366 = checks:check_assert_has_calls paths = ./nova/hacking |