Improve the presubmit_canned_checks testing by using a real mock and testing for more cases.

Remove a superfluous check in CheckLongLines().

Add unittest to InputApi.

Review URL: http://codereview.chromium.org/114082

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@17805 0039d316-1c4b-4281-b951-d872f2087c98
experimental/szager/collated-output
maruel@chromium.org 16 years ago
parent 79613219a3
commit 1487d53b6c

@ -84,16 +84,12 @@ def CheckLongLines(input_api, output_api, maxlen=80):
"""Checks that there aren't any lines longer than maxlen characters in any of """Checks that there aren't any lines longer than maxlen characters in any of
the text files to be submitted. the text files to be submitted.
""" """
basename = input_api.basename
bad = [] bad = []
for f, line_num, line in input_api.RightHandSideLines(): for f, line_num, line in input_api.RightHandSideLines():
if line.endswith('\n'):
line = line[:-1]
if len(line) > maxlen: if len(line) > maxlen:
bad.append( bad.append(
'%s, line %s, %s chars' % '%s, line %s, %s chars' %
(basename(f.LocalPath()), line_num, len(line))) (f.LocalPath(), line_num, len(line)))
if len(bad) == 5: # Just show the first 5 errors. if len(bad) == 5: # Just show the first 5 errors.
break break
@ -120,27 +116,25 @@ def CheckTreeIsOpen(input_api, output_api, url, closed):
return [] return []
def _RunPythonUnitTests_LoadTests(input_api, module_name):
"""Meant to be stubbed out during unit testing."""
module = __import__(module_name)
for part in module_name.split('.')[1:]:
module = getattr(module, part)
return input_api.unittest.TestLoader().loadTestsFromModule(module)._tests
def RunPythonUnitTests(input_api, output_api, unit_tests): def RunPythonUnitTests(input_api, output_api, unit_tests):
"""Imports the unit_tests modules and run them.""" """Imports the unit_tests modules and run them."""
import unittest
tests_suite = [] tests_suite = []
test_loader = unittest.TestLoader()
def LoadTests(module_name):
module = __import__(module_name)
for part in module_name.split('.')[1:]:
module = getattr(module, part)
tests_suite.extend(test_loader.loadTestsFromModule(module)._tests)
outputs = [] outputs = []
for unit_test in unit_tests: for unit_test in unit_tests:
try: try:
LoadTests(unit_test) tests_suite.extend(_RunPythonUnitTests_LoadTests(unit_test))
except ImportError: except ImportError:
outputs.Append(output_api.PresubmitError("Failed to load %s" % unit_test)) outputs.append(output_api.PresubmitError("Failed to load %s" % unit_test))
raise
results = unittest.TextTestRunner(verbosity=0).run(unittest.TestSuite( results = input_api.unittest.TextTestRunner(verbosity=0).run(
tests_suite)) input_api.unittest.TestSuite(tests_suite))
if not results.wasSuccessful(): if not results.wasSuccessful():
outputs.append(output_api.PresubmitError( outputs.append(output_api.PresubmitError(
"%d unit tests failed." % (results.failures + results.errors))) "%d unit tests failed." % (results.failures + results.errors)))

