From be0d1ca0e41eb01891ca2719f4c51653361ebd9a Mon Sep 17 00:00:00 2001 From: "maruel@chromium.org" Date: Tue, 12 May 2009 19:23:02 +0000 Subject: [PATCH] Add more tests and cleanup ChangeInfo class. Review URL: http://codereview.chromium.org/113269 git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@15885 0039d316-1c4b-4281-b951-d872f2087c98 --- gcl.py | 19 +++++----- tests/gcl_unittest.py | 49 +++++++++++++++++++++++-- tests/trychange_unittest.py | 72 +++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 tests/trychange_unittest.py diff --git a/gcl.py b/gcl.py index dd2b63979..21ca6ddae 100755 --- a/gcl.py +++ b/gcl.py @@ -29,10 +29,6 @@ CODEREVIEW_SETTINGS = { "VIEW_VC": "http://src.chromium.org/viewvc/chrome?view=rev&revision=", } -# Use a shell for subcommands on Windows to get a PATH search, and because svn -# may be a batch file. -use_shell = sys.platform.startswith("win") - # globals that store the root of the current repository and the directory where # we store information about changelists. repository_root = "" @@ -84,7 +80,8 @@ def IsSVNMoved(filename): def GetSVNFileInfo(file): """Returns a dictionary from the svn info output for the given file.""" - dom = ParseXML(RunShell(["svn", "info", "--xml", file])) + output = RunShell(["svn", "info", "--xml", file]) + dom = ParseXML(output) result = {} if dom: # /info/entry/ @@ -147,7 +144,8 @@ def GetSVNStatus(file): 'unversioned': '?', # TODO(maruel): Find the corresponding strings for X, ~ } - dom = ParseXML(RunShell(command)) + output = RunShell(command) + dom = ParseXML(output) results = [] if dom: # /status/target/entry/(wc-status|commit|author|date) @@ -286,6 +284,9 @@ def ErrorExit(msg, exit=True): def RunShellWithReturnCode(command, print_output=False): """Executes a command and returns the output and the return code.""" + # Use a shell for subcommands on Windows to get a PATH search, and because svn + # may be a batch file. + use_shell = sys.platform.startswith("win") p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=use_shell, universal_newlines=True) @@ -326,7 +327,7 @@ def WriteFile(filename, contents): file.close() -class ChangeInfo: +class ChangeInfo(object): """Holds information about a changelist. issue: the Rietveld issue number, of "" if it hasn't been uploaded yet. @@ -334,10 +335,12 @@ class ChangeInfo: files: a list of 2 tuple containing (status, filename) of changed files, with paths being relative to the top repository directory. """ - def __init__(self, name="", issue="", description="", files=[]): + def __init__(self, name="", issue="", description="", files=None): self.name = name self.issue = issue self.description = description + if files is None: + files = [] self.files = files self.patch = None diff --git a/tests/gcl_unittest.py b/tests/gcl_unittest.py index b36dd9a57..cb15538f7 100755 --- a/tests/gcl_unittest.py +++ b/tests/gcl_unittest.py @@ -5,7 +5,9 @@ """Unit tests for gcl.py.""" +import StringIO import os +import sys import unittest # Local imports @@ -56,8 +58,7 @@ class GclUnittest(GclTestsBase): 'UnknownFiles', 'UploadCL', 'Warn', 'WriteFile', 'gcl_info_dir', 'getpass', 'main', 'os', 'random', 're', 'read_gcl_info', 'repository_root', 'string', 'subprocess', 'sys', 'tempfile', 'upload', - 'urllib2', 'use_shell', 'xml', - + 'urllib2', 'xml', ] # If this test fails, you should add the relevant test. self.compareMembers(gcl, members) @@ -79,6 +80,7 @@ class GclUnittest(GclTestsBase): """ % command[3] + # GclTestsBase.tearDown will restore the original. gcl.RunShell = RunShellMock filename = os.path.join('app', 'd') info = gcl.GetSVNFileInfo(filename) @@ -132,6 +134,7 @@ class GclUnittest(GclTestsBase): """ + # GclTestsBase.tearDown will restore the original. gcl.RunShell = RunShellMock info = gcl.GetSVNStatus('.') expected = [ @@ -152,10 +155,52 @@ class GclUnittest(GclTestsBase): """ + # GclTestsBase.tearDown will restore the original. gcl.RunShell = RunShellMock info = gcl.GetSVNStatus(None) self.assertEquals(info, []) + def testHelp(self): + old_stdout = sys.stdout + try: + dummy = StringIO.StringIO() + gcl.sys.stdout = dummy + gcl.Help() + self.assertEquals(len(dummy.getvalue()), 1718) + finally: + gcl.sys.stdout = old_stdout + + def testGetRepositoryRoot(self): + try: + def RunShellMock(filename): + return '\n' + gcl.RunShell = RunShellMock + gcl.GetRepositoryRoot() + except Exception,e: + self.assertEquals(e.args[0], "gcl run outside of repository") + pass + + +class ChangeInfoUnittest(GclTestsBase): + def testChangeInfoMembers(self): + members = [ + 'CloseIssue', 'Delete', 'FileList', 'MissingTests', 'Save', + 'UpdateRietveldDescription', 'description', 'files', 'issue', 'name', + 'patch' + ] + # If this test fails, you should add the relevant test. + self.compareMembers(gcl.ChangeInfo(), members) + + def testChangeInfoBase(self): + files = [('M', 'foo'), ('A', 'bar')] + o = gcl.ChangeInfo('name2', 'issue2', 'description2', files) + self.assertEquals(o.name, 'name2') + self.assertEquals(o.issue, 'issue2') + self.assertEquals(o.description, 'description2') + self.assertEquals(o.files, files) + self.assertEquals(o.patch, None) + self.assertEquals(o.FileList(), ['foo', 'bar']) + if __name__ == '__main__': unittest.main() diff --git a/tests/trychange_unittest.py b/tests/trychange_unittest.py new file mode 100644 index 000000000..1e68dfc3e --- /dev/null +++ b/tests/trychange_unittest.py @@ -0,0 +1,72 @@ +#!/usr/bin/python +# Copyright (c) 2009 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. + +"""Unit tests for trychange.py.""" + +import os +import unittest + +# Local imports +import trychange + + +class TryChangeTestsBase(unittest.TestCase): + """Setups and tear downs the mocks but doesn't test anything as-is.""" + def setUp(self): + pass + + def tearDown(self): + pass + + def compareMembers(self, object, members): + """If you add a member, be sure to add the relevant test!""" + # Skip over members starting with '_' since they are usually not meant to + # be for public use. + actual_members = [x for x in sorted(dir(object)) + if not x.startswith('_')] + expected_members = sorted(members) + if actual_members != expected_members: + diff = ([i for i in actual_members if i not in expected_members] + + [i for i in expected_members if i not in actual_members]) + print diff + self.assertEqual(actual_members, expected_members) + + +class TryChangeUnittest(TryChangeTestsBase): + """General trychange.py tests.""" + def testMembersChanged(self): + members = [ + 'EscapeDot', 'ExecuteTryServerScript', 'GIT', 'GetSourceRoot', 'GuessVCS', + 'HELP_STRING', 'InvalidScript', 'NoTryServerAccess', 'PathDifference', + 'RunCommand', 'SCM', 'SCRIPT_PATH', 'SVN', 'TryChange', 'USAGE', + 'datetime', 'gcl', 'gclient', 'getpass', 'logging', 'optparse', 'os', + 'shutil', 'sys', 'tempfile', 'traceback', 'urllib', + ] + # If this test fails, you should add the relevant test. + self.compareMembers(trychange, members) + + +class SVNUnittest(TryChangeTestsBase): + """General trychange.py tests.""" + def testMembersChanged(self): + members = [ + 'GenerateDiff', 'ProcessOptions', 'options' + ] + # If this test fails, you should add the relevant test. + self.compareMembers(trychange.SVN(None), members) + + +class TryChangeUnittest(TryChangeTestsBase): + """General trychange.py tests.""" + def testMembersChanged(self): + members = [ + 'GenerateDiff', 'GetEmail', 'GetPatchName', 'ProcessOptions', 'options' + ] + # If this test fails, you should add the relevant test. + self.compareMembers(trychange.GIT(None), members) + + +if __name__ == '__main__': + unittest.main()