Skip to content

Commit 324a2c3

Browse files
committed
Running restricted set of unit tests on Travis PR.
1 parent 8fcf9ef commit 324a2c3

File tree

3 files changed

+113
-19
lines changed

3 files changed

+113
-19
lines changed

scripts/run_unit_tests.py

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
import subprocess
2727
import sys
2828

29+
from script_utils import check_output
30+
from script_utils import get_changed_packages
31+
from script_utils import in_travis
32+
from script_utils import in_travis_pr
33+
from script_utils import travis_branch
34+
2935

3036
PROJECT_ROOT = os.path.abspath(
3137
os.path.join(os.path.dirname(__file__), '..'))
@@ -44,24 +50,6 @@
4450
UNSET_SENTINEL = object() # Sentinel for argparser
4551

4652

47-
def check_output(*args):
48-
"""Run a command on the operation system.
49-
50-
:type args: tuple
51-
:param args: Keyword arguments to pass to ``subprocess.check_output``.
52-
53-
:rtype: str
54-
:returns: The raw STDOUT from the command (converted from bytes
55-
if necessary).
56-
"""
57-
cmd_output = subprocess.check_output(args)
58-
# On Python 3, this returns bytes (from STDOUT), so we
59-
# convert to a string.
60-
cmd_output = cmd_output.decode('utf-8')
61-
# Also strip the output since it usually has a trailing newline.
62-
return cmd_output.strip()
63-
64-
6553
def get_package_directories():
6654
"""Get a list of directories containing sub-packages.
6755
@@ -83,6 +71,30 @@ def get_package_directories():
8371
return result
8472

8573

74+
def get_travis_directories(package_list):
75+
"""Get list of packages that need to be tested on Travis CI.
76+
77+
See: https://travis-ci.com/
78+
79+
If the current Travis build is for a pull request (PR), this will
80+
limit the directories to the ones impacted by the PR. Otherwise
81+
it will just test all package directories.
82+
83+
:type package_list: list
84+
:param package_list: The list of **all** valid packages with unit tests.
85+
86+
:rtype: list
87+
:returns: A list of all package directories where tests
88+
need to be run.
89+
"""
90+
if in_travis_pr():
91+
pr_against_branch = travis_branch()
92+
return get_changed_packages('HEAD', pr_against_branch,
93+
package_list)
94+
else:
95+
return package_list
96+
97+
8698
def verify_packages(subset, all_packages):
8799
"""Verify that a subset of packages are among all packages.
88100
@@ -107,6 +119,9 @@ def get_test_packages():
107119
Filters the package list in the following order:
108120
109121
* Check command line for packages passed in as positional arguments
122+
* Check if in Travis, then limit the subset based on changes
123+
in a Pull Request ("push" builds to branches may not have
124+
any filtering)
110125
* Just use all packages
111126
112127
:rtype: list
@@ -120,6 +135,8 @@ def get_test_packages():
120135
if args.packages is not UNSET_SENTINEL:
121136
verify_packages(args.packages, all_packages)
122137
return sorted(args.packages)
138+
elif in_travis():
139+
return get_travis_directories(all_packages)
123140
else:
124141
return all_packages
125142

scripts/script_utils.py

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"""Common helpers for testing scripts."""
1616

1717
import os
18+
import subprocess
1819

1920

2021
LOCAL_REMOTE_ENV = 'GOOGLE_CLOUD_TESTING_REMOTE'
@@ -81,5 +82,80 @@ def travis_branch():
8182
:rtype: str
8283
:returns: The name of the branch the current pull request is
8384
changed against.
85+
:raises: :class:`~exceptions.OSError` if the ``TRAVIS_BRANCH_ENV``
86+
environment variable isn't set during a pull request
87+
build.
8488
"""
85-
return os.getenv(TRAVIS_BRANCH_ENV)
89+
try:
90+
return os.environ[TRAVIS_BRANCH_ENV]
91+
except KeyError:
92+
msg = ('Pull request build does not have an '
93+
'associated branch set (via %s)') % (TRAVIS_BRANCH_ENV,)
94+
raise OSError(msg)
95+
96+
97+
def check_output(*args):
98+
"""Run a command on the operation system.
99+
100+
:type args: tuple
101+
:param args: Arguments to pass to ``subprocess.check_output``.
102+
103+
:rtype: str
104+
:returns: The raw STDOUT from the command (converted from bytes
105+
if necessary).
106+
"""
107+
cmd_output = subprocess.check_output(args)
108+
# On Python 3, this returns bytes (from STDOUT), so we
109+
# convert to a string.
110+
cmd_output = cmd_output.decode('utf-8')
111+
# Also strip the output since it usually has a trailing newline.
112+
return cmd_output.strip()
113+
114+
115+
def rootname(filename):
116+
"""Get the root directory that a file is contained in.
117+
118+
:type filename: str
119+
:param filename: The path / name of a file.
120+
121+
:rtype: str
122+
:returns: The root directory containing the file.
123+
"""
124+
if os.path.sep not in filename:
125+
return ''
126+
else:
127+
file_root, _ = filename.split(os.path.sep, 1)
128+
return file_root
129+
130+
131+
def get_changed_packages(blob_name1, blob_name2, package_list):
132+
"""Get a list of packages which have changed between two changesets.
133+
134+
:type blob_name1: str
135+
:param blob_name1: The name of a commit hash or branch name or other
136+
``git`` artifact.
137+
138+
:type blob_name2: str
139+
:param blob_name2: The name of a commit hash or branch name or other
140+
``git`` artifact.
141+
142+
:type package_list: list
143+
:param package_list: The list of **all** valid packages with unit tests.
144+
145+
:rtype: list
146+
:returns: A list of all package directories that have changed
147+
between ``blob_name1`` and ``blob_name2``. Starts
148+
with a list of valid packages (``package_list``)
149+
and filters out the unchanged directories.
150+
"""
151+
changed_files = check_output(
152+
'git', 'diff', '--name-only', blob_name1, blob_name2)
153+
changed_files = changed_files.split('\n')
154+
155+
result = set()
156+
for filename in changed_files:
157+
file_root = rootname(filename)
158+
if file_root in package_list:
159+
result.add(file_root)
160+
161+
return sorted(result)

tox.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ skip_install =
121121
py34: True
122122
py35: True
123123
isolated-cover: True
124+
passenv = TRAVIS*
124125

125126
[testenv:isolated-cover]
126127
commands =

0 commit comments

Comments
 (0)