@ -6,7 +6,7 @@
"""Enables directory-specific presubmit checks to run at upload and/or commit. """Enables directory-specific presubmit checks to run at upload and/or commit.
""" """
__version__ = '1.1' __version__ = '1.2'
# TODO(joi) Add caching where appropriate/needed. The API is designed to allow # TODO(joi) Add caching where appropriate/needed. The API is designed to allow
# caching (between all different invocations of presubmit scripts for a given # caching (between all different invocations of presubmit scripts for a given
@ -26,6 +26,7 @@ import subprocess # Exposed through the API.
import sys # Parts exposed through API. import sys # Parts exposed through API.
import tempfile # Exposed through the API. import tempfile # Exposed through the API.
import types import types
import unittest # Exposed through the API.
import urllib2 # Exposed through the API. import urllib2 # Exposed through the API.
import warnings import warnings
@ -172,6 +173,7 @@ class InputApi(object):
self.re = re self.re = re
self.subprocess = subprocess self.subprocess = subprocess
self.tempfile = tempfile self.tempfile = tempfile
self.unittest = unittest
self.urllib2 = urllib2 self.urllib2 = urllib2
# InputApi.platform is the platform you're currently running on. # InputApi.platform is the platform you're currently running on.
@ -273,6 +275,8 @@ class InputApi(object):
the AffectedFile instance of the current file; the AffectedFile instance of the current file;
integer line number (1-based); and integer line number (1-based); and
the contents of the line as a string. the contents of the line as a string.
Note: The cariage return (LF or CR) is stripped off.
""" """
return InputApi._RightHandSideLinesImpl( return InputApi._RightHandSideLinesImpl(
filter(lambda x: x.IsTextFile(), filter(lambda x: x.IsTextFile(),
@ -349,6 +353,7 @@ class AffectedFile(object):
side". side".
Contents will be empty if the file is a directory or does not exist. Contents will be empty if the file is a directory or does not exist.
Note: The cariage returns (LF or CR) are stripped off.
""" """
if self.IsDirectory(): if self.IsDirectory():
return [] return []

@ -86,12 +86,6 @@ def CheckChangeOnUpload(input_api, output_api):
self.mox.StubOutWithMock(presubmit.gcl, 'GetSVNFileProperty') self.mox.StubOutWithMock(presubmit.gcl, 'GetSVNFileProperty')
self.mox.StubOutWithMock(presubmit.gcl, 'ReadFile') self.mox.StubOutWithMock(presubmit.gcl, 'ReadFile')
@staticmethod
def MakeBasicChange(name, description):
ci = presubmit.gcl.ChangeInfo(name=name, description=description)
change = presubmit.GclChange(ci)
return change
def compareMembers(self, object, members): def compareMembers(self, object, members):
"""If you add a member, be sure to add the relevant test!""" """If you add a member, be sure to add the relevant test!"""
# Skip over members starting with '_' since they are usually not meant to # Skip over members starting with '_' since they are usually not meant to
@ -113,7 +107,7 @@ class PresubmitUnittest(PresubmitTestsBase):
'cPickle', 'cStringIO', 'deprecated', 'exceptions', 'cPickle', 'cStringIO', 'deprecated', 'exceptions',
'fnmatch', 'gcl', 'gclient', 'glob', 'marshal', 'normpath', 'optparse', 'fnmatch', 'gcl', 'gclient', 'glob', 'marshal', 'normpath', 'optparse',
'os', 'pickle', 'presubmit_canned_checks', 're', 'subprocess', 'sys', 'os', 'pickle', 'presubmit_canned_checks', 're', 'subprocess', 'sys',
'tempfile', 'types', 'urllib2', 'warnings', 'tempfile', 'types', 'unittest', 'urllib2', 'warnings',
] ]
# If this test fails, you should add the relevant test. # If this test fails, you should add the relevant test.
self.compareMembers(presubmit, members) self.compareMembers(presubmit, members)
@ -522,7 +516,7 @@ class InputApiUnittest(PresubmitTestsBase):
'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths', 'PresubmitLocalPath', 'RightHandSideLines', 'ServerPaths',
'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change', 'basename', 'cPickle', 'cStringIO', 'canned_checks', 'change',
'marshal', 'os_path', 'pickle', 'platform', 'marshal', 'os_path', 'pickle', 'platform',
're', 'subprocess', 'tempfile', 'urllib2', 'version', 're', 'subprocess', 'tempfile', 'unittest', 'urllib2', 'version',
] ]
# If this test fails, you should add the relevant test. # If this test fails, you should add the relevant test.
self.compareMembers(presubmit.InputApi(None, './.'), members) self.compareMembers(presubmit.InputApi(None, './.'), members)
@ -800,27 +794,22 @@ class AffectedFileUnittest(PresubmitTestsBase):
class CannedChecksUnittest(PresubmitTestsBase): class CannedChecksUnittest(PresubmitTestsBase):
"""Tests presubmit_canned_checks.py.""" """Tests presubmit_canned_checks.py."""
class MockInputApi(object):
class MockUrllib2(object): def setUp(self):
class urlopen(object): PresubmitTestsBase.setUp(self)
def __init__(self, url): self.mox.StubOutWithMock(presubmit_canned_checks,
if url == 'url_to_open': '_RunPythonUnitTests_LoadTests')
self.result = '1'
else: def MockInputApi(self):
self.result = '0' input_api = self.mox.CreateMock(presubmit.InputApi)
def read(self): input_api.re = presubmit.re
return self.result input_api.urllib2 = self.mox.CreateMock(presubmit.urllib2)
def close(self): input_api.unittest = unittest
pass return input_api
def __init__(self, lines=None):
self.lines = lines def MakeBasicChange(self, name, description):
self.basename = lambda x: x ci = presubmit.gcl.ChangeInfo(name=name, description=description)
self.urllib2 = self.MockUrllib2() return presubmit.GclChange(ci, self.fake_root_dir)
self.re = presubmit.re
def RightHandSideLines(self):
for line in self.lines:
yield (presubmit.AffectedFile('bingo', 'M'), 1, line)
def testMembersChanged(self): def testMembersChanged(self):
self.mox.ReplayAll() self.mox.ReplayAll()
@ -834,120 +823,181 @@ class CannedChecksUnittest(PresubmitTestsBase):
# If this test fails, you should add the relevant test. # If this test fails, you should add the relevant test.
self.compareMembers(presubmit_canned_checks, members) self.compareMembers(presubmit_canned_checks, members)
def testCannedCheckChangeHasBugField(self): def TestDescription(self, check, description1, description2, error_type):
input_api1 = self.MockInputApi()
input_api1.change = self.MakeBasicChange('foo', 'Foo\n' + description1)
input_api2 = self.MockInputApi()
input_api2.change = self.MakeBasicChange('foo', 'Foo\n' + description2)
self.mox.ReplayAll()
results1 = check(input_api1, presubmit.OutputApi)
self.assertEquals(results1, [])
results2 = check(input_api2, presubmit.OutputApi)
self.assertEquals(len(results2), 1)
self.assertEquals(results2[0].__class__, error_type)
def TestContent(self, check, content1, content2, error_type):
input_api1 = self.MockInputApi()
input_api1.change = self.MakeBasicChange('foo', 'Foo\n')
affected_file = self.mox.CreateMock(presubmit.SvnAffectedFile)
affected_file.LocalPath().AndReturn('foo.cc')
output1 = [
(affected_file, 42, 'yo, ' + content1),
(affected_file, 43, 'yer'),
(affected_file, 23, 'ya'),
]
input_api1.RightHandSideLines().AndReturn(output1)
input_api2 = self.MockInputApi()
input_api2.change = self.MakeBasicChange('foo', 'Foo\n')
output2 = [
(affected_file, 42, 'yo, ' + content2),
(affected_file, 43, 'yer'),
(affected_file, 23, 'ya'),
]
input_api2.RightHandSideLines().AndReturn(output2)
self.mox.ReplayAll() self.mox.ReplayAll()
change = self.MakeBasicChange('foo',
'Foo\nBUG=1234')
api = presubmit.InputApi(change, './PRESUBMIT.py')
self.failIf(presubmit_canned_checks.CheckChangeHasBugField(
api, presubmit.OutputApi))
change = self.MakeBasicChange('foo', results1 = check(input_api1, presubmit.OutputApi)
'Foo\nNEVERTESTED=did some stuff') self.assertEquals(results1, [])
api = presubmit.InputApi(change, './PRESUBMIT.py') results2 = check(input_api2, presubmit.OutputApi)
self.failUnless(presubmit_canned_checks.CheckChangeHasBugField( self.assertEquals(len(results2), 1)
api, presubmit.OutputApi)) self.assertEquals(results2[0].__class__, error_type)
def testCannedCheckChangeHasTestField(self): def testCannedCheckChangeHasBugField(self):
self.mox.ReplayAll() self.TestDescription(presubmit_canned_checks.CheckChangeHasBugField,
change = self.MakeBasicChange('foo', 'BUG=1234', '',
'Foo\nTEST=did some stuff') presubmit.OutputApi.PresubmitNotifyResult)
api = presubmit.InputApi(change, './PRESUBMIT.py')
self.failIf(presubmit_canned_checks.CheckChangeHasTestField(
api, presubmit.OutputApi))
change = self.MakeBasicChange('foo', def testCannedCheckChangeHasTestField(self):
'Foo\nNOTEST=did some stuff') self.TestDescription(presubmit_canned_checks.CheckChangeHasTestField,
api = presubmit.InputApi(change, './PRESUBMIT.py') 'TEST=did some stuff', '',
self.failUnless(presubmit_canned_checks.CheckChangeHasTestField( presubmit.OutputApi.PresubmitNotifyResult)
api, presubmit.OutputApi))
def testCannedCheckChangeHasTestedField(self): def testCannedCheckChangeHasTestedField(self):
self.mox.ReplayAll() self.TestDescription(presubmit_canned_checks.CheckChangeHasTestedField,
change = self.MakeBasicChange('foo', 'TESTED=did some stuff', '',
'Foo\nTESTED=did some stuff') presubmit.OutputApi.PresubmitError)
api = presubmit.InputApi(change, './PRESUBMIT.py')
self.failIf(presubmit_canned_checks.CheckChangeHasTestedField(
api, presubmit.OutputApi))
change = self.MakeBasicChange('foo',
'Foo\nNEVERTESTED=did some stuff')
api = presubmit.InputApi(change, './PRESUBMIT.py')
self.failUnless(presubmit_canned_checks.CheckChangeHasTestedField(
api, presubmit.OutputApi))
def testCannedCheckChangeHasQAField(self): def testCannedCheckChangeHasQAField(self):
self.mox.ReplayAll() self.TestDescription(presubmit_canned_checks.CheckChangeHasQaField,
change = self.MakeBasicChange('foo', 'QA=BSOD your machine', '',
'Foo\nQA=test floop feature very well') presubmit.OutputApi.PresubmitError)
api = presubmit.InputApi(change, './PRESUBMIT.py')
self.failIf(presubmit_canned_checks.CheckChangeHasQaField(
api, presubmit.OutputApi))
change = self.MakeBasicChange('foo',
'Foo\nNOTFORQA=test floop feature very well')
api = presubmit.InputApi(change, './PRESUBMIT.py')
self.failUnless(presubmit_canned_checks.CheckChangeHasQaField(
api, presubmit.OutputApi))
def testCannedCheckDoNotSubmitInDescription(self): def testCannedCheckDoNotSubmitInDescription(self):
self.mox.ReplayAll() self.TestDescription(presubmit_canned_checks.CheckDoNotSubmitInDescription,
change = self.MakeBasicChange('foo', 'hello') 'DO NOTSUBMIT', 'DO NOT ' + 'SUBMIT',
api = presubmit.InputApi(change, './PRESUBMIT.py') presubmit.OutputApi.PresubmitError)
self.failIf(presubmit_canned_checks.CheckDoNotSubmitInDescription(
api, presubmit.OutputApi))
change = self.MakeBasicChange('foo',
'DO NOT ' + 'SUBMIT')
api = presubmit.InputApi(change, './PRESUBMIT.py')
self.failUnless(presubmit_canned_checks.CheckDoNotSubmitInDescription(
api, presubmit.OutputApi))
def testCannedCheckDoNotSubmitInFiles(self): def testCannedCheckDoNotSubmitInFiles(self):
self.mox.ReplayAll() self.TestContent(presubmit_canned_checks.CheckDoNotSubmitInFiles,
self.failIf(presubmit_canned_checks.CheckDoNotSubmitInFiles( 'DO NOTSUBMIT', 'DO NOT ' + 'SUBMIT',
self.MockInputApi(['hello', 'there']), presubmit.OutputApi presubmit.OutputApi.PresubmitError)
))
self.failUnless(presubmit_canned_checks.CheckDoNotSubmitInFiles(
self.MockInputApi(['hello', 'yo, DO NOT ' + 'SUBMIT']),
presubmit.OutputApi))
def testCannedCheckChangeHasNoTabs(self): def testCannedCheckChangeHasNoTabs(self):
self.mox.ReplayAll() self.TestContent(presubmit_canned_checks.CheckChangeHasNoTabs,
self.failIf(presubmit_canned_checks.CheckChangeHasNoTabs( 'blah blah', 'blah\tblah',
self.MockInputApi(['hello', 'there']), presubmit.OutputApi presubmit.OutputApi.PresubmitError)
))
self.failUnless(presubmit_canned_checks.CheckChangeHasNoTabs(
self.MockInputApi(['hello', 'there\tit is']), presubmit.OutputApi
))
def testCannedCheckLongLines(self): def testCannedCheckLongLines(self):
self.mox.ReplayAll() check = lambda x,y: presubmit_canned_checks.CheckLongLines(x, y, 10)
self.failIf(presubmit_canned_checks.CheckLongLines( self.TestContent(check, '', 'blah blah blah',
self.MockInputApi(['hello', 'there']), presubmit.OutputApi, 5 presubmit.OutputApi.PresubmitPromptWarning)
))
self.failUnless(presubmit_canned_checks.CheckLongLines( def testCannedCheckTreeIsOpenOpen(self):
self.MockInputApi(['hello', 'there!']), presubmit.OutputApi, 5 input_api = self.MockInputApi()
)) connection = self.mox.CreateMockAnything()
input_api.urllib2.urlopen('url_to_open').AndReturn(connection)
def testCannedCheckTreeIsOpen(self): connection.read().AndReturn('1')
self.mox.ReplayAll() connection.close()
self.failIf(presubmit_canned_checks.CheckTreeIsOpen( self.mox.ReplayAll()
self.MockInputApi(), presubmit.OutputApi, url='url_to_open', closed='0' results = presubmit_canned_checks.CheckTreeIsOpen(
)) input_api, presubmit.OutputApi, url='url_to_open', closed='0')
self.failUnless(presubmit_canned_checks.CheckTreeIsOpen( self.assertEquals(results, [])
self.MockInputApi(), presubmit.OutputApi, url='url_to_closed', closed='0'
)) def testCannedCheckTreeIsOpenClosed(self):
input_api = self.MockInputApi()
connection = self.mox.CreateMockAnything()
input_api.urllib2.urlopen('url_to_closed').AndReturn(connection)
connection.read().AndReturn('0')
connection.close()
self.mox.ReplayAll()
results = presubmit_canned_checks.CheckTreeIsOpen(
input_api, presubmit.OutputApi, url='url_to_closed', closed='0')
self.assertEquals(len(results), 1)
self.assertEquals(results[0].__class__,
presubmit.OutputApi.PresubmitError)
def testRunPythonUnitTests1(self):
input_api = self.MockInputApi()
self.mox.ReplayAll()
results = presubmit_canned_checks.RunPythonUnitTests(
input_api, presubmit.OutputApi, [])
self.assertEquals(results, [])
def testRunPythonUnitTests2(self):
input_api = self.MockInputApi()
presubmit_canned_checks._RunPythonUnitTests_LoadTests('_non_existent_module'
).AndRaise(exceptions.ImportError('Blehh'))
self.mox.ReplayAll()
results = presubmit_canned_checks.RunPythonUnitTests(
input_api, presubmit.OutputApi, ['_non_existent_module'])
self.assertEquals(len(results), 1)
self.assertEquals(results[0].__class__, presubmit.OutputApi.PresubmitError)
def testRunPythonUnitTests3(self):
input_api = self.MockInputApi()
test_module = self.mox.CreateMockAnything()
presubmit_canned_checks._RunPythonUnitTests_LoadTests('test_module'
).AndReturn([])
self.mox.ReplayAll()
results = presubmit_canned_checks.RunPythonUnitTests(
input_api, presubmit.OutputApi, ['test_module'])
self.assertEquals(results, [])
def testRunPythonUnitTests4(self):
input_api = self.MockInputApi()
input_api.unittest = self.mox.CreateMock(unittest)
test = self.mox.CreateMockAnything()
presubmit_canned_checks._RunPythonUnitTests_LoadTests('test_module'
).AndReturn([test])
runner = self.mox.CreateMockAnything()
input_api.unittest.TextTestRunner(verbosity=0).AndReturn(runner)
suite = self.mox.CreateMockAnything()
input_api.unittest.TestSuite([test]).AndReturn(suite)
test_result = self.mox.CreateMockAnything()
runner.run(suite).AndReturn(test_result)
test_result.wasSuccessful().AndReturn(False)
test_result.failures = 2
test_result.errors = 3
self.mox.ReplayAll()
results = presubmit_canned_checks.RunPythonUnitTests(
input_api, presubmit.OutputApi, ['test_module'])
self.assertEquals(len(results), 1)
self.assertEquals(results[0].__class__, presubmit.OutputApi.PresubmitError)
def testRunPythonUnitTests5(self):
input_api = self.MockInputApi()
input_api.unittest = self.mox.CreateMock(unittest)
test = self.mox.CreateMockAnything()
presubmit_canned_checks._RunPythonUnitTests_LoadTests('test_module'
).AndReturn([test])
runner = self.mox.CreateMockAnything()
input_api.unittest.TextTestRunner(verbosity=0).AndReturn(runner)
suite = self.mox.CreateMockAnything()
input_api.unittest.TestSuite([test]).AndReturn(suite)
test_result = self.mox.CreateMockAnything()
runner.run(suite).AndReturn(test_result)
test_result.wasSuccessful().AndReturn(True)
test_result.failures = 0
test_result.errors = 0
self.mox.ReplayAll()
results = presubmit_canned_checks.RunPythonUnitTests(
input_api, presubmit.OutputApi, ['test_module'])
self.assertEquals(len(results), 0)
def RunPythonUnitTests(self):
self.mox.ReplayAll()
# TODO(maruel): Add real tests.
self.failIf(presubmit_canned_checks.RunPythonUnitTests(
self.MockInputApi(),
presubmit.OutputApi, []))
self.failUnless(presubmit_canned_checks.RunPythonUnitTests(
self.MockInputApi(),
presubmit.OutputApi, ['non_existent_module']))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

Loading…
Cancel
Save