Test:Use unittest.mock on Python 3

The mock module has been added to Python 3.3 as unittest.mock.
The third party mock module doesn't seem to be maintained anymore.
This is follow up of 72c501454e and
add hacking rule to avoid regression issue.

oslotest prepares mock for six in oslotest/__init__.py as follow:
six.add_move(six.MovedModule('mock', 'mock', 'unittest.mock')) and
oslo_messaging/tests/__init__.py imports oslotest before importing
test submodules to setup six.moves for mock, then "from six.moves
import mock" works well.

Note: unittest.mock also detects wrong usage of method
assert_called_once_with.

Change-Id: I3d09733789cfa2550cf47c24f2553357d36bcc0d
This commit is contained in:
ChangBo Guo(gcb) 2017-02-04 15:30:23 +08:00
parent f3cc165dba
commit 4f229832c0
13 changed files with 51 additions and 37 deletions

View File

@ -20,6 +20,8 @@ import six
oslo_namespace_imports_dot = re.compile(r"import[\s]+oslo[.][^\s]+") oslo_namespace_imports_dot = re.compile(r"import[\s]+oslo[.][^\s]+")
oslo_namespace_imports_from_dot = re.compile(r"from[\s]+oslo[.]") oslo_namespace_imports_from_dot = re.compile(r"from[\s]+oslo[.]")
oslo_namespace_imports_from_root = re.compile(r"from[\s]+oslo[\s]+import[\s]+") oslo_namespace_imports_from_root = re.compile(r"from[\s]+oslo[\s]+import[\s]+")
mock_imports_directly = re.compile(r"import[\s]+mock")
mock_imports_direclty_from = re.compile(r"from[\s]+mock[\s]+import[\s]+")
def check_oslo_namespace_imports(logical_line): def check_oslo_namespace_imports(logical_line):
@ -40,6 +42,17 @@ def check_oslo_namespace_imports(logical_line):
yield(0, msg) yield(0, msg)
def check_mock_imports(logical_line):
if re.match(mock_imports_directly, logical_line):
msg = ("O324: '%s' must be used instead of '%s'.") % (
logical_line.replace('import mock', 'from six.moves import mock'),
logical_line)
yield(0, msg)
elif re.match(mock_imports_direclty_from, logical_line):
msg = "O324: Use mock from six.moves."
yield(0, msg)
class BaseASTChecker(ast.NodeVisitor): class BaseASTChecker(ast.NodeVisitor):
"""Provides a simple framework for writing AST-based checks. """Provides a simple framework for writing AST-based checks.
@ -347,3 +360,4 @@ class CheckForLoggingIssues(BaseASTChecker):
def factory(register): def factory(register):
register(CheckForLoggingIssues) register(CheckForLoggingIssues)
register(check_oslo_namespace_imports) register(check_oslo_namespace_imports)
register(check_mock_imports)

View File

@ -16,5 +16,8 @@
import eventlet import eventlet
eventlet.monkey_patch() eventlet.monkey_patch()
# Import oslotest before importing test submodules to setup six.moves for mock # oslotest prepares mock for six in oslotest/__init__.py as follow:
# six.add_move(six.MovedModule('mock', 'mock', 'unittest.mock')) and
# oslo.messaging imports oslotest before importing test submodules to
# setup six.moves for mock, then "from six.moves import mock" works well.
import oslotest import oslotest

View File

