Skip to content

Commit 900923b

Browse files
authored
Merge pull request googleapis#2473 from dhermes/collapse-travis-config
Collapsing sub-package explosion in Travis config into a script.
2 parents c055ee8 + d7f79cd commit 900923b

File tree

3 files changed

+174
-52
lines changed

3 files changed

+174
-52
lines changed

.travis.yml

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,53 +5,11 @@ install:
55
- pip install --upgrade pip tox
66

77
script:
8-
- (cd core && tox -e py27)
9-
- (cd bigtable && tox -e py27)
10-
- (cd storage && tox -e py27)
11-
- (cd datastore && tox -e py27)
12-
- (cd bigquery && tox -e py27)
13-
- (cd pubsub && tox -e py27)
14-
- (cd logging && tox -e py27)
15-
- (cd dns && tox -e py27)
16-
- (cd language && tox -e py27)
17-
- (cd error_reporting && tox -e py27)
18-
- (cd resource_manager && tox -e py27)
19-
- (cd monitoring && tox -e py27)
20-
- (cd vision && tox -e py27)
21-
- (cd translate && tox -e py27)
22-
- (cd speech && tox -e py27)
23-
- (cd core && tox -e py34)
24-
- (cd bigtable && tox -e py34)
25-
- (cd storage && tox -e py34)
26-
- (cd datastore && tox -e py34)
27-
- (cd bigquery && tox -e py34)
28-
- (cd pubsub && tox -e py34)
29-
- (cd logging && tox -e py34)
30-
- (cd dns && tox -e py34)
31-
- (cd language && tox -e py34)
32-
- (cd error_reporting && tox -e py34)
33-
- (cd resource_manager && tox -e py34)
34-
- (cd monitoring && tox -e py34)
35-
- (cd vision && tox -e py34)
36-
- (cd translate && tox -e py34)
37-
- (cd speech && tox -e py34)
8+
- tox -e py27
9+
- tox -e py34
3810
- tox -e lint
3911
- tox -e cover
40-
- (cd core && tox -e cover)
41-
- (cd bigtable && tox -e cover)
42-
- (cd storage && tox -e cover)
43-
- (cd datastore && tox -e cover)
44-
- (cd bigquery && tox -e cover)
45-
- (cd pubsub && tox -e cover)
46-
- (cd logging && tox -e cover)
47-
- (cd dns && tox -e cover)
48-
- (cd language && tox -e cover)
49-
- (cd error_reporting && tox -e cover)
50-
- (cd resource_manager && tox -e cover)
51-
- (cd monitoring && tox -e cover)
52-
- (cd vision && tox -e cover)
53-
- (cd translate && tox -e cover)
54-
- (cd speech && tox -e cover)
12+
- tox -e isolated-cover
5513
- tox -e system-tests
5614
- tox -e system-tests3
5715
- scripts/update_docs.sh

scripts/run_unit_tests.py

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# Copyright 2016 Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Script to run unit tests for the entire project.
16+
17+
This script orchestrates stepping into each sub-package and
18+
running tests. It also allows running a limited subset of tests
19+
in cases where such a limited subset can be identified.
20+
"""
21+
22+
from __future__ import print_function
23+
24+
import argparse
25+
import os
26+
import subprocess
27+
import sys
28+
29+
30+
PROJECT_ROOT = os.path.abspath(
31+
os.path.join(os.path.dirname(__file__), '..'))
32+
IGNORED_DIRECTORIES = (
33+
'appveyor',
34+
'docs',
35+
'scripts',
36+
'system_tests',
37+
)
38+
ENV_REMAP = {
39+
'isolated-cover': 'cover',
40+
}
41+
42+
43+
def check_output(*args):
44+
"""Run a command on the operation system.
45+
46+
:type args: tuple
47+
:param args: Keyword arguments to pass to ``subprocess.check_output``.
48+
49+
:rtype: str
50+
:returns: The raw STDOUT from the command (converted from bytes
51+
if necessary).
52+
"""
53+
cmd_output = subprocess.check_output(args)
54+
# On Python 3, this returns bytes (from STDOUT), so we
55+
# convert to a string.
56+
cmd_output = cmd_output.decode('utf-8')
57+
# Also strip the output since it usually has a trailing newline.
58+
return cmd_output.strip()
59+
60+
61+
def get_package_directories():
62+
"""Get a list of directories containing sub-packages.
63+
64+
:rtype: list
65+
:returns: A list of all sub-package directories.
66+
"""
67+
# Run ls-tree with
68+
# -d: For directories only
69+
# --name-only: No extra info like the type/hash/permission bits.
70+
# --full-name: Give path relative to root, rather than cwd.
71+
ls_tree_out = check_output(
72+
'git', 'ls-tree',
73+
'-d', '--name-only', '--full-name',
74+
'HEAD', PROJECT_ROOT)
75+
result = []
76+
for package in ls_tree_out.split('\n'):
77+
if package not in IGNORED_DIRECTORIES:
78+
result.append(package)
79+
return result
80+
81+
82+
def run_package(package, tox_env):
83+
"""Run tox environment for a given package.
84+
85+
:type package: str
86+
:param package: The name of the subdirectory which holds the sub-package.
87+
This will be a path relative to ``PROJECT_ROOT``.
88+
89+
:type tox_env: str
90+
:param tox_env: The ``tox`` environment(s) to run in each sub-package.
91+
92+
:rtype: bool
93+
:returns: Flag indicating if the test run succeeded.
94+
"""
95+
curr_dir = os.getcwd()
96+
package_dir = os.path.join(PROJECT_ROOT, package)
97+
try:
98+
os.chdir(package_dir)
99+
return_code = subprocess.call(['tox', '-e', tox_env])
100+
return return_code == 0
101+
finally:
102+
os.chdir(curr_dir)
103+
104+
105+
def get_parser():
106+
"""Get simple ``argparse`` parser to determine configuration.
107+
108+
:rtype: :class:`argparse.ArgumentParser`
109+
:returns: The parser for this script.
110+
"""
111+
description = 'Run tox environment(s) in all sub-packages.'
112+
parser = argparse.ArgumentParser(description=description)
113+
parser.add_argument(
114+
'--tox-env-dir', dest='tox_env_dir',
115+
help='The current tox environment directory.')
116+
return parser
117+
118+
119+
def get_tox_env():
120+
"""Get the environment to be used with ``tox``.
121+
122+
:rtype: str
123+
:returns: The current ``tox`` environment to be used, e.g. ``"py27"``.
124+
"""
125+
parser = get_parser()
126+
args = parser.parse_args()
127+
env_dir = args.tox_env_dir
128+
_, tox_env = os.path.split(env_dir)
129+
tox_env = ENV_REMAP.get(tox_env, tox_env)
130+
return tox_env
131+
132+
133+
def main():
134+
"""Run all the unit tests that need to be run."""
135+
packages_to_run = get_package_directories()
136+
if not packages_to_run:
137+
print('No tests to run.')
138+
return
139+
140+
tox_env = get_tox_env()
141+
failed_packages = []
142+
for package in packages_to_run:
143+
succeeded = run_package(package, tox_env)
144+
if not succeeded:
145+
failed_packages.append(package)
146+
147+
if failed_packages:
148+
msg_parts = ['Sub-packages failed:']
149+
for package in failed_packages:
150+
msg_parts.append('- ' + package)
151+
msg = '\n'.join(msg_parts)
152+
print(msg, file=sys.stderr)
153+
sys.exit(len(failed_packages))
154+
155+
156+
if __name__ == '__main__':
157+
main()

tox.ini

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,22 @@ covercmd =
114114

115115
[testenv]
116116
commands =
117-
py.test --quiet {posargs} unit_tests
117+
python {toxinidir}/scripts/run_unit_tests.py --tox-env-dir {envdir}
118118
deps =
119-
{[testing]deps}
119+
skip_install =
120+
py27: True
121+
py34: True
122+
py35: True
123+
isolated-cover: True
124+
125+
[testenv:isolated-cover]
126+
commands = {[testenv]commands}
120127

121128
[testenv:py27-pandas]
122129
basepython =
123130
python2.7
124131
deps =
125-
{[testenv]deps}
132+
{[testing]deps}
126133
pandas
127134

128135
[testenv:cover]
@@ -131,7 +138,7 @@ basepython =
131138
commands =
132139
{[testing]covercmd}
133140
deps =
134-
{[testenv]deps}
141+
{[testing]deps}
135142
coverage
136143
pytest-cov
137144

@@ -172,7 +179,7 @@ commands =
172179
sphinx-build -W -b html -d docs/_build/doctrees docs docs/_build/html
173180
python {toxinidir}/scripts/verify_included_modules.py --build-root _build
174181
deps =
175-
{[testenv]deps}
182+
{[testing]deps}
176183
Sphinx
177184
sphinx_rtd_theme
178185
passenv = {[testenv:system-tests]passenv} SPHINX_RELEASE READTHEDOCS
@@ -208,7 +215,7 @@ commands =
208215
python {toxinidir}/scripts/pycodestyle_on_repo.py
209216
python {toxinidir}/scripts/run_pylint.py
210217
deps =
211-
{[testenv]deps}
218+
{[testing]deps}
212219
pycodestyle
213220
pylint >= 1.6.4
214221
passenv = {[testenv:system-tests]passenv}
@@ -229,7 +236,7 @@ passenv = {[testenv:system-tests]passenv}
229236

230237
[emulator]
231238
deps =
232-
{[testenv]deps}
239+
{[testing]deps}
233240
psutil
234241
setenv =
235242
GOOGLE_CLOUD_NO_PRINT=true

0 commit comments

Comments
 (0)