Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test_utilities: Teach drake_py_unittest where the source lives #10969

Merged
merged 1 commit into from Mar 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 16 additions & 18 deletions common/test_utilities/drake_py_unittest_main.py
Expand Up @@ -26,27 +26,25 @@
main_py = sys.argv[0]

# Parse the test case name out of the runfiles directory name.
match = re.search("/([^/]*_test).runfiles/", main_py)
match = re.search("^(.*bin/(.*?/)?(py/)?([^/]*_test).runfiles/)", main_py)
if not match:
print("error: no test name match in {}".format(main_py))
sys.exit(1)
test_name, = match.groups()
test_filename = test_name + ".py"
runfiles, test_package, _, test_name, = match.groups()
test_basename = test_name + ".py"

# Find the test_filename and check it for a (misleading) __main__.
found_filename = None
for dirpath, dirs, files in os.walk("."):
if test_filename in files:
assert not found_filename
found_filename = os.path.join(dirpath, test_filename)
if not found_filename:
raise RuntimeError("No such file found {}!".format(
test_filename))
with io.open(found_filename, "r", encoding="utf8") as infile:
# Check the test's source code for a (misleading) __main__.
runfiles_test_filename = (
runfiles + "drake/" + test_package + "test/" + test_basename)
if not os.path.exists(runfiles_test_filename):
raise RuntimeError("Could not find {} at {}".format(
test_basename, runfiles_test_filename))
realpath_test_filename = os.path.realpath(runfiles_test_filename)
with io.open(realpath_test_filename, "r", encoding="utf8") as infile:
for line in infile.readlines():
if any([line.startswith("if __name__ =="),
line.strip().startswith("unittest.main")]):
print("error: " + test_filename + " appears to have a main " +
print("error: " + test_basename + " appears to have a main " +
"function (checks 'if __name__ == ') or call the main " +
"function of unittest ('unittest.main') but also uses " +
"drake_py_unittest; when using drake_py_unittest, " +
Expand All @@ -55,12 +53,12 @@
"as drake_py_test instead of drake_py_unittest and " +
"keep the main function intact")
sys.exit(1)
if os.access(found_filename, os.X_OK):
print("error: " + test_filename + " uses drake_py_unittest but is " +
if os.access(realpath_test_filename, os.X_OK):
print("error: " + test_basename + " uses drake_py_unittest but is " +
"marked executable in the filesystem; fix this via chmod a-x " +
test_filename)
test_basename)
sys.exit(1)
module = imp.load_source(test_name, found_filename)
module = imp.load_source(test_name, runfiles_test_filename)

# Figure out which arguments are for unittest and which are for the module
# under test.
Expand Down
3 changes: 1 addition & 2 deletions manipulation/util/BUILD.bazel
Expand Up @@ -124,9 +124,8 @@ drake_py_unittest(

drake_py_unittest(
name = "meshlab_to_sdf_test",
srcs = [
data = [
"meshlab_to_sdf.py",
"test/meshlab_to_sdf_test.py",
],
)

Expand Down
15 changes: 10 additions & 5 deletions tools/install/install.bzl
@@ -1,7 +1,7 @@
# -*- python -*-

load("@drake//tools/skylark:drake_java.bzl", "MainClassInfo")
load("@drake//tools/skylark:drake_py.bzl", "drake_py_unittest")
load("@drake//tools/skylark:drake_py.bzl", "drake_py_test")
load(
"@drake//tools/skylark:pathutils.bzl",
"dirname",
Expand Down Expand Up @@ -926,17 +926,22 @@ def install_test(

src = "//tools/install:install_test.py"

drake_py_unittest(
# We can't use drake_py_unittest here, because the srcs path is atypical.
drake_py_test(
name = name,
# This is an integration test with significant I/O that requires an
# "eternal" timeout so that debug builds are successful.
# Therefore, the test size is increased to "medium", and the timeout to
# "eternal".
# "eternal" timeout so that debug builds are successful. Therefore,
# the test size is increased to "medium", and the timeout to "eternal".
# TODO(jamiesnape): Try to shorten the duration of this test.
size = "medium",
srcs = [src],
timeout = "eternal",
deps = ["//tools/install:install_test_helper"],
# The commands in our "list of commands" use unittest themselves, so we
# do the same for our own test rig. That means that both our rig and
# the "list of commands" python programs must have a __main__ clause
# (i.e., they must all be binaries, not libraries).
allow_import_unittest = True,
**kwargs
)

Expand Down
16 changes: 9 additions & 7 deletions tools/install/install_test.py
Expand Up @@ -6,6 +6,11 @@

class TestInstall(unittest.TestCase):
def test_install(self):
# Fail (on purpose) if not given exactly one command line argument.
self.assertEqual(len(sys.argv), 2)
with open(sys.argv[1], 'r') as f:
lines = f.readlines()

# Install into bazel read-only temporary directory. The temporary
# directory does not need to be removed as bazel tests are run in a
# scratch space.
Expand All @@ -17,15 +22,12 @@ def test_install(self):
content = set(os.listdir(installation_folder))
self.assertSetEqual(set(['bin', 'include', 'lib', 'share']), content)

# Will fail (on purpose) if not exactly one command line argument
# given.
self.assertEqual(len(sys.argv), 2)

with open(sys.argv[1], 'r') as f:
lines = f.readlines()

# Execute the install actions.
for cmd in lines:
cmd = cmd.strip()
print("+ {}".format(cmd))
install_test_helper.check_call([os.path.join(os.getcwd(), cmd)])


if __name__ == '__main__':
unittest.main(argv=["TestInstall"])
9 changes: 5 additions & 4 deletions tools/skylark/drake_py.bzl
Expand Up @@ -158,7 +158,6 @@ def drake_py_binary(

def drake_py_unittest(
name,
srcs = [],
**kwargs):
"""Declares a `unittest`-based python test.

Expand All @@ -168,11 +167,13 @@ def drake_py_unittest(
to "small" to indicate a unit test.
"""
helper = "//common/test_utilities:drake_py_unittest_main.py"
if not srcs:
srcs = ["test/%s.py" % name]
if kwargs.pop("srcs", None):
fail("Changing srcs= is not allowed by drake_py_unittest." +
" Use drake_py_test instead, if you need something weird.")
srcs = ["test/%s.py" % name, helper]
drake_py_test(
name = name,
srcs = srcs + [helper],
srcs = srcs,
main = helper,
allow_import_unittest = True,
**kwargs
Expand Down