diff --git a/testing_support/auto_stub.py b/testing_support/auto_stub.py deleted file mode 100644 index a47a8b244..000000000 --- a/testing_support/auto_stub.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (c) 2011 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -__version__ = '1.0' - -import collections -import inspect -import unittest - - -class AutoStubMixIn(object): - """Automatically restores stubbed functions on unit test teardDown. - - It's an extremely lightweight mocking class that doesn't require bookeeping. - """ - _saved = None - - def mock(self, obj, member, mock): - self._saved = self._saved or collections.OrderedDict() - old_value = self._saved.setdefault( - obj, collections.OrderedDict()).setdefault(member, getattr(obj, member)) - setattr(obj, member, mock) - return old_value - - def tearDown(self): - """Restore all the mocked members.""" - if self._saved: - for obj, items in self._saved.items(): - for member, previous_value in items.items(): - setattr(obj, member, previous_value) - - -class SimpleMock(object): - """Really simple manual class mock.""" - def __init__(self, unit_test): - """Do not call __init__ if you want to use the global call list to detect - ordering across different instances. - """ - self.calls = [] - self.unit_test = unit_test - self.assertEqual = unit_test.assertEqual - - def pop_calls(self): - """Returns the list of calls up to date. - - Good to do self.assertEqual(expected, mock.pop_calls()). - """ - calls = self.calls - self.calls = [] - return calls - - def check_calls(self, expected): - self.assertEqual(expected, self.pop_calls()) - - def _register_call(self, *args, **kwargs): - """Registers the name of the caller function.""" - caller_name = kwargs.pop('caller_name', None) or inspect.stack()[1][3] - str_args = ', '.join(repr(arg) for arg in args) - str_kwargs = ', '.join('%s=%r' % (k, v) for k, v in kwargs.items()) - self.calls.append('%s(%s)' % ( - caller_name, ', '.join(filter(None, [str_args, str_kwargs])))) - - -class TestCase(unittest.TestCase, AutoStubMixIn): - """Adds self.mock() and self.has_failed() to a TestCase.""" - def tearDown(self): - AutoStubMixIn.tearDown(self) - unittest.TestCase.tearDown(self) - - def has_failed(self): - """Returns True if the test has failed.""" - if not self._resultForDoCleanups: - # Maybe skipped. - return False - return not self._resultForDoCleanups.wasSuccessful() diff --git a/tests/git_cl_test.py b/tests/git_cl_test.py index c68ede26e..64a729e87 100755 --- a/tests/git_cl_test.py +++ b/tests/git_cl_test.py @@ -26,8 +26,6 @@ else: sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from testing_support.auto_stub import TestCase - import metrics # We have to disable monitoring before importing git_cl. metrics.DISABLE_METRICS_COLLECTION = True @@ -393,7 +391,8 @@ class TestGitClBasic(unittest.TestCase): 'Cr-Commit-Position: refs/heads/branch@{#2}\n' 'Cr-Branched-From: somehash-refs/heads/master@{#12}') - def test_valid_accounts(self): + @mock.patch('gerrit_util.GetAccountDetails') + def test_valid_accounts(self, mockGetAccountDetails): mock_per_account = { 'u1': None, # 404, doesn't exist. 'u2': { @@ -412,13 +411,9 @@ class TestGitClBasic(unittest.TestCase): raise v return v - original = git_cl.gerrit_util.GetAccountDetails - try: - git_cl.gerrit_util.GetAccountDetails = GetAccountDetailsMock - actual = git_cl.gerrit_util.ValidAccounts( - 'host', ['u1', 'u2', 'u3'], max_threads=1) - finally: - git_cl.gerrit_util.GetAccountDetails = original + mockGetAccountDetails.side_effect = GetAccountDetailsMock + actual = git_cl.gerrit_util.ValidAccounts( + 'host', ['u1', 'u2', 'u3'], max_threads=1) self.assertEqual(actual, { 'u2': { '_account_id': 123124, @@ -477,11 +472,13 @@ class TestParseIssueURL(unittest.TestCase): -class GitCookiesCheckerTest(TestCase): +class GitCookiesCheckerTest(unittest.TestCase): def setUp(self): super(GitCookiesCheckerTest, self).setUp() self.c = git_cl._GitCookiesChecker() self.c._all_hosts = [] + mock.patch('sys.stdout', StringIO()).start() + self.addCleanup(mock.patch.stopall) def mock_hosts_creds(self, subhost_identity_pairs): def ensure_googlesource(h): @@ -543,15 +540,14 @@ class GitCookiesCheckerTest(TestCase): def test_report_no_problems(self): self.test_analysis_nothing() - self.mock(sys, 'stdout', StringIO()) self.assertFalse(self.c.find_and_report_problems()) self.assertEqual(sys.stdout.getvalue(), '') - def test_report(self): + @mock.patch( + 'git_cl.gerrit_util.CookiesAuthenticator.get_gitcookies_path', + return_value='~/.gitcookies') + def test_report(self, *_mocks): self.test_analysis() - self.mock(sys, 'stdout', StringIO()) - self.mock(git_cl.gerrit_util.CookiesAuthenticator, 'get_gitcookies_path', - classmethod(lambda _: '~/.gitcookies')) self.assertTrue(self.c.find_and_report_problems()) with open(os.path.join(os.path.dirname(__file__), 'git_cl_creds_check_report.txt')) as f: @@ -562,62 +558,78 @@ class GitCookiesCheckerTest(TestCase): self.assertEqual(by_line(sys.stdout.getvalue().strip()), by_line(expected)) -class TestGitCl(TestCase): +class TestGitCl(unittest.TestCase): def setUp(self): super(TestGitCl, self).setUp() self.calls = [] self._calls_done = [] - self.mock(git_cl, 'time_time', - lambda: self._mocked_call('time.time')) - self.mock(git_cl.metrics.collector, 'add_repeated', - lambda *a: self._mocked_call('add_repeated', *a)) - self.mock(subprocess2, 'call', self._mocked_call) - self.mock(subprocess2, 'check_call', self._mocked_call) - self.mock(subprocess2, 'check_output', self._mocked_call) - self.mock(subprocess2, 'communicate', - lambda *a, **kw: ([self._mocked_call(*a, **kw), ''], 0)) - self.mock(git_cl.gclient_utils, 'CheckCallAndFilter', self._mocked_call) - self.mock(git_common, 'is_dirty_git_tree', lambda x: False) - self.mock(git_common, 'get_or_create_merge_base', - lambda *a: ( - self._mocked_call(['get_or_create_merge_base'] + list(a)))) - self.mock(git_cl, 'BranchExists', lambda _: True) - self.mock(git_cl, 'FindCodereviewSettingsFile', lambda: '') - self.mock(git_cl, 'SaveDescriptionBackup', lambda _: - self._mocked_call('SaveDescriptionBackup')) - self.mock(git_cl, 'ask_for_data', lambda *a, **k: self._mocked_call( - *(['ask_for_data'] + list(a)), **k)) - self.mock(git_cl, 'write_json', lambda path, contents: - self._mocked_call('write_json', path, contents)) - self.mock(git_cl.presubmit_support, 'DoPresubmitChecks', PresubmitMock) - self.mock(git_cl.watchlists, 'Watchlists', WatchlistsMock) - self.mock(git_cl.auth, 'Authenticator', AuthenticatorMock) - self.mock(git_cl.gerrit_util, 'GetChangeDetail', - lambda *args, **kwargs: self._mocked_call( - 'GetChangeDetail', *args, **kwargs)) - self.mock(git_cl.gerrit_util, 'GetChangeComments', - lambda *args, **kwargs: self._mocked_call( - 'GetChangeComments', *args, **kwargs)) - self.mock(git_cl.gerrit_util, 'GetChangeRobotComments', - lambda *args, **kwargs: self._mocked_call( - 'GetChangeRobotComments', *args, **kwargs)) - self.mock(git_cl.gerrit_util, 'AddReviewers', - lambda h, i, reviewers, ccs, notify: self._mocked_call( - 'AddReviewers', h, i, reviewers, ccs, notify)) - self.mock(git_cl.gerrit_util, 'SetReview', - lambda h, i, msg=None, labels=None, notify=None: - self._mocked_call('SetReview', h, i, msg, labels, notify)) - self.mock(git_cl.gerrit_util.LuciContextAuthenticator, 'is_luci', - staticmethod(lambda: False)) - self.mock(git_cl.gerrit_util.GceAuthenticator, 'is_gce', - classmethod(lambda _: False)) - self.mock(git_cl.gerrit_util, 'ValidAccounts', - lambda host, accounts: - self._mocked_call('ValidAccounts', host, accounts)) - self.mock(git_cl, 'DieWithError', - lambda msg, change=None: self._mocked_call(['DieWithError', msg])) + mock.patch('sys.stdout', StringIO()).start() + mock.patch( + 'git_cl.time_time', + lambda: self._mocked_call('time.time')).start() + mock.patch( + 'git_cl.metrics.collector.add_repeated', + lambda *a: self._mocked_call('add_repeated', *a)).start() + mock.patch('subprocess2.call', self._mocked_call).start() + mock.patch('subprocess2.check_call', self._mocked_call).start() + mock.patch('subprocess2.check_output', self._mocked_call).start() + mock.patch( + 'subprocess2.communicate', + lambda *a, **_k: ([self._mocked_call(*a), ''], 0)).start() + mock.patch( + 'git_cl.gclient_utils.CheckCallAndFilter', + self._mocked_call).start() + mock.patch('git_common.is_dirty_git_tree', lambda x: False).start() + mock.patch( + 'git_common.get_or_create_merge_base', + lambda *a: self._mocked_call('get_or_create_merge_base', *a)).start() + mock.patch('git_cl.BranchExists', return_value=True).start() + mock.patch('git_cl.FindCodereviewSettingsFile', return_value='').start() + mock.patch( + 'git_cl.SaveDescriptionBackup', + lambda _: self._mocked_call('SaveDescriptionBackup')).start() + mock.patch( + 'git_cl.ask_for_data', + lambda prompt: self._mocked_call('ask_for_data', prompt)).start() + mock.patch( + 'git_cl.write_json', + lambda *a: self._mocked_call('write_json', *a)).start() + mock.patch( + 'git_cl.presubmit_support.DoPresubmitChecks', PresubmitMock).start() + mock.patch('git_cl.watchlists.Watchlists', WatchlistsMock).start() + mock.patch('git_cl.auth.Authenticator', AuthenticatorMock).start() + mock.patch( + 'git_cl.gerrit_util.GetChangeDetail', + lambda *a: self._mocked_call('GetChangeDetail', *a)).start() + mock.patch( + 'git_cl.gerrit_util.GetChangeComments', + lambda *a: self._mocked_call('GetChangeComments', *a)).start() + mock.patch( + 'git_cl.gerrit_util.GetChangeRobotComments', + lambda *a: self._mocked_call('GetChangeRobotComments', *a)).start() + mock.patch( + 'git_cl.gerrit_util.AddReviewers', + lambda *a: self._mocked_call('AddReviewers', *a)).start() + mock.patch( + 'git_cl.gerrit_util.SetReview', + lambda h, i, msg=None, labels=None, notify=None, ready=None: ( + self._mocked_call( + 'SetReview', h, i, msg, labels, notify, ready))).start() + mock.patch( + 'git_cl.gerrit_util.LuciContextAuthenticator.is_luci', + return_value=False).start() + mock.patch( + 'git_cl.gerrit_util.GceAuthenticator.is_gce', + return_value=False).start() + mock.patch( + 'git_cl.gerrit_util.ValidAccounts', + lambda *a: self._mocked_call('ValidAccounts', *a)).start() + mock.patch( + 'git_cl.DieWithError', + lambda msg, change=None: self._mocked_call('DieWithError', msg)).start() # It's important to reset settings to not have inter-tests interference. git_cl.settings = None + self.addCleanup(mock.patch.stopall) def tearDown(self): try: @@ -799,8 +811,8 @@ class TestGitCl(TestCase): calls += [ ((['git', 'config', 'branch.master.merge'],), 'refs/heads/master'), ((['git', 'config', 'branch.master.remote'],), 'origin'), - ((['get_or_create_merge_base', 'master', - 'refs/remotes/origin/master'],), ancestor_revision), + (('get_or_create_merge_base', 'master', 'refs/remotes/origin/master'), + ancestor_revision), ] # Calls to verify branch point is ancestor @@ -962,8 +974,7 @@ class TestGitCl(TestCase): if custom_cl_base is None: calls += [ - ((['get_or_create_merge_base', 'master', - 'refs/remotes/origin/master'],), + (('get_or_create_merge_base', 'master', 'refs/remotes/origin/master'), 'origin/master'), ] parent = 'origin/master' @@ -1224,26 +1235,25 @@ class TestGitCl(TestCase): reviewers = reviewers or [] cc = cc or [] - self.mock(git_cl.sys, 'stdout', StringIO()) - self.mock(git_cl.gerrit_util, 'CookiesAuthenticator', + mock.patch('git_cl.gerrit_util.CookiesAuthenticator', CookiesAuthenticatorMockFactory( - same_auth=('git-owner.example.com', '', 'pass'))) - self.mock(git_cl.Changelist, '_GerritCommitMsgHookCheck', - lambda _, offer_removal: None) - self.mock(git_cl.gclient_utils, 'RunEditor', - lambda *_, **__: self._mocked_call(['RunEditor'])) - self.mock(git_cl, 'DownloadGerritHook', lambda force: self._mocked_call( - 'DownloadGerritHook', force)) - self.mock(git_cl.gclient_utils, 'FileRead', - lambda path: self._mocked_call(['FileRead', path])) - self.mock(git_cl.gclient_utils, 'FileWrite', + same_auth=('git-owner.example.com', '', 'pass'))).start() + mock.patch('git_cl.Changelist._GerritCommitMsgHookCheck', + lambda _, offer_removal: None).start() + mock.patch('git_cl.gclient_utils.RunEditor', + lambda *_, **__: self._mocked_call(['RunEditor'])).start() + mock.patch('git_cl.DownloadGerritHook', lambda force: self._mocked_call( + 'DownloadGerritHook', force)).start() + mock.patch('git_cl.gclient_utils.FileRead', + lambda path: self._mocked_call(['FileRead', path])).start() + mock.patch('git_cl.gclient_utils.FileWrite', lambda path, contents: self._mocked_call( - ['FileWrite', path, contents])) - self.mock(git_cl, 'datetime_now', - lambda: datetime.datetime(2017, 3, 16, 20, 0, 41, 0)) - self.mock(git_cl.tempfile, 'mkdtemp', lambda: 'TEMP_DIR') - self.mock(git_cl, 'TRACES_DIR', 'TRACES_DIR') - self.mock(git_cl, 'TRACES_README_FORMAT', + ['FileWrite', path, contents])).start() + mock.patch('git_cl.datetime_now', + lambda: datetime.datetime(2017, 3, 16, 20, 0, 41, 0)).start() + mock.patch('git_cl.tempfile.mkdtemp', lambda: 'TEMP_DIR').start() + mock.patch('git_cl.TRACES_DIR', 'TRACES_DIR').start() + mock.patch('git_cl.TRACES_README_FORMAT', '%(now)s\n' '%(gerrit_host)s\n' '%(change_id)s\n' @@ -1251,11 +1261,12 @@ class TestGitCl(TestCase): '%(description)s\n' '%(execution_time)s\n' '%(exit_code)s\n' - '%(trace_name)s') - self.mock(git_cl.shutil, 'make_archive', - lambda *args: self._mocked_call(['make_archive'] + list(args))) - self.mock(os.path, 'isfile', - lambda path: self._mocked_call(['os.path.isfile', path])) + '%(trace_name)s').start() + mock.patch('git_cl.shutil.make_archive', + lambda *args: self._mocked_call(['make_archive'] + + list(args))).start() + mock.patch('os.path.isfile', + lambda path: self._mocked_call(['os.path.isfile', path])).start() self.calls = self._gerrit_base_calls( issue=issue, @@ -1266,9 +1277,11 @@ class TestGitCl(TestCase): short_hostname=short_hostname, change_id=change_id) if fetched_status != 'ABANDONED': - self.mock(tempfile, 'NamedTemporaryFile', MakeNamedTemporaryFileMock( - self, expected_content=description)) - self.mock(os, 'remove', lambda _: True) + mock.patch( + 'tempfile.NamedTemporaryFile', + MakeNamedTemporaryFileMock( + self, expected_content=description)).start() + mock.patch('os.remove', return_value=True).start() self.calls += self._gerrit_upload_calls( description, reviewers, squash, squash_mode=squash_mode, @@ -1339,7 +1352,6 @@ class TestGitCl(TestCase): change_id='I123456789') def test_gerrit_patchset_title_special_chars(self): - self.mock(git_cl.sys, 'stdout', StringIO()) self._run_gerrit_upload_test( ['-f', '-t', 'We\'ll escape ^_ ^ special chars...@{u}'], 'desc ✔\n\nBUG=\n\nChange-Id: I123456789', @@ -1397,8 +1409,8 @@ class TestGitCl(TestCase): change_id='Ixxx') def test_gerrit_reviewer_multiple(self): - self.mock(git_cl.gerrit_util, 'GetCodeReviewTbrScore', - lambda *a: self._mocked_call('GetCodeReviewTbrScore', *a)) + mock.patch('git_cl.gerrit_util.GetCodeReviewTbrScore', + lambda *a: self._mocked_call('GetCodeReviewTbrScore', *a)).start() self._run_gerrit_upload_test( [], 'desc ✔\nTBR=reviewer@example.com\nBUG=\nR=another@example.com\n' @@ -1470,8 +1482,6 @@ class TestGitCl(TestCase): original_title='User input') def test_gerrit_upload_squash_reupload_to_abandoned(self): - self.mock(git_cl, 'DieWithError', - lambda msg, change=None: self._mocked_call('DieWithError', msg)) description = 'desc ✔\nBUG=\n\nChange-Id: 123456789' with self.assertRaises(SystemExitMock): self._run_gerrit_upload_test( @@ -1484,9 +1494,10 @@ class TestGitCl(TestCase): fetched_status='ABANDONED', change_id='123456789') - def test_gerrit_upload_squash_reupload_to_not_owned(self): - self.mock(git_cl.gerrit_util, 'GetAccountDetails', - lambda *_, **__: {'email': 'yet-another@example.com'}) + @mock.patch( + 'gerrit_util.GetAccountDetails', + return_value={'email': 'yet-another@example.com'}) + def test_gerrit_upload_squash_reupload_to_not_owned(self, _mock): description = 'desc ✔\nBUG=\n\nChange-Id: 123456789' self._run_gerrit_upload_test( ['--squash'], @@ -1502,7 +1513,7 @@ class TestGitCl(TestCase): 'WARNING: Change 123456 is owned by other@example.com, but you ' 'authenticate to Gerrit as yet-another@example.com.\n' 'Uploading may fail due to lack of permissions', - git_cl.sys.stdout.getvalue()) + sys.stdout.getvalue()) def test_upload_change_description_editor(self): fetched_description = 'foo\n\nChange-Id: 123456789' @@ -1519,8 +1530,10 @@ class TestGitCl(TestCase): original_title='User input', edit_description=description) - def test_upload_branch_deps(self): - self.mock(git_cl.sys, 'stdout', StringIO()) + @mock.patch('git_cl.RunGit') + @mock.patch('git_cl.CMDupload') + @mock.patch('git_cl.ask_for_data') + def test_upload_branch_deps(self, *_mocks): def mock_run_git(*args, **_kwargs): if args[0] == ['for-each-ref', '--format=%(refname:short) %(upstream:short)', @@ -1539,21 +1552,8 @@ class TestGitCl(TestCase): 'test7', # test7 ] return '\n'.join(branch_deps) - self.mock(git_cl, 'RunGit', mock_run_git) - - class RecordCalls: - times_called = 0 - record_calls = RecordCalls() - def mock_CMDupload(*args, **_kwargs): - record_calls.times_called += 1 - return 0 - self.mock(git_cl, 'CMDupload', mock_CMDupload) - - self.calls = [ - (('ask_for_data', 'This command will checkout all dependent branches ' - 'and run "git cl upload". Press Enter to continue, ' - 'or Ctrl+C to abort'), ''), - ] + git_cl.RunGit.side_effect = mock_run_git + git_cl.CMDupload.return_value = 0 class MockChangelist(): def __init__(self): @@ -1569,7 +1569,11 @@ class TestGitCl(TestCase): ret = git_cl.upload_branch_deps(MockChangelist(), []) # CMDupload should have been called 5 times because of 5 dependent branches. - self.assertEqual(5, record_calls.times_called) + self.assertEqual(5, len(git_cl.CMDupload.mock_calls)) + git_cl.ask_for_data.assert_called_once_with( + 'This command will checkout all dependent branches ' + 'and run "git cl upload". Press Enter to continue, ' + 'or Ctrl+C to abort') self.assertEqual(0, ret) def test_gerrit_change_id(self): @@ -1744,9 +1748,9 @@ class TestGitCl(TestCase): 'refs/remotes/branch-heads/123', branch)) - def test_patch_when_dirty(self): + @mock.patch('git_common.is_dirty_git_tree', return_value=True) + def test_patch_when_dirty(self, *_mocks): # Patch when local tree is dirty. - self.mock(git_common, 'is_dirty_git_tree', lambda x: True) self.assertNotEqual(git_cl.main(['patch', '123456']), 0) @staticmethod @@ -1780,8 +1784,7 @@ class TestGitCl(TestCase): detect_gerrit_server=False, actual_codereview=None, codereview_in_url=False): - self.mock(git_cl.sys, 'stdout', StringIO()) - self.mock(git_cl, 'IsGitVersionAtLeast', lambda *args: True) + mock.patch('git_cl.IsGitVersionAtLeast', return_value=True).start() if new_branch: self.calls = [((['git', 'new-branch', 'master'],), '')] @@ -1932,18 +1935,16 @@ class TestGitCl(TestCase): ((['git', 'fetch', 'https://chromium.googlesource.com/my/repo', 'refs/changes/56/123456/7'],), ''), ((['git', 'cherry-pick', 'FETCH_HEAD'],), CERR1), - ((['DieWithError', 'Command "git cherry-pick FETCH_HEAD" failed.\n'],), + (('DieWithError', 'Command "git cherry-pick FETCH_HEAD" failed.\n'), SystemExitMock()), ] with self.assertRaises(SystemExitMock): git_cl.main(['patch', '123456']) - def test_patch_gerrit_not_exists(self): - - def notExists(_issue, *_, **kwargs): - raise git_cl.gerrit_util.GerritError(404, '') - self.mock(git_cl.gerrit_util, 'GetChangeDetail', notExists) - + @mock.patch( + 'git_cl.gerrit_util.GetChangeDetail', + side_effect=gerrit_util.GerritError(404, '')) + def test_patch_gerrit_not_exists(self, *_mocks): self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'master'), ((['git', 'config', 'branch.master.gerritserver'],), CERR1), @@ -1951,9 +1952,9 @@ class TestGitCl(TestCase): ((['git', 'config', 'branch.master.remote'],), 'origin'), ((['git', 'config', 'remote.origin.url'],), 'https://chromium.googlesource.com/my/repo'), - ((['DieWithError', - 'change 123456 at https://chromium-review.googlesource.com does not ' - 'exist or you have no access to it'],), SystemExitMock()), + (('DieWithError', + 'change 123456 at https://chromium-review.googlesource.com does not ' + 'exist or you have no access to it'), SystemExitMock()), ] with self.assertRaises(SystemExitMock): self.assertEqual(1, git_cl.main(['patch', '123456'])) @@ -1974,13 +1975,11 @@ class TestGitCl(TestCase): def test_checkout_not_found(self): """Tests git cl checkout .""" - self.mock(git_cl.sys, 'stdout', StringIO()) self.calls = self._checkout_calls() self.assertEqual(1, git_cl.main(['checkout', '99999'])) def test_checkout_no_branch_issues(self): """Tests git cl checkout .""" - self.mock(git_cl.sys, 'stdout', StringIO()) self.calls = [ ((['git', 'config', '--local', '--get-regexp', 'branch\\..*\\.gerritissue'], ), CERR1), @@ -1989,10 +1988,8 @@ class TestGitCl(TestCase): def _test_gerrit_ensure_authenticated_common(self, auth, skip_auth_check=False): - self.mock(git_cl.gerrit_util, 'CookiesAuthenticator', - CookiesAuthenticatorMockFactory(hosts_with_creds=auth)) - self.mock(git_cl, 'DieWithError', - lambda msg, change=None: self._mocked_call(['DieWithError', msg])) + mock.patch('git_cl.gerrit_util.CookiesAuthenticator', + CookiesAuthenticatorMockFactory(hosts_with_creds=auth)).start() self.calls = self._gerrit_ensure_auth_calls(skip_auth_check=skip_auth_check) cl = git_cl.Changelist() cl.branch = 'master' @@ -2004,16 +2001,15 @@ class TestGitCl(TestCase): 'chromium.googlesource.com': ('git-is.ok', '', 'but gerrit is missing'), }) self.calls.append( - ((['DieWithError', - 'Credentials for the following hosts are required:\n' - ' chromium-review.googlesource.com\n' - 'These are read from ~/.gitcookies (or legacy ~/.netrc)\n' - 'You can (re)generate your credentials by visiting ' - 'https://chromium-review.googlesource.com/new-password'],), ''),) + (('DieWithError', + 'Credentials for the following hosts are required:\n' + ' chromium-review.googlesource.com\n' + 'These are read from ~/.gitcookies (or legacy ~/.netrc)\n' + 'You can (re)generate your credentials by visiting ' + 'https://chromium-review.googlesource.com/new-password'), ''),) self.assertIsNone(cl.EnsureAuthenticated(force=False)) def test_gerrit_ensure_authenticated_conflict(self): - self.mock(git_cl.sys, 'stdout', StringIO()) cl = self._test_gerrit_ensure_authenticated_common(auth={ 'chromium.googlesource.com': ('git-one.example.com', None, 'secret1'), @@ -2065,10 +2061,10 @@ class TestGitCl(TestCase): 'remote': 'custom-scheme://repo'} ), None), ] - self.mock(git_cl.gerrit_util, 'CookiesAuthenticator', - CookiesAuthenticatorMockFactory(hosts_with_creds={})) - self.mock(logging, 'warning', - lambda *a: self._mocked_call('logging.warning', *a)) + mock.patch('git_cl.gerrit_util.CookiesAuthenticator', + CookiesAuthenticatorMockFactory(hosts_with_creds={})).start() + mock.patch('logging.warning', + lambda *a: self._mocked_call('logging.warning', *a)).start() cl = git_cl.Changelist() cl.branch = 'master' cl.branchref = 'refs/heads/master' @@ -2091,10 +2087,10 @@ class TestGitCl(TestCase): 'url': 'git@somehost.example:foo/bar.git'} ), None), ] - self.mock(git_cl.gerrit_util, 'CookiesAuthenticator', - CookiesAuthenticatorMockFactory(hosts_with_creds={})) - self.mock(logging, 'error', - lambda *a: self._mocked_call('logging.error', *a)) + mock.patch('git_cl.gerrit_util.CookiesAuthenticator', + CookiesAuthenticatorMockFactory(hosts_with_creds={})).start() + mock.patch('logging.error', + lambda *a: self._mocked_call('logging.error', *a)).start() cl = git_cl.Changelist() cl.branch = 'master' cl.branchref = 'refs/heads/master' @@ -2102,10 +2098,6 @@ class TestGitCl(TestCase): self.assertIsNone(cl.EnsureAuthenticated(force=False)) def _cmd_set_commit_gerrit_common(self, vote, notify=None): - self.mock(git_cl.gerrit_util, 'SetReview', - lambda h, i, labels, notify=None: - self._mocked_call(['SetReview', h, i, labels, notify])) - self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'feature'), ((['git', 'config', 'branch.feature.gerritissue'],), '123'), @@ -2115,9 +2107,9 @@ class TestGitCl(TestCase): ((['git', 'config', 'branch.feature.remote'],), 'origin'), ((['git', 'config', 'remote.origin.url'],), 'https://chromium.googlesource.com/infra/infra.git'), - ((['SetReview', 'chromium-review.googlesource.com', - 'infra%2Finfra~123', - {'Commit-Queue': vote}, notify],), ''), + (('SetReview', 'chromium-review.googlesource.com', + 'infra%2Finfra~123', None, + {'Commit-Queue': vote}, notify, None), ''), ] def test_cmd_set_commit_gerrit_clear(self): @@ -2133,49 +2125,31 @@ class TestGitCl(TestCase): self.assertEqual(0, git_cl.main(['set-commit'])) def test_description_display(self): - out = StringIO() - self.mock(git_cl.sys, 'stdout', out) - - self.mock(git_cl, 'Changelist', ChangelistMock) + mock.patch('git_cl.Changelist', ChangelistMock).start() ChangelistMock.desc = 'foo\n' self.assertEqual(0, git_cl.main(['description', '-d'])) - self.assertEqual('foo\n', out.getvalue()) + self.assertEqual('foo\n', sys.stdout.getvalue()) + @mock.patch('sys.stderr', StringIO()) def test_StatusFieldOverrideIssueMissingArgs(self): - out = StringIO() - self.mock(git_cl.sys, 'stderr', out) - try: self.assertEqual(git_cl.main(['status', '--issue', '1']), 0) except SystemExit as ex: self.assertEqual(ex.code, 2) self.assertIn( - '--field must be given when --issue is set.', out.getvalue()) - - out = StringIO() - self.mock(git_cl.sys, 'stderr', out) - - try: - self.assertEqual(git_cl.main(['status', '--issue', '1']), 0) - except SystemExit as ex: - self.assertEqual(ex.code, 2) - self.assertIn( - '--field must be given when --issue is set.', out.getvalue()) + '--field must be given when --issue is set.', sys.stderr.getvalue()) def test_StatusFieldOverrideIssue(self): - out = StringIO() - self.mock(git_cl.sys, 'stdout', out) - def assertIssue(cl_self, *_args): self.assertEqual(cl_self.issue, 1) return 'foobar' - self.mock(git_cl.Changelist, 'FetchDescription', assertIssue) + mock.patch('git_cl.Changelist.FetchDescription', assertIssue).start() self.assertEqual( git_cl.main(['status', '--issue', '1', '--field', 'desc']), 0) - self.assertEqual(out.getvalue(), 'foobar\n') + self.assertEqual(sys.stdout.getvalue(), 'foobar\n') def test_SetCloseOverrideIssue(self): @@ -2183,14 +2157,12 @@ class TestGitCl(TestCase): self.assertEqual(cl_self.issue, 1) return 'foobar' - self.mock(git_cl.Changelist, 'FetchDescription', assertIssue) - self.mock(git_cl.Changelist, 'CloseIssue', lambda *_: None) + mock.patch('git_cl.Changelist.FetchDescription', assertIssue).start() + mock.patch('git_cl.Changelist.CloseIssue', lambda *_: None).start() self.assertEqual( git_cl.main(['set-close', '--issue', '1']), 0) def test_description(self): - out = StringIO() - self.mock(git_cl.sys, 'stdout', out) self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'feature'), ((['git', 'config', 'branch.feature.merge'],), 'feature'), @@ -2210,14 +2182,11 @@ class TestGitCl(TestCase): 'description', 'https://chromium-review.googlesource.com/c/my/repo/+/123123', '-d'])) - self.assertEqual('foobar\n', out.getvalue()) + self.assertEqual('foobar\n', sys.stdout.getvalue()) def test_description_set_raw(self): - out = StringIO() - self.mock(git_cl.sys, 'stdout', out) - - self.mock(git_cl, 'Changelist', ChangelistMock) - self.mock(git_cl.sys, 'stdin', StringIO('hihi')) + mock.patch('git_cl.Changelist', ChangelistMock).start() + mock.patch('git_cl.sys.stdin', StringIO('hihi')).start() self.assertEqual(0, git_cl.main(['description', '-n', 'hihi'])) self.assertEqual('hihi', ChangelistMock.desc) @@ -2240,12 +2209,11 @@ class TestGitCl(TestCase): def UpdateDescription(_, desc, force=False): self.assertEqual(desc, 'Some.\n\nChange-Id: xxx\nBug: 123') - self.mock(git_cl.sys, 'stdout', StringIO()) - self.mock(git_cl.Changelist, 'FetchDescription', - lambda *args: current_desc) - self.mock(git_cl.Changelist, 'UpdateDescription', - UpdateDescription) - self.mock(git_cl.gclient_utils, 'RunEditor', RunEditor) + mock.patch('git_cl.Changelist.FetchDescription', + lambda *args: current_desc).start() + mock.patch('git_cl.Changelist.UpdateDescription', + UpdateDescription).start() + mock.patch('git_cl.gclient_utils.RunEditor', RunEditor).start() self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'feature'), @@ -2270,10 +2238,9 @@ class TestGitCl(TestCase): desc) return desc - self.mock(git_cl.sys, 'stdout', StringIO()) - self.mock(git_cl.Changelist, 'FetchDescription', - lambda *args: current_desc) - self.mock(git_cl.gclient_utils, 'RunEditor', RunEditor) + mock.patch('git_cl.Changelist.FetchDescription', + lambda *args: current_desc).start() + mock.patch('git_cl.gclient_utils.RunEditor', RunEditor).start() self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'feature'), @@ -2285,18 +2252,13 @@ class TestGitCl(TestCase): self.assertEqual(0, git_cl.main(['description'])) def test_description_set_stdin(self): - out = StringIO() - self.mock(git_cl.sys, 'stdout', out) - - self.mock(git_cl, 'Changelist', ChangelistMock) - self.mock(git_cl.sys, 'stdin', StringIO('hi \r\n\t there\n\nman')) + mock.patch('git_cl.Changelist', ChangelistMock).start() + mock.patch('git_cl.sys.stdin', StringIO('hi \r\n\t there\n\nman')).start() self.assertEqual(0, git_cl.main(['description', '-n', '-'])) self.assertEqual('hi\n\t there\n\nman', ChangelistMock.desc) def test_archive(self): - self.mock(git_cl.sys, 'stdout', StringIO()) - self.calls = [ ((['git', 'for-each-ref', '--format=%(refname)', 'refs/heads'],), 'refs/heads/master\nrefs/heads/foo\nrefs/heads/bar'), @@ -2306,17 +2268,15 @@ class TestGitCl(TestCase): ((['git', 'branch', '-D', 'foo'],), '') ] - self.mock(git_cl, 'get_cl_statuses', + mock.patch('git_cl.get_cl_statuses', lambda branches, fine_grained, max_processes: [(MockChangelistWithBranchAndIssue('master', 1), 'open'), (MockChangelistWithBranchAndIssue('foo', 456), 'closed'), - (MockChangelistWithBranchAndIssue('bar', 789), 'open')]) + (MockChangelistWithBranchAndIssue('bar', 789), 'open')]).start() self.assertEqual(0, git_cl.main(['archive', '-f'])) def test_archive_tag_collision(self): - self.mock(git_cl.sys, 'stdout', StringIO()) - self.calls = [ ((['git', 'for-each-ref', '--format=%(refname)', 'refs/heads'],), 'refs/heads/master\nrefs/heads/foo\nrefs/heads/bar'), @@ -2327,16 +2287,15 @@ class TestGitCl(TestCase): ((['git', 'branch', '-D', 'foo'],), '') ] - self.mock(git_cl, 'get_cl_statuses', + mock.patch('git_cl.get_cl_statuses', lambda branches, fine_grained, max_processes: [(MockChangelistWithBranchAndIssue('master', 1), 'open'), (MockChangelistWithBranchAndIssue('foo', 456), 'closed'), - (MockChangelistWithBranchAndIssue('bar', 789), 'open')]) + (MockChangelistWithBranchAndIssue('bar', 789), 'open')]).start() self.assertEqual(0, git_cl.main(['archive', '-f'])) def test_archive_current_branch_fails(self): - self.mock(git_cl.sys, 'stdout', StringIO()) self.calls = [ ((['git', 'for-each-ref', '--format=%(refname)', 'refs/heads'],), 'refs/heads/master'), @@ -2344,15 +2303,14 @@ class TestGitCl(TestCase): ((['git', 'symbolic-ref', 'HEAD'],), 'master'), ] - self.mock(git_cl, 'get_cl_statuses', + mock.patch('git_cl.get_cl_statuses', lambda branches, fine_grained, max_processes: - [(MockChangelistWithBranchAndIssue('master', 1), 'closed')]) + [(MockChangelistWithBranchAndIssue('master', 1), + 'closed')]).start() self.assertEqual(1, git_cl.main(['archive', '-f'])) def test_archive_dry_run(self): - self.mock(git_cl.sys, 'stdout', StringIO()) - self.calls = [ ((['git', 'for-each-ref', '--format=%(refname)', 'refs/heads'],), 'refs/heads/master\nrefs/heads/foo\nrefs/heads/bar'), @@ -2360,17 +2318,15 @@ class TestGitCl(TestCase): ((['git', 'symbolic-ref', 'HEAD'],), 'master') ] - self.mock(git_cl, 'get_cl_statuses', + mock.patch('git_cl.get_cl_statuses', lambda branches, fine_grained, max_processes: [(MockChangelistWithBranchAndIssue('master', 1), 'open'), (MockChangelistWithBranchAndIssue('foo', 456), 'closed'), - (MockChangelistWithBranchAndIssue('bar', 789), 'open')]) + (MockChangelistWithBranchAndIssue('bar', 789), 'open')]).start() self.assertEqual(0, git_cl.main(['archive', '-f', '--dry-run'])) def test_archive_no_tags(self): - self.mock(git_cl.sys, 'stdout', StringIO()) - self.calls = [ ((['git', 'for-each-ref', '--format=%(refname)', 'refs/heads'],), 'refs/heads/master\nrefs/heads/foo\nrefs/heads/bar'), @@ -2379,17 +2335,15 @@ class TestGitCl(TestCase): ((['git', 'branch', '-D', 'foo'],), '') ] - self.mock(git_cl, 'get_cl_statuses', + mock.patch('git_cl.get_cl_statuses', lambda branches, fine_grained, max_processes: [(MockChangelistWithBranchAndIssue('master', 1), 'open'), (MockChangelistWithBranchAndIssue('foo', 456), 'closed'), - (MockChangelistWithBranchAndIssue('bar', 789), 'open')]) + (MockChangelistWithBranchAndIssue('bar', 789), 'open')]).start() self.assertEqual(0, git_cl.main(['archive', '-f', '--notags'])) def test_archive_tag_cleanup_on_branch_deletion_error(self): - self.mock(git_cl.sys, 'stdout', StringIO()) - self.calls = [ ((['git', 'for-each-ref', '--format=%(refname)', 'refs/heads'],), 'refs/heads/master\nrefs/heads/foo\nrefs/heads/bar'), @@ -2402,17 +2356,15 @@ class TestGitCl(TestCase): 'refs/tags/git-cl-archived-456-foo'), ] - self.mock(git_cl, 'get_cl_statuses', + mock.patch('git_cl.get_cl_statuses', lambda branches, fine_grained, max_processes: [(MockChangelistWithBranchAndIssue('master', 1), 'open'), (MockChangelistWithBranchAndIssue('foo', 456), 'closed'), - (MockChangelistWithBranchAndIssue('bar', 789), 'open')]) + (MockChangelistWithBranchAndIssue('bar', 789), 'open')]).start() self.assertEqual(0, git_cl.main(['archive', '-f'])) def test_cmd_issue_erase_existing(self): - out = StringIO() - self.mock(git_cl.sys, 'stdout', out) self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'feature'), # Let this command raise exception (retcode=1) - it should be ignored. @@ -2428,10 +2380,8 @@ class TestGitCl(TestCase): self.assertEqual(0, git_cl.main(['issue', '0'])) def test_cmd_issue_erase_existing_with_change_id(self): - out = StringIO() - self.mock(git_cl.sys, 'stdout', out) - self.mock(git_cl.Changelist, 'FetchDescription', - lambda _: 'This is a description\n\nChange-Id: Ideadbeef') + mock.patch('git_cl.Changelist.FetchDescription', + lambda _: 'This is a description\n\nChange-Id: Ideadbeef').start() self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'feature'), # Let this command raise exception (retcode=1) - it should be ignored. @@ -2449,8 +2399,6 @@ class TestGitCl(TestCase): self.assertEqual(0, git_cl.main(['issue', '0'])) def test_cmd_issue_json(self): - out = StringIO() - self.mock(git_cl.sys, 'stdout', out) self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'feature'), ((['git', 'config', 'branch.feature.gerritissue'],), '123'), @@ -2464,15 +2412,14 @@ class TestGitCl(TestCase): self.assertEqual(0, git_cl.main(['issue', '--json', 'output.json'])) def _common_GerritCommitMsgHookCheck(self): - self.mock(git_cl.sys, 'stdout', StringIO()) - self.mock(git_cl.os.path, 'abspath', - lambda path: self._mocked_call(['abspath', path])) - self.mock(git_cl.os.path, 'exists', - lambda path: self._mocked_call(['exists', path])) - self.mock(git_cl.gclient_utils, 'FileRead', - lambda path: self._mocked_call(['FileRead', path])) - self.mock(git_cl.gclient_utils, 'rm_file_or_tree', - lambda path: self._mocked_call(['rm_file_or_tree', path])) + mock.patch('git_cl.os.path.abspath', + lambda path: self._mocked_call(['abspath', path])).start() + mock.patch('git_cl.os.path.exists', + lambda path: self._mocked_call(['exists', path])).start() + mock.patch('git_cl.gclient_utils.FileRead', + lambda path: self._mocked_call(['FileRead', path])).start() + mock.patch('git_cl.gclient_utils.rm_file_or_tree', + lambda path: self._mocked_call(['rm_file_or_tree', path])).start() self.calls = [ ((['git', 'rev-parse', '--show-cdup'],), '../'), ((['abspath', '../'],), '/abs/git_repo_root'), @@ -2527,21 +2474,19 @@ class TestGitCl(TestCase): 'url': 'https://git.googlesource.com/test/+/deadbeef'}], } cl.SubmitIssue = lambda wait_for_merge: None - out = StringIO() - self.mock(sys, 'stdout', out) self.assertEqual(0, cl.CMDLand(force=True, bypass_hooks=True, verbose=True, parallel=False)) self.assertIn( 'Issue chromium-review.googlesource.com/123 has been submitted', - out.getvalue()) + sys.stdout.getvalue()) self.assertIn( 'Landed as: https://git.googlesource.com/test/+/deadbeef', - out.getvalue()) + sys.stdout.getvalue()) def _mock_gerrit_changes_for_detail_cache(self): - self.mock(git_cl.Changelist, '_GetGerritHost', lambda _: 'host') + mock.patch('git_cl.Changelist._GetGerritHost', lambda _: 'host').start() def test_gerrit_change_detail_cache_simple(self): self._mock_gerrit_changes_for_detail_cache() @@ -2621,9 +2566,8 @@ class TestGitCl(TestCase): 'github.com': ('user2', None, 'pass2'), 'host2.googlesource.com': ('user3', None, 'pass'), } - self.mock(git_cl.gerrit_util, 'CookiesAuthenticator', - CookiesAuthenticatorMock) - self.mock(sys, 'stdout', StringIO()) + mock.patch('git_cl.gerrit_util.CookiesAuthenticator', + CookiesAuthenticatorMock).start() git_cl._GitCookiesChecker().print_current_creds(include_netrc=True) self.assertEqual(list(sys.stdout.getvalue().splitlines()), [ ' Host\t User\t Which file', @@ -2652,13 +2596,12 @@ class TestGitCl(TestCase): return self._mocked_call('os.path.exists', '%s/%s' % (dirname, base)) # git cl also checks for existence other files not relevant to this test. return None - self.mock(os.path, 'exists', exists_mock) - self.mock(sys, 'stdout', StringIO()) + mock.patch('os.path.exists', exists_mock).start() def test_creds_check_gitcookies_not_configured(self): self._common_creds_check_mocks() - self.mock(git_cl._GitCookiesChecker, 'get_hosts_with_creds', - lambda _, include_netrc=False: []) + mock.patch('git_cl._GitCookiesChecker.get_hosts_with_creds', + lambda _, include_netrc=False: []).start() self.calls = [ ((['git', 'config', '--path', 'http.cookiefile'],), CERR1), ((['git', 'config', '--global', 'http.cookiefile'],), CERR1), @@ -2678,8 +2621,8 @@ class TestGitCl(TestCase): def test_creds_check_gitcookies_configured_custom_broken(self): self._common_creds_check_mocks() - self.mock(git_cl._GitCookiesChecker, 'get_hosts_with_creds', - lambda _, include_netrc=False: []) + mock.patch('git_cl._GitCookiesChecker.get_hosts_with_creds', + lambda _, include_netrc=False: []).start() self.calls = [ ((['git', 'config', '--path', 'http.cookiefile'],), CERR1), ((['git', 'config', '--global', 'http.cookiefile'],), @@ -2699,9 +2642,6 @@ class TestGitCl(TestCase): sys.stdout.getvalue()) def test_git_cl_comment_add_gerrit(self): - self.mock(git_cl.gerrit_util, 'SetReview', - lambda host, change, msg, ready: - self._mocked_call('SetReview', host, change, msg, ready)) self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), CERR1), ((['git', 'symbolic-ref', 'HEAD'],), CERR1), @@ -2711,13 +2651,13 @@ class TestGitCl(TestCase): ((['git', 'config', 'remote.origin.url'],), 'https://chromium.googlesource.com/infra/infra'), (('SetReview', 'chromium-review.googlesource.com', 'infra%2Finfra~10', - 'msg', None), + 'msg', None, None, None), None), ] self.assertEqual(0, git_cl.main(['comment', '-i', '10', '-a', 'msg'])) - def test_git_cl_comments_fetch_gerrit(self): - self.mock(sys, 'stdout', StringIO()) + @mock.patch('git_cl.Changelist.GetBranch', return_value='foo') + def test_git_cl_comments_fetch_gerrit(self, *_mocks): self.calls = [ ((['git', 'config', 'branch.foo.gerritserver'],), ''), ((['git', 'config', 'branch.foo.merge'],), ''), @@ -2860,7 +2800,6 @@ class TestGitCl(TestCase): cl = git_cl.Changelist( issue=1, branchref='refs/heads/foo') self.assertEqual(cl.GetCommentsSummary(), expected_comments_summary) - self.mock(git_cl.Changelist, 'GetBranch', lambda _: 'foo') self.assertEqual( 0, git_cl.main(['comments', '-i', '1', '-j', 'output.json'])) @@ -2868,7 +2807,6 @@ class TestGitCl(TestCase): # git cl comments also fetches robot comments (which are considered a type # of autogenerated comment), and unlike other types of comments, only robot # comments from the latest patchset are shown. - self.mock(sys, 'stdout', StringIO()) self.calls = [ ((['git', 'config', 'branch.foo.gerritserver'],), ''), ((['git', 'config', 'branch.foo.merge'],), ''), @@ -2984,7 +2922,7 @@ class TestGitCl(TestCase): return self._mocked_call('os.path.isdir', path) return original_os_path_isdir(path) - self.mock(os.path, 'isdir', selective_os_path_isdir_mock) + mock.patch('os.path.isdir', selective_os_path_isdir_mock).start() url = 'https://chromium.googlesource.com/my/repo' self.calls = [ @@ -3011,9 +2949,9 @@ class TestGitCl(TestCase): return self._mocked_call('os.path.isdir', path) return original_os_path_isdir(path) - self.mock(os.path, 'isdir', selective_os_path_isdir_mock) - self.mock(logging, 'error', - lambda *a: self._mocked_call('logging.error', *a)) + mock.patch('os.path.isdir', selective_os_path_isdir_mock).start() + mock.patch('logging.error', + lambda *a: self._mocked_call('logging.error', *a)).start() self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'master'), @@ -3042,9 +2980,9 @@ class TestGitCl(TestCase): return self._mocked_call('os.path.isdir', path) return original_os_path_isdir(path) - self.mock(os.path, 'isdir', selective_os_path_isdir_mock) - self.mock(logging, 'error', - lambda *a: self._mocked_call('logging.error', *a)) + mock.patch('os.path.isdir', selective_os_path_isdir_mock).start() + mock.patch('logging.error', + lambda *a: self._mocked_call('logging.error', *a)).start() self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'master'), @@ -3080,8 +3018,8 @@ class TestGitCl(TestCase): self.assertEqual(cl._GerritChangeIdentifier(), 'my%2Frepo~123456') def test_gerrit_change_identifier_without_project(self): - self.mock(logging, 'error', - lambda *a: self._mocked_call('logging.error', *a)) + mock.patch('logging.error', + lambda *a: self._mocked_call('logging.error', *a)).start() self.calls = [ ((['git', 'symbolic-ref', 'HEAD'],), 'master'), @@ -3552,7 +3490,7 @@ class CMDUploadTestCase(CMDTestCaseBase): mock.ANY, expected_buckets, mock.ANY, 8) -class CMDFormatTestCase(TestCase): +class CMDFormatTestCase(unittest.TestCase): def setUp(self): super(CMDFormatTestCase, self).setUp()