@ -16,11 +16,10 @@ import functools
import unittest import unittest
from concurrent import futures from concurrent import futures
from mock import mock
from mock import patch
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from oslo_utils import timeutils from oslo_utils import timeutils
import pika import pika
from six.moves import mock
import oslo_messaging import oslo_messaging
from oslo_messaging._drivers.pika_driver import pika_commons as pika_drv_cmns from oslo_messaging._drivers.pika_driver import pika_commons as pika_drv_cmns
@ -151,8 +150,8 @@ class RpcPikaIncomingMessageTestCase(unittest.TestCase):
self.assertEqual("payload_value", self.assertEqual("payload_value",
message.message.get("payload_key", None)) message.message.get("payload_key", None))
@patch(("oslo_messaging._drivers.pika_driver.pika_message." @mock.patch(("oslo_messaging._drivers.pika_driver.pika_message."
"PikaOutgoingMessage.send")) "PikaOutgoingMessage.send"))
def test_reply_for_cast_message(self, send_reply_mock): def test_reply_for_cast_message(self, send_reply_mock):
message = pika_drv_msg.RpcPikaIncomingMessage( message = pika_drv_msg.RpcPikaIncomingMessage(
self._pika_engine, self._channel, self._method, self._properties, self._pika_engine, self._channel, self._method, self._properties,
@ -171,9 +170,9 @@ class RpcPikaIncomingMessageTestCase(unittest.TestCase):
self.assertEqual(0, send_reply_mock.call_count) self.assertEqual(0, send_reply_mock.call_count)
@patch("oslo_messaging._drivers.pika_driver.pika_message." @mock.patch("oslo_messaging._drivers.pika_driver.pika_message."
"RpcReplyPikaOutgoingMessage") "RpcReplyPikaOutgoingMessage")
@patch("tenacity.retry") @mock.patch("tenacity.retry")
def test_positive_reply_for_call_message(self, def test_positive_reply_for_call_message(self,
retry_mock, retry_mock,
outgoing_message_mock): outgoing_message_mock):
@ -206,9 +205,9 @@ class RpcPikaIncomingMessageTestCase(unittest.TestCase):
stop=mock.ANY, retry=mock.ANY, wait=mock.ANY stop=mock.ANY, retry=mock.ANY, wait=mock.ANY
) )
@patch("oslo_messaging._drivers.pika_driver.pika_message." @mock.patch("oslo_messaging._drivers.pika_driver.pika_message."
"RpcReplyPikaOutgoingMessage") "RpcReplyPikaOutgoingMessage")
@patch("tenacity.retry") @mock.patch("tenacity.retry")
def test_negative_reply_for_call_message(self, def test_negative_reply_for_call_message(self,
retry_mock, retry_mock,
outgoing_message_mock): outgoing_message_mock):
@ -319,8 +318,8 @@ class PikaOutgoingMessageTestCase(unittest.TestCase):
self._message = {"msg_type": 1, "msg_str": "hello"} self._message = {"msg_type": 1, "msg_str": "hello"}
self._context = {"request_id": 555, "token": "it is a token"} self._context = {"request_id": 555, "token": "it is a token"}
@patch("oslo_serialization.jsonutils.dump_as_bytes", @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True)) new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
def test_send_with_confirmation(self): def test_send_with_confirmation(self):
message = pika_drv_msg.PikaOutgoingMessage( message = pika_drv_msg.PikaOutgoingMessage(
self._pika_engine, self._message, self._context self._pika_engine, self._message, self._context
@ -363,8 +362,8 @@ class PikaOutgoingMessageTestCase(unittest.TestCase):
self.assertEqual({'version': '1.0'}, props.headers) self.assertEqual({'version': '1.0'}, props.headers)
self.assertTrue(props.message_id) self.assertTrue(props.message_id)
@patch("oslo_serialization.jsonutils.dump_as_bytes", @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True)) new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
def test_send_without_confirmation(self): def test_send_without_confirmation(self):
message = pika_drv_msg.PikaOutgoingMessage( message = pika_drv_msg.PikaOutgoingMessage(
self._pika_engine, self._message, self._context self._pika_engine, self._message, self._context
@ -421,8 +420,8 @@ class RpcPikaOutgoingMessageTestCase(unittest.TestCase):
self._message = {"msg_type": 1, "msg_str": "hello"} self._message = {"msg_type": 1, "msg_str": "hello"}
self._context = {"request_id": 555, "token": "it is a token"} self._context = {"request_id": 555, "token": "it is a token"}
@patch("oslo_serialization.jsonutils.dump_as_bytes", @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True)) new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
def test_send_cast_message(self): def test_send_cast_message(self):
message = pika_drv_msg.RpcPikaOutgoingMessage( message = pika_drv_msg.RpcPikaOutgoingMessage(
self._pika_engine, self._message, self._context self._pika_engine, self._message, self._context
@ -467,8 +466,8 @@ class RpcPikaOutgoingMessageTestCase(unittest.TestCase):
self.assertIsNone(props.reply_to) self.assertIsNone(props.reply_to)
self.assertTrue(props.message_id) self.assertTrue(props.message_id)
@patch("oslo_serialization.jsonutils.dump_as_bytes", @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True)) new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
def test_send_call_message(self): def test_send_call_message(self):
message = pika_drv_msg.RpcPikaOutgoingMessage( message = pika_drv_msg.RpcPikaOutgoingMessage(
self._pika_engine, self._message, self._context self._pika_engine, self._message, self._context
@ -542,8 +541,8 @@ class RpcReplyPikaOutgoingMessageTestCase(unittest.TestCase):
self._msg_id = 12345567 self._msg_id = 12345567
@patch("oslo_serialization.jsonutils.dump_as_bytes", @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True)) new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
def test_success_message_send(self): def test_success_message_send(self):
message = pika_drv_msg.RpcReplyPikaOutgoingMessage( message = pika_drv_msg.RpcReplyPikaOutgoingMessage(
self._pika_engine, self._msg_id, reply="all_fine" self._pika_engine, self._msg_id, reply="all_fine"
@ -571,9 +570,9 @@ class RpcReplyPikaOutgoingMessageTestCase(unittest.TestCase):
self.assertIsNone(props.reply_to) self.assertIsNone(props.reply_to)
self.assertTrue(props.message_id) self.assertTrue(props.message_id)
@patch("traceback.format_exception", new=lambda x, y, z: z) @mock.patch("traceback.format_exception", new=lambda x, y, z: z)
@patch("oslo_serialization.jsonutils.dump_as_bytes", @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True)) new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
def test_failure_message_send(self): def test_failure_message_send(self):
failure_info = (oslo_messaging.MessagingException, failure_info = (oslo_messaging.MessagingException,
oslo_messaging.MessagingException("Error message"), oslo_messaging.MessagingException("Error message"),

View File

@ -17,7 +17,7 @@ import time
import unittest import unittest
from concurrent import futures from concurrent import futures
import mock from six.moves import mock
from oslo_messaging._drivers.pika_driver import pika_exceptions as pika_drv_exc from oslo_messaging._drivers.pika_driver import pika_exceptions as pika_drv_exc
from oslo_messaging._drivers.pika_driver import pika_poller from oslo_messaging._drivers.pika_driver import pika_poller

View File

@ -13,7 +13,7 @@
# under the License. # under the License.
import kafka import kafka
import kafka.errors import kafka.errors
import mock from six.moves import mock
import testscenarios import testscenarios
import oslo_messaging import oslo_messaging
@ -117,7 +117,7 @@ class TestKafkaDriver(test_utils.BaseTestCase):
self.driver.listeners.extend(listeners) self.driver.listeners.extend(listeners)
self.driver.cleanup() self.driver.cleanup()
for listener in listeners: for listener in listeners:
listener.close.assert_called_once() listener.close.assert_called_once_with()
class TestKafkaConnection(test_utils.BaseTestCase): class TestKafkaConnection(test_utils.BaseTestCase):

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import mock from six.moves import mock
import testtools import testtools
import time import time

View File

@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import mock from six.moves import mock
import testtools import testtools
from oslo_messaging._drivers.zmq_driver.poller import green_poller from oslo_messaging._drivers.zmq_driver.poller import green_poller

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import mock from six.moves import mock
import testtools import testtools
import oslo_messaging import oslo_messaging

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import mock from six.moves import mock
from oslo_messaging.tests import utils as test_utils from oslo_messaging.tests import utils as test_utils

View File

@ -13,9 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import mock
from oslo_config import cfg from oslo_config import cfg
from six.moves import mock
import testscenarios import testscenarios
import oslo_messaging import oslo_messaging

View File

@ -17,9 +17,9 @@ import eventlet
import threading import threading
from oslo_config import cfg from oslo_config import cfg
from six.moves import mock
import testscenarios import testscenarios
import mock
import oslo_messaging import oslo_messaging
from oslo_messaging import rpc from oslo_messaging import rpc
from oslo_messaging.rpc import server as rpc_server_module from oslo_messaging.rpc import server as rpc_server_module

View File

@ -12,11 +12,10 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from six.moves import mock
import stevedore import stevedore
import testtools import testtools
import mock
from oslo_messaging import server from oslo_messaging import server
try: try:
from oslo_messaging import opts from oslo_messaging import opts

View File

@ -14,9 +14,9 @@
# under the License. # under the License.
import fixtures import fixtures
import mock
from oslo_config import cfg from oslo_config import cfg
import six import six
from six.moves import mock
from stevedore import driver from stevedore import driver
import testscenarios import testscenarios