Skip to content

Commit

Permalink
pydrake: De-boilerplate deprecation unit tests (#10765)
Browse files Browse the repository at this point in the history
  • Loading branch information
jwnimmer-tri authored Feb 26, 2019
1 parent 6a8b847 commit d1e1c97
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 64 deletions.
47 changes: 47 additions & 0 deletions bindings/pydrake/common/test_utilities/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# -*- python -*-

load("//tools/lint:lint.bzl", "add_lint_tests")
load(
"@drake//tools/skylark:pybind.bzl",
"get_pybind_package_info",
)
load(
"@drake//tools/skylark:drake_py.bzl",
"drake_py_library",
)

package(default_visibility = [
"//bindings/pydrake:__subpackages__",
])

# This determines how `PYTHONPATH` is configured.
PACKAGE_INFO = get_pybind_package_info("//bindings")

drake_py_library(
name = "module_py",
srcs = ["__init__.py"],
imports = PACKAGE_INFO.py_imports,
deps = [
"//bindings/pydrake/common:module_py",
],
)

drake_py_library(
name = "deprecation_py",
srcs = ["deprecation.py"],
deps = [":module_py"],
)

# Package roll-up (for Bazel dependencies).
drake_py_library(
name = "test_utilities",
deps = [
":deprecation_py",
":module_py",
],
)

add_lint_tests(
cpplint_data = ["//bindings/pydrake:.clang-format"],
enable_clang_format_lint = True,
)
3 changes: 3 additions & 0 deletions bindings/pydrake/common/test_utilities/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
Utilities for unit testing.
"""
28 changes: 28 additions & 0 deletions bindings/pydrake/common/test_utilities/deprecation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
Utilities for unit testing deprecation.
"""

import contextlib
import warnings

from pydrake.common.deprecation import DrakeDeprecationWarning


def _check_expected(caught, expected_count):
if expected_count is None:
return
if len(caught) == expected_count:
return
raise ValueError(
"Expected {} deprecation warnings but got {} instead:\n".format(
expected_count, len(caught)) + "\n".join([str(x) for x in caught]))


@contextlib.contextmanager
def catch_drake_warnings(action="always", expected_count=None):
try:
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter(action, DrakeDeprecationWarning)
yield caught
finally:
_check_expected(caught, expected_count)
2 changes: 2 additions & 0 deletions bindings/pydrake/multibody/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ drake_py_unittest(
":multibody_tree_py",
":plant_py",
":tree_py",
"//bindings/pydrake/common/test_utilities",
],
)

Expand All @@ -241,6 +242,7 @@ drake_py_unittest(
deps = [
":benchmarks_py",
":inverse_kinematics_py",
"//bindings/pydrake/common/test_utilities",
],
)

Expand Down
26 changes: 6 additions & 20 deletions bindings/pydrake/multibody/test/inverse_kinematics_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import numpy as np
from numpy.linalg import norm

from pydrake.common.deprecation import DrakeDeprecationWarning
from pydrake.common import FindResourceOrThrow
from pydrake.common.eigen_geometry import Quaternion, AngleAxis, Isometry3
from pydrake.common.test_utilities.deprecation import catch_drake_warnings
from pydrake.math import RotationMatrix
from pydrake.multibody.plant import (
MultibodyPlant, AddMultibodyPlantSceneGraph)
Expand Down Expand Up @@ -102,13 +102,11 @@ def test_AddPositionConstraint(self):
self.assertTrue(np.less(p_AQ, p_AQ_upper +
1E-6 * np.ones((3, 1))).all())

with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always', DrakeDeprecationWarning)
with catch_drake_warnings(expected_count=2):
self.assertEqual(
self.prog.Solve(), mp.SolutionResult.kSolutionFound)
self.assertTrue(np.allclose(
self.prog.GetSolution(self.q), q_val))
self.assertEqual(len(w), 2)

def test_AddOrientationConstraint(self):
theta_bound = 0.2 * math.pi
Expand All @@ -133,9 +131,7 @@ def test_AddOrientationConstraint(self):
R_AbarBbar.dot(R_BbarB.matrix()))
self.assertGreater(R_AB.trace(), 1 + 2 * math.cos(theta_bound) - 1E-6)

with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always', DrakeDeprecationWarning)

with catch_drake_warnings(expected_count=2):
self.assertEqual(
self.prog.Solve(), mp.SolutionResult.kSolutionFound)
q_val = self.prog.GetSolution(self.q)
Expand All @@ -150,8 +146,6 @@ def test_AddOrientationConstraint(self):
self.assertGreater(R_AB.trace(),
1 + 2 * math.cos(theta_bound) - 1E-6)

self.assertEqual(len(w), 2)

def test_AddGazeTargetConstraint(self):
p_AS = np.array([0.1, 0.2, 0.3])
n_A = np.array([0.3, 0.5, 1.2])
Expand Down Expand Up @@ -181,9 +175,7 @@ def test_AddGazeTargetConstraint(self):
self.assertGreater(p_ST_W.dot(n_W), np.linalg.norm(
p_ST_W) * np.linalg.norm(n_W) * math.cos(cone_half_angle) - 1E-6)

with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always', DrakeDeprecationWarning)

with catch_drake_warnings(expected_count=2):
self.assertEqual(
self.prog.Solve(), mp.SolutionResult.kSolutionFound)
q_val = self.prog.GetSolution(self.q)
Expand All @@ -203,8 +195,6 @@ def test_AddGazeTargetConstraint(self):
p_ST_W) * np.linalg.norm(n_W) *
math.cos(cone_half_angle) - 1E-6)

self.assertEqual(len(w), 2)

def test_AddAngleBetweenVectorsConstraint(self):
na_A = np.array([0.2, -0.4, 0.9])
nb_B = np.array([1.4, -0.1, 1.8])
Expand Down Expand Up @@ -233,13 +223,11 @@ def test_AddAngleBetweenVectorsConstraint(self):

self.assertLess(math.fabs(angle - angle_lower), 1E-6)

with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always', DrakeDeprecationWarning)
with catch_drake_warnings(expected_count=2):
self.assertEqual(
self.prog.Solve(), mp.SolutionResult.kSolutionFound)
self.assertTrue(np.allclose(
self.prog.GetSolution(self.q), q_val))
self.assertEqual(len(w), 2)

def test_AddMinimumDistanceConstraint(self):
ik = self.ik_two_bodies
Expand Down Expand Up @@ -273,10 +261,8 @@ def get_min_distance_actual():
self.plant.SetPositions(context, q_val)
self.assertGreater(get_min_distance_actual(), min_distance - tol)

with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always', DrakeDeprecationWarning)
with catch_drake_warnings(expected_count=2):
self.assertEqual(
self.prog.Solve(), mp.SolutionResult.kSolutionFound)
self.assertTrue(np.allclose(
self.prog.GetSolution(ik.q()), q_val))
self.assertEqual(len(w), 2)
15 changes: 4 additions & 11 deletions bindings/pydrake/multibody/test/plant_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@
import numpy as np

from pydrake.common import FindResourceOrThrow
from pydrake.common.deprecation import (
DrakeDeprecationWarning,
)
from pydrake.common.eigen_geometry import Isometry3
from pydrake.common.test_utilities.deprecation import catch_drake_warnings
from pydrake.systems.framework import InputPort, OutputPort
from pydrake.math import RigidTransform, RollPitchYaw
from pydrake.systems.lcm import LcmPublisherSystem
Expand All @@ -66,15 +64,13 @@
# modules. Additionally, assert length of warnings here rather than in the test
# so that we do not have to worry about whether a module has already been
# loaded.
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("default", DrakeDeprecationWarning)
with catch_drake_warnings(expected_count=3):
from pydrake.multibody.multibody_tree import (
BodyNodeIndex,
MobilizerIndex,
MultibodyTree,
)
from pydrake.multibody.multibody_tree.parsing import AddModelFromSdfFile
assert len(w) == 3, len(w)


def get_index_class(cls):
Expand Down Expand Up @@ -220,11 +216,9 @@ def test_deprecated_parsing(self):
"drake/multibody/benchmarks/acrobot/acrobot.sdf")

plant = MultibodyPlant(time_step=0.01)
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("default", DrakeDeprecationWarning)
with catch_drake_warnings(expected_count=1):
result = AddModelFromSdfFile(plant=plant, file_name=sdf_file)
self.assertIsInstance(result, ModelInstanceIndex)
self.assertEqual(len(w), 1)

def check_old_spelling_exists(self, value):
# Just to make it obvious when this is being tested.
Expand Down Expand Up @@ -849,8 +843,7 @@ def test_deprecated_tree_api(self):
plant = MultibodyPlant()
plant.Finalize()

with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always', DrakeDeprecationWarning)
with catch_drake_warnings() as w:
num_expected_warnings = [0]

def expect_new_warning(msg_part):
Expand Down
6 changes: 5 additions & 1 deletion bindings/pydrake/solvers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,10 @@ drake_py_unittest(
"//tools:no_ipopt": ["TestIpoptSolver.unavailable"],
"//conditions:default": [],
}),
deps = [":ipopt_py"],
deps = [
":ipopt_py",
"//bindings/pydrake/common/test_utilities",
],
)

drake_py_unittest(
Expand All @@ -191,6 +194,7 @@ drake_py_unittest(
":gurobi_py",
":mathematicalprogram_py",
":snopt_py",
"//bindings/pydrake/common/test_utilities",
],
)

Expand Down
6 changes: 2 additions & 4 deletions bindings/pydrake/solvers/test/ipopt_solver_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import numpy as np

from pydrake.common.deprecation import DrakeDeprecationWarning
from pydrake.common.test_utilities.deprecation import catch_drake_warnings
from pydrake.solvers import mathematicalprogram as mp
from pydrake.solvers.ipopt import IpoptSolver

Expand Down Expand Up @@ -36,11 +36,9 @@ def test_ipopt_solver_deprecated(self):
# SolverBase method that writes the solution back into the program.
prog, x, x_expected = self._make_prog()
solver = IpoptSolver()
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always', DrakeDeprecationWarning)
with catch_drake_warnings(expected_count=2):
result = solver.Solve(prog)
solution = prog.GetSolution(x)
self.assertEqual(len(w), 2)
self.assertEqual(result, mp.SolutionResult.kSolutionFound)
self.assertTrue(np.allclose(solution, x_expected))

Expand Down
13 changes: 4 additions & 9 deletions bindings/pydrake/solvers/test/mathematicalprogram_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import numpy as np

import pydrake
from pydrake.common.deprecation import DrakeDeprecationWarning
from pydrake.common.test_utilities.deprecation import catch_drake_warnings
from pydrake.autodiffutils import AutoDiffXd
import pydrake.symbolic as sym

Expand Down Expand Up @@ -224,10 +224,8 @@ def test_bindings(self):
self.assertTrue(np.allclose(result.GetSolution(x), x_expected))

# Test deprecated method.
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('once', DrakeDeprecationWarning)
with catch_drake_warnings(expected_count=1):
c = binding.constraint()
self.assertEqual(len(w), 1)

def test_constraint_api(self):
prog = mp.MathematicalProgram()
Expand Down Expand Up @@ -293,9 +291,7 @@ def test_eval_binding(self):
constraints = qp.constraints
constraint_values_expected = [1., 1., 2., 3.]

with warnings.catch_warnings():
warnings.simplefilter('ignore', DrakeDeprecationWarning)

with catch_drake_warnings(action='ignore'):
prog.Solve()
self.assertTrue(np.allclose(prog.GetSolution(x), x_expected))

Expand Down Expand Up @@ -375,8 +371,7 @@ def test_sos(self):
self.assertTrue(result.is_success())

# Test SubstituteSolution(sym.Expression)
with warnings.catch_warnings():
warnings.simplefilter('ignore', DrakeDeprecationWarning)
with catch_drake_warnings(action='ignore'):
prog.Solve()
# TODO(eric.cousineau): Expose `SymbolicTestCase` so that other
# tests can use the assertion utilities.
Expand Down
2 changes: 2 additions & 0 deletions bindings/pydrake/systems/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ drake_py_unittest(
":framework_py",
":primitives_py",
":test_util_py",
"//bindings/pydrake/common/test_utilities",
],
)

Expand Down Expand Up @@ -449,6 +450,7 @@ drake_py_unittest(
name = "trajectory_optimization_test",
deps = [
":trajectory_optimization_py",
"//bindings/pydrake/common/test_utilities",
"//bindings/pydrake/examples:pendulum_py",
],
)
Expand Down
12 changes: 3 additions & 9 deletions bindings/pydrake/systems/test/custom_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@
call_vector_system_overrides,
)

from pydrake.common.deprecation import (
DrakeDeprecationWarning,
)
from pydrake.common.test_utilities.deprecation import catch_drake_warnings


def noop(*args, **kwargs):
Expand Down Expand Up @@ -390,10 +388,8 @@ def __init__(self):
self.assertEqual(
values.get_mutable_value(0).get_value(), model_value.get_value())
values.SetFrom(values.Clone())
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always", DrakeDeprecationWarning)
with catch_drake_warnings(expected_count=1):
values.CopyFrom(values.Clone())
self.assertEqual(len(w), 1)

# - Check diagram context accessors.
builder = DiagramBuilder()
Expand Down Expand Up @@ -514,10 +510,8 @@ def test_deprecated_abstract_input_port(self):
class ParseFloatSystem(LeafSystem_[float]):
def __init__(self):
LeafSystem_[float].__init__(self)
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("default", DrakeDeprecationWarning)
with catch_drake_warnings(expected_count=1):
self._DeclareAbstractInputPort("in")
test.assertEqual(len(w), 1)
self._DeclareVectorOutputPort("out", BasicVector(1), self._Out)

def _Out(self, context, y_data):
Expand Down
Loading

0 comments on commit d1e1c97

Please sign in to comment.