Stop using subprocess in tests.

There's no need to run the script to test it, so lets not.

Change-Id: I5b2115a5519d3a82dc3d35fc0d68f606fea97047
This commit is contained in:
Robert Collins 2015-06-03 12:23:17 +12:00
parent 71c1018dc9
commit 673e88e8a6
4 changed files with 55 additions and 61 deletions

View File

@ -17,12 +17,13 @@ from __future__ import print_function
import os import os
import os.path import os.path
import shutil import shutil
import subprocess import StringIO
import sys
import fixtures import fixtures
import testtools import testtools
import update
def _file_to_list(fname): def _file_to_list(fname):
with open(fname) as f: with open(fname) as f:
@ -72,10 +73,8 @@ class UpdateTest(testtools.TestCase):
def _run_update(self): def _run_update(self):
# now go call update and see what happens # now go call update and see what happens
subprocess.check_output( update.main(['project'])
[sys.executable, "update.py", "project"]) update.main(['project_with_oslo'])
subprocess.check_output([sys.executable, "update.py",
"project_with_oslo"])
def setUp(self): def setUp(self):
super(UpdateTest, self).setUp() super(UpdateTest, self).setUp()
@ -140,29 +139,23 @@ class UpdateTest(testtools.TestCase):
# These are tests which don't need to run the project update in advance # These are tests which don't need to run the project update in advance
def test_requirment_not_in_global(self): def test_requirment_not_in_global(self):
returncode = subprocess.call([sys.executable, "update.py", with testtools.ExpectedException(Exception):
"bad_project"]) update.main(['bad_project'])
self.assertEqual(returncode, 1)
def test_requirment_not_in_global_non_fatal(self): def test_requirment_not_in_global_non_fatal(self):
env = os.environ.copy() self.useFixture(
env['NON_STANDARD_REQS'] = '1' fixtures.EnvironmentVariable("NON_STANDARD_REQS", "1"))
returncode = subprocess.call( update.main(["bad_project"])
[sys.executable, "update.py", "bad_project"],
env=env)
self.assertEqual(returncode, 0)
def test_requirement_soft_update(self): def test_requirement_soft_update(self):
returncode = subprocess.call( update.main(["-s", "bad_project"])
[sys.executable, "update.py", "-s", "bad_project"])
self.assertEqual(returncode, 0)
reqs = _file_to_list(self.bad_proj_file) reqs = _file_to_list(self.bad_proj_file)
self.assertIn("thisisnotarealdepedency", reqs) self.assertIn("thisisnotarealdepedency", reqs)
# testing output # testing output
def test_non_verbose_output(self): def test_non_verbose_output(self):
output = subprocess.check_output( capture = StringIO.StringIO()
[sys.executable, "update.py", "project"]) update.main(['project'], capture)
expected = 'Version change for: greenlet, sqlalchemy, eventlet, pastedeploy, routes, webob, wsgiref, boto, kombu, pycrypto, python-swiftclient, lxml, jsonschema, python-keystoneclient\n' # noqa expected = 'Version change for: greenlet, sqlalchemy, eventlet, pastedeploy, routes, webob, wsgiref, boto, kombu, pycrypto, python-swiftclient, lxml, jsonschema, python-keystoneclient\n' # noqa
expected += """Updated project/requirements.txt: expected += """Updated project/requirements.txt:
greenlet>=0.3.1 -> greenlet>=0.3.2 greenlet>=0.3.1 -> greenlet>=0.3.2
@ -186,11 +179,11 @@ Updated project/test-requirements.txt:
testrepository>=0.0.13 -> testrepository>=0.0.17 testrepository>=0.0.13 -> testrepository>=0.0.17
testtools>=0.9.27 -> testtools>=0.9.32 testtools>=0.9.27 -> testtools>=0.9.32
""" """
self.assertEqual(expected, output) self.assertEqual(expected, capture.getvalue())
def test_verbose_output(self): def test_verbose_output(self):
output = subprocess.check_output( capture = StringIO.StringIO()
[sys.executable, "update.py", "-v", "project"]) update.main(['-v', 'project'], capture)
expected = """Syncing project/requirements.txt expected = """Syncing project/requirements.txt
Version change for: greenlet, sqlalchemy, eventlet, pastedeploy, routes, webob, wsgiref, boto, kombu, pycrypto, python-swiftclient, lxml, jsonschema, python-keystoneclient\n""" # noqa Version change for: greenlet, sqlalchemy, eventlet, pastedeploy, routes, webob, wsgiref, boto, kombu, pycrypto, python-swiftclient, lxml, jsonschema, python-keystoneclient\n""" # noqa
expected += """Updated project/requirements.txt: expected += """Updated project/requirements.txt:
@ -217,4 +210,4 @@ Updated project/test-requirements.txt:
testtools>=0.9.27 -> testtools>=0.9.32 testtools>=0.9.27 -> testtools>=0.9.32
Syncing setup.py Syncing setup.py
""" """
self.assertEqual(expected, output) self.assertEqual(expected, capture.getvalue())

View File

@ -20,12 +20,12 @@ from __future__ import print_function
import os import os
import shutil import shutil
import subprocess
import sys
import tempfile import tempfile
import testtools import testtools
import update
def _file_to_list(fname): def _file_to_list(fname):
with open(fname) as f: with open(fname) as f:
@ -59,7 +59,7 @@ class UpdateTestPbr(testtools.TestCase):
# now go call update and see what happens # now go call update and see what happens
self.addCleanup(os.chdir, os.path.abspath(os.curdir)) self.addCleanup(os.chdir, os.path.abspath(os.curdir))
os.chdir(self.dir) os.chdir(self.dir)
subprocess.call([sys.executable, "update.py", "project_pbr"]) update.main(["project_pbr"])
def test_requirements(self): def test_requirements(self):
reqs = _file_to_list(self.req_file) reqs = _file_to_list(self.req_file)

View File

@ -17,12 +17,12 @@ from __future__ import print_function
import os import os
import os.path import os.path
import shutil import shutil
import subprocess
import sys
import tempfile import tempfile
import testtools import testtools
import update
def _file_to_list(fname): def _file_to_list(fname):
with open(fname) as f: with open(fname) as f:
@ -64,10 +64,8 @@ class UpdateTestWithSuffix(testtools.TestCase):
# now go call update and see what happens # now go call update and see what happens
self.addCleanup(os.chdir, os.path.abspath(os.curdir)) self.addCleanup(os.chdir, os.path.abspath(os.curdir))
os.chdir(self.dir) os.chdir(self.dir)
subprocess.call([sys.executable, "update.py", update.main(['-o', 'global', 'project'])
"-o", "global", "project"]) update.main(['-o', 'global', 'project_with_oslo'])
subprocess.call([sys.executable, "update.py",
"-o", "global", "project_with_oslo"])
def test_requirements(self): def test_requirements(self):
# this is the sanity check test # this is the sanity check test

View File

@ -77,9 +77,9 @@ _REQS_HEADER = [
] ]
def verbose(msg): def verbose(msg, stdout):
if VERBOSE: if VERBOSE:
print(msg) stdout.write(msg + "\n")
class Change(object): class Change(object):
@ -138,7 +138,7 @@ def _parse_reqs(filename):
def _sync_requirements_file( def _sync_requirements_file(
source_reqs, dest_path, suffix, softupdate, hacking): source_reqs, dest_path, suffix, softupdate, hacking, stdout):
dest_reqs = _readlines(dest_path) dest_reqs = _readlines(dest_path)
changes = [] changes = []
# this is specifically for global-requirements gate jobs so we don't # this is specifically for global-requirements gate jobs so we don't
@ -146,10 +146,9 @@ def _sync_requirements_file(
if suffix: if suffix:
dest_path = "%s.%s" % (dest_path, suffix) dest_path = "%s.%s" % (dest_path, suffix)
verbose("Syncing %s" % dest_path) verbose("Syncing %s" % dest_path, stdout)
with open(dest_path, 'w') as new_reqs: with open(dest_path, 'w') as new_reqs:
# Check the instructions header # Check the instructions header
if dest_reqs[:len(_REQS_HEADER)] != _REQS_HEADER: if dest_reqs[:len(_REQS_HEADER)] != _REQS_HEADER:
new_reqs.writelines(_REQS_HEADER) new_reqs.writelines(_REQS_HEADER)
@ -194,18 +193,20 @@ def _sync_requirements_file(
# devstack jobs that might have legitimate reasons to # devstack jobs that might have legitimate reasons to
# override. For those we support NON_STANDARD_REQS=1 # override. For those we support NON_STANDARD_REQS=1
# environment variable to turn this into a warning only. # environment variable to turn this into a warning only.
print("'%s' is not in global-requirements.txt" % old_pip) stdout.write(
"'%s' is not in global-requirements.txt\n" % old_pip)
if os.getenv('NON_STANDARD_REQS', '0') != '1': if os.getenv('NON_STANDARD_REQS', '0') != '1':
sys.exit(1) raise Exception("nonstandard requirement present.")
# always print out what we did if we did a thing # always print out what we did if we did a thing
if changes: if changes:
print("Version change for: %s" % ", ".join([x.name for x in changes])) stdout.write(
print("Updated %s:" % dest_path) "Version change for: %s\n" % ", ".join([x.name for x in changes]))
stdout.write("Updated %s:\n" % dest_path)
for change in changes: for change in changes:
print(" %s" % change) stdout.write(" %s\n" % change)
def _copy_requires(suffix, softupdate, hacking, dest_dir): def _copy_requires(suffix, softupdate, hacking, dest_dir, stdout):
"""Copy requirements files.""" """Copy requirements files."""
source_reqs = _parse_reqs('global-requirements.txt') source_reqs = _parse_reqs('global-requirements.txt')
@ -222,10 +223,10 @@ def _copy_requires(suffix, softupdate, hacking, dest_dir):
dest_path = os.path.join(dest_dir, dest) dest_path = os.path.join(dest_dir, dest)
if os.path.exists(dest_path): if os.path.exists(dest_path):
_sync_requirements_file( _sync_requirements_file(
source_reqs, dest_path, suffix, softupdate, hacking) source_reqs, dest_path, suffix, softupdate, hacking, stdout)
def _write_setup_py(dest_path): def _write_setup_py(dest_path, stdout):
target_setup_py = os.path.join(dest_path, 'setup.py') target_setup_py = os.path.join(dest_path, 'setup.py')
setup_cfg = os.path.join(dest_path, 'setup.cfg') setup_cfg = os.path.join(dest_path, 'setup.cfg')
# If it doesn't have a setup.py, then we don't want to update it # If it doesn't have a setup.py, then we don't want to update it
@ -234,25 +235,14 @@ def _write_setup_py(dest_path):
has_pbr = 'pbr' in _read(target_setup_py) has_pbr = 'pbr' in _read(target_setup_py)
if has_pbr: if has_pbr:
if 'name = pbr' not in _read(setup_cfg): if 'name = pbr' not in _read(setup_cfg):
verbose("Syncing setup.py") verbose("Syncing setup.py", stdout)
# We only want to sync things that are up to date # We only want to sync things that are up to date
# with pbr mechanics # with pbr mechanics
with open(target_setup_py, 'w') as setup_file: with open(target_setup_py, 'w') as setup_file:
setup_file.write(_setup_py_text) setup_file.write(_setup_py_text)
def main(options, args): def main(argv=None, stdout=None):
if len(args) != 1:
print("Must specify directory to update")
sys.exit(1)
global VERBOSE
VERBOSE = options.verbose
_copy_requires(options.suffix, options.softupdate, options.hacking,
args[0])
_write_setup_py(args[0])
if __name__ == "__main__":
parser = optparse.OptionParser() parser = optparse.OptionParser()
parser.add_option("-o", "--output-suffix", dest="suffix", default="", parser.add_option("-o", "--output-suffix", dest="suffix", default="",
help="output suffix for updated files (i.e. .global)") help="output suffix for updated files (i.e. .global)")
@ -265,5 +255,18 @@ if __name__ == "__main__":
parser.add_option("-v", "--verbose", dest="verbose", parser.add_option("-v", "--verbose", dest="verbose",
action="store_true", action="store_true",
help="Add further verbosity to output") help="Add further verbosity to output")
(options, args) = parser.parse_args() options, args = parser.parse_args(argv)
main(options, args) if len(args) != 1:
print("Must specify directory to update")
raise Exception("Must specify one and only one directory to update.")
global VERBOSE
VERBOSE = options.verbose
if stdout is None:
stdout = sys.stdout
_copy_requires(options.suffix, options.softupdate, options.hacking,
args[0], stdout=stdout)
_write_setup_py(args[0], stdout=stdout)
if __name__ == "__main__":
main()