[tor-commits] [stem/master] Add assertRaisesWith testing helper

atagar at torproject.org atagar at torproject.org
Mon Aug 6 01:50:09 UTC 2018


commit 1c030e32539d1e10facbb2684c65103bca45b966
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Aug 5 18:42:19 2018 -0700

    Add assertRaisesWith testing helper
    
    Python's builtin unittest module provides an assertRaises and
    assertRaisesRegexp, but not a method to check for an exact match.
    Adding one so we can simplify things a bit.
    
      https://trac.torproject.org/projects/tor/ticket/26420
---
 setup.py                                           |  1 +
 stem/util/test_tools.py                            | 13 ++++++++
 test/integ/client/connection.py                    | 12 +++----
 test/integ/control/controller.py                   | 10 +++---
 test/integ/util/system.py                          |  4 +--
 test/unit/client/address.py                        |  9 +++--
 test/unit/client/cell.py                           | 37 ++++++++++-----------
 test/unit/client/size.py                           | 11 +++----
 test/unit/control/controller.py                    | 18 +++++-----
 test/unit/descriptor/certificate.py                | 38 ++++++++++++++--------
 test/unit/descriptor/extrainfo_descriptor.py       |  5 ++-
 test/unit/descriptor/hidden_service_descriptor.py  |  2 +-
 test/unit/descriptor/microdescriptor.py            |  4 +--
 .../networkstatus/directory_authority.py           |  2 +-
 test/unit/descriptor/networkstatus/document_v2.py  |  2 +-
 test/unit/descriptor/networkstatus/document_v3.py  |  7 ++--
 .../descriptor/networkstatus/key_certificate.py    |  2 +-
 test/unit/descriptor/remote.py                     |  7 ++--
 test/unit/descriptor/router_status_entry.py        |  6 ++--
 test/unit/descriptor/server_descriptor.py          |  8 ++---
 test/unit/exit_policy/rule.py                      |  5 ++-
 test/unit/manual.py                                | 15 ++++-----
 test/unit/util/proc.py                             |  3 +-
 23 files changed, 118 insertions(+), 103 deletions(-)

diff --git a/setup.py b/setup.py
index 7c6f2f97..5f786ded 100644
--- a/setup.py
+++ b/setup.py
@@ -72,6 +72,7 @@ MANIFEST = """
 include cache_fallback_directories.py
 include cache_manual.py
 include LICENSE
+include README.md
 include MANIFEST.in
 include requirements.txt
 include run_tests.py
diff --git a/stem/util/test_tools.py b/stem/util/test_tools.py
index c7573202..759c8238 100644
--- a/stem/util/test_tools.py
+++ b/stem/util/test_tools.py
@@ -266,6 +266,19 @@ class TimedTestRunner(unittest.TextTestRunner):
           else:
             return super(original_type, self).assertItemsEqual(expected, actual)
 
+        def assertRaisesWith(self, exc_type, exc_msg, func, *args, **kwargs):
+          """
+          Asserts the given invokation raises the expected excepiton. This is
+          similar to unittest's assertRaises and assertRaisesRegexp, but checks
+          for an exact match.
+
+          This method is **not** being vended to external users and may be
+          changed without notice. If you want this method to be part of our
+          vended API then please let us know.
+          """
+
+          return self.assertRaisesRegexp(exc_type, '^%s$' % re.escape(exc_msg), func, *args, **kwargs)
+
         def assertRaisesRegexp(self, exc_type, exc_msg, func, *args, **kwargs):
           if stem.prereq._is_python_26():
             try:
diff --git a/test/integ/client/connection.py b/test/integ/client/connection.py
index 94277d4f..a43283b9 100644
--- a/test/integ/client/connection.py
+++ b/test/integ/client/connection.py
@@ -17,21 +17,21 @@ class TestConnection(unittest.TestCase):
     Provide invalid arguments to Relay.connect().
     """
 
-    self.assertRaisesRegexp(ValueError, "'nope' isn't an IPv4 or IPv6 address", Relay.connect, 'nope', 80)
-    self.assertRaisesRegexp(ValueError, "'-54' isn't a valid port", Relay.connect, '127.0.0.1', -54)
-    self.assertRaisesRegexp(ValueError, "Connection can't be established without a link protocol.", Relay.connect, '127.0.0.1', 54, [])
+    self.assertRaisesWith(ValueError, "'nope' isn't an IPv4 or IPv6 address", Relay.connect, 'nope', 80)
+    self.assertRaisesWith(ValueError, "'-54' isn't a valid port", Relay.connect, '127.0.0.1', -54)
+    self.assertRaisesWith(ValueError, "Connection can't be established without a link protocol.", Relay.connect, '127.0.0.1', 54, [])
 
   def test_not_orport(self):
     """
     Attempt to connect to an ORPort that doesn't exist.
     """
 
-    self.assertRaisesRegexp(stem.SocketError, "Failed to connect to 127.0.0.1:1587. Maybe it isn't an ORPort?", Relay.connect, '127.0.0.1', 1587)
+    self.assertRaisesWith(stem.SocketError, "Failed to connect to 127.0.0.1:1587. Maybe it isn't an ORPort?", Relay.connect, '127.0.0.1', 1587)
 
     # connect to our ControlPort like it's an ORPort
 
     if test.runner.Torrc.PORT in test.runner.get_runner().get_options():
-      self.assertRaisesRegexp(stem.SocketError, "Failed to SSL authenticate to 127.0.0.1:1111. Maybe it isn't an ORPort?", Relay.connect, '127.0.0.1', test.runner.CONTROL_PORT)
+      self.assertRaisesWith(stem.SocketError, "Failed to SSL authenticate to 127.0.0.1:1111. Maybe it isn't an ORPort?", Relay.connect, '127.0.0.1', test.runner.CONTROL_PORT)
 
   def test_no_common_link_protocol(self):
     """
@@ -39,7 +39,7 @@ class TestConnection(unittest.TestCase):
     """
 
     for link_protocol in (1, 2, 6, 20):
-      self.assertRaisesRegexp(stem.SocketError, 'Unable to establish a common link protocol with 127.0.0.1:1113', Relay.connect, '127.0.0.1', test.runner.ORPORT, [link_protocol])
+      self.assertRaisesWith(stem.SocketError, 'Unable to establish a common link protocol with 127.0.0.1:1113', Relay.connect, '127.0.0.1', test.runner.ORPORT, [link_protocol])
 
   def test_connection_time(self):
     """
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 5c989889..a28300ba 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -534,7 +534,7 @@ class TestController(unittest.TestCase):
     with test.runner.get_runner().get_tor_controller() as controller:
       for ports in (4567890, [4567, 4567890], {4567: '-:4567'}):
         exc_msg = "ADD_ONION response didn't have an OK status: Invalid VIRTPORT/TARGET"
-        self.assertRaisesRegexp(stem.ProtocolError, exc_msg, controller.create_ephemeral_hidden_service, ports)
+        self.assertRaisesWith(stem.ProtocolError, exc_msg, controller.create_ephemeral_hidden_service, ports)
 
   @test.require.controller
   @test.require.version(Requirement.ADD_ONION)
@@ -658,7 +658,7 @@ class TestController(unittest.TestCase):
 
     with runner.get_tor_controller() as controller:
       exc_msg = "ADD_ONION response didn't have an OK status: No auth clients specified"
-      self.assertRaisesRegexp(stem.ProtocolError, exc_msg, controller.create_ephemeral_hidden_service, 4567, basic_auth = {})
+      self.assertRaisesWith(stem.ProtocolError, exc_msg, controller.create_ephemeral_hidden_service, 4567, basic_auth = {})
 
   @test.require.controller
   @test.require.version(Requirement.ADD_ONION)
@@ -789,8 +789,8 @@ class TestController(unittest.TestCase):
     """
 
     with test.runner.get_runner().get_tor_controller() as controller:
-      self.assertRaisesRegexp(stem.InvalidArguments, "DisableAllSwap cannot be changed while tor's running", controller.set_conf, 'DisableAllSwap', '1')
-      self.assertRaisesRegexp(stem.InvalidArguments, "DisableAllSwap, User cannot be changed while tor's running", controller.set_options, {'User': 'atagar', 'DisableAllSwap': '1'})
+      self.assertRaisesWith(stem.InvalidArguments, "DisableAllSwap cannot be changed while tor's running", controller.set_conf, 'DisableAllSwap', '1')
+      self.assertRaisesWith(stem.InvalidArguments, "DisableAllSwap, User cannot be changed while tor's running", controller.set_options, {'User': 'atagar', 'DisableAllSwap': '1'})
 
   @test.require.controller
   @test.require.version(Requirement.LOADCONF)
@@ -1294,7 +1294,7 @@ class TestController(unittest.TestCase):
       # try to fetch something that doesn't exist
 
       exc_msg = 'No running hidden service at m4cfuk6qp4lpu2g3.onion'
-      self.assertRaisesRegexp(stem.DescriptorUnavailable, exc_msg, controller.get_hidden_service_descriptor, 'm4cfuk6qp4lpu2g3')
+      self.assertRaisesWith(stem.DescriptorUnavailable, exc_msg, controller.get_hidden_service_descriptor, 'm4cfuk6qp4lpu2g3')
 
       # ... but shouldn't fail if we have a default argument or aren't awaiting the descriptor
 
diff --git a/test/integ/util/system.py b/test/integ/util/system.py
index cad94df2..cc6f9eda 100644
--- a/test/integ/util/system.py
+++ b/test/integ/util/system.py
@@ -102,7 +102,7 @@ class TestSystem(unittest.TestCase):
     self.assertEqual(State.PENDING, task.status)
 
     task.run()
-    self.assertRaisesRegexp(RuntimeError, 'hello world', task.join)
+    self.assertRaisesWith(RuntimeError, 'hello world', task.join)
     self.assertEqual(State.FAILED, task.status)
     self.assertTrue(0 < task.runtime < 1.0)
 
@@ -531,7 +531,7 @@ class TestSystem(unittest.TestCase):
     self.assertEqual(os.path.join(home_dir, 'foo'), stem.util.system.expand_path('~%s/foo' % username))
 
   def test_call_timeout(self):
-    self.assertRaisesRegexp(stem.util.system.CallTimeoutError, "Process didn't finish after 0.0 seconds", stem.util.system.call, 'sleep 1', timeout = 0.001)
+    self.assertRaisesWith(stem.util.system.CallTimeoutError, "Process didn't finish after 0.0 seconds", stem.util.system.call, 'sleep 1', timeout = 0.001)
 
   def test_call_time_tracked(self):
     """
diff --git a/test/unit/client/address.py b/test/unit/client/address.py
index aaa5fc0e..c4e51f4e 100644
--- a/test/unit/client/address.py
+++ b/test/unit/client/address.py
@@ -3,7 +3,6 @@ Unit tests for stem.client.Address.
 """
 
 import collections
-import re
 import unittest
 
 from stem.client.datatype import AddrType, Address
@@ -17,7 +16,7 @@ class TestAddress(unittest.TestCase):
     self.assertEqual(('IPv4', 4), AddrType.get(4))
 
     self.assertEqual(('UNKNOWN', 25), AddrType.get(25))
-    self.assertRaisesRegexp(ValueError, "Invalid enumeration 'boom', options are HOSTNAME, IPv4, IPv6, ERROR_TRANSIENT, ERROR_PERMANENT, UNKNOWN", AddrType.get, 'boom')
+    self.assertRaisesWith(ValueError, "Invalid enumeration 'boom', options are HOSTNAME, IPv4, IPv6, ERROR_TRANSIENT, ERROR_PERMANENT, UNKNOWN", AddrType.get, 'boom')
 
   def test_constructor(self):
     test_data = (
@@ -42,9 +41,9 @@ class TestAddress(unittest.TestCase):
     self.assertEqual(AddrType.IPv4, Address('127.0.0.1').type)
     self.assertEqual(AddrType.IPv6, Address('2001:0DB8:AC10:FE01::').type)
 
-    self.assertRaisesRegexp(ValueError, re.escape("Packed IPv4 addresses should be four bytes, but was: '\\x7f\\x00'"), Address, '\x7f\x00', 4)
-    self.assertRaisesRegexp(ValueError, re.escape("Packed IPv6 addresses should be sixteen bytes, but was: '\\x7f\\x00'"), Address, '\x7f\x00', 6)
-    self.assertRaisesRegexp(ValueError, re.escape("'nope' isn't an IPv4 or IPv6 address"), Address, 'nope')
+    self.assertRaisesWith(ValueError, "Packed IPv4 addresses should be four bytes, but was: '\\x7f\\x00'", Address, '\x7f\x00', 4)
+    self.assertRaisesWith(ValueError, "Packed IPv6 addresses should be sixteen bytes, but was: '\\x7f\\x00'", Address, '\x7f\x00', 6)
+    self.assertRaisesWith(ValueError, "'nope' isn't an IPv4 or IPv6 address", Address, 'nope')
 
   def test_unknown_type(self):
     addr = Address('hello', 12)
diff --git a/test/unit/client/cell.py b/test/unit/client/cell.py
index 9be0f73b..ce492638 100644
--- a/test/unit/client/cell.py
+++ b/test/unit/client/cell.py
@@ -5,7 +5,6 @@ Unit tests for the stem.client.cell.
 import datetime
 import hashlib
 import os
-import re
 import unittest
 
 from stem.client.datatype import ZERO, CertType, CloseReason, Address, Certificate
@@ -115,8 +114,8 @@ class TestCell(unittest.TestCase):
   def test_unimplemented_cell_methods(self):
     cell_instance = Cell()
 
-    self.assertRaisesRegexp(NotImplementedError, re.escape('Packing not yet implemented for UNKNOWN cells'), cell_instance.pack, 2)
-    self.assertRaisesRegexp(NotImplementedError, re.escape('Unpacking not yet implemented for UNKNOWN cells'), cell_instance._unpack, b'dummy', 0, 2)
+    self.assertRaisesWith(NotImplementedError, 'Packing not yet implemented for UNKNOWN cells', cell_instance.pack, 2)
+    self.assertRaisesWith(NotImplementedError, 'Unpacking not yet implemented for UNKNOWN cells', cell_instance._unpack, b'dummy', 0, 2)
 
   def test_payload_too_large(self):
     class OversizedCell(Cell):
@@ -130,20 +129,20 @@ class TestCell(unittest.TestCase):
     instance = OversizedCell()
 
     expected_message = 'Cell of type OVERSIZED is too large (%i bytes), must not be more than %i. Check payload size (was %i bytes)' % (FIXED_PAYLOAD_LEN + 4, FIXED_PAYLOAD_LEN + 3, FIXED_PAYLOAD_LEN + 1)
-    self.assertRaisesRegexp(ValueError, re.escape(expected_message), instance.pack, 2)
+    self.assertRaisesWith(ValueError, expected_message, instance.pack, 2)
 
   def test_circuit_id_validation(self):
     # only CircuitCell subclasses should provide a circ_id
 
-    self.assertRaisesRegexp(ValueError, 'PADDING cells should not specify a circuit identifier', PaddingCell._pack, 5, b'', circ_id = 12)
+    self.assertRaisesWith(ValueError, 'PADDING cells should not specify a circuit identifier', PaddingCell._pack, 5, b'', circ_id = 12)
 
     # CircuitCell should validate its circ_id
 
-    self.assertRaisesRegexp(ValueError, 'RELAY cells require a circuit identifier', RelayCell._pack, 5, b'', circ_id = None)
+    self.assertRaisesWith(ValueError, 'RELAY cells require a circuit identifier', RelayCell._pack, 5, b'', circ_id = None)
 
     for circ_id in (0, -1, -50):
       expected_msg = 'Circuit identifiers must a positive integer, not %s' % circ_id
-      self.assertRaisesRegexp(ValueError, expected_msg, RelayCell._pack, 5, b'', circ_id = circ_id)
+      self.assertRaisesWith(ValueError, expected_msg, RelayCell._pack, 5, b'', circ_id = circ_id)
 
   def test_unpack_for_new_link(self):
     expected_certs = (
@@ -212,7 +211,7 @@ class TestCell(unittest.TestCase):
     self.assertEqual(3257622417, RelayCell(5, 'RELAY_BEGIN_DIR', '', digest, 564346860).digest)
     self.assertEqual(3257622417, RelayCell(5, 'RELAY_BEGIN_DIR', '', digest.digest(), 564346860).digest)
     self.assertEqual(3257622417, RelayCell(5, 'RELAY_BEGIN_DIR', '', 3257622417, 564346860).digest)
-    self.assertRaisesRegexp(ValueError, 'RELAY cell digest must be a hash, string, or int but was a list', RelayCell, 5, 'RELAY_BEGIN_DIR', '', [], 564346860)
+    self.assertRaisesWith(ValueError, 'RELAY cell digest must be a hash, string, or int but was a list', RelayCell, 5, 'RELAY_BEGIN_DIR', '', [], 564346860)
     self.assertRaisesRegexp(ValueError, "Invalid enumeration 'NO_SUCH_COMMAND', options are RELAY_BEGIN, RELAY_DATA", RelayCell, 5, 'NO_SUCH_COMMAND', '', 5, 564346860)
 
     mismatched_data_length_bytes = b''.join((
@@ -225,8 +224,8 @@ class TestCell(unittest.TestCase):
       b'\xFF\xFF',  # data len (65535, clearly invalid)
       ZERO * 498,  # data
     ))
-    expected_message = 'RELAY cell said it had 65535 bytes of data, but only had 498'
-    self.assertRaisesRegexp(ValueError, '^%s$' % re.escape(expected_message), Cell.pop, mismatched_data_length_bytes, 2)
+
+    self.assertRaisesWith(ValueError, 'RELAY cell said it had 65535 bytes of data, but only had 498', Cell.pop, mismatched_data_length_bytes, 2)
 
   def test_destroy_cell(self):
     for cell_bytes, (circ_id, reason, reason_int, unused, link_protocol) in DESTROY_CELLS.items():
@@ -257,7 +256,7 @@ class TestCell(unittest.TestCase):
       self.assertEqual(unused, cell.unused)
       self.assertEqual(cell_bytes, cell.pack(link_protocol))
 
-    self.assertRaisesRegexp(ValueError, 'Key material should be 20 bytes, but was 3', CreateFastCell, 5, 'boo')
+    self.assertRaisesWith(ValueError, 'Key material should be 20 bytes, but was 3', CreateFastCell, 5, 'boo')
 
   def test_created_fast_cell(self):
     for cell_bytes, (circ_id, key_material, derivative_key, unused, link_protocol) in CREATED_FAST_CELLS.items():
@@ -273,7 +272,7 @@ class TestCell(unittest.TestCase):
       self.assertEqual(unused, cell.unused)
       self.assertEqual(cell_bytes, cell.pack(link_protocol))
 
-    self.assertRaisesRegexp(ValueError, 'Key material should be 20 bytes, but was 3', CreateFastCell, 5, 'boo')
+    self.assertRaisesWith(ValueError, 'Key material should be 20 bytes, but was 3', CreateFastCell, 5, 'boo')
 
   def test_versions_cell(self):
     for cell_bytes, (versions, link_protocol) in VERSIONS_CELLS.items():
@@ -311,9 +310,9 @@ class TestCell(unittest.TestCase):
     self.assertEqual(VPADDING_CELL_EMPTY_PACKED, empty_constructed_cell.pack(2))
     self.assertEqual(b'', empty_constructed_cell.payload)
 
-    self.assertRaisesRegexp(ValueError, 'VPaddingCell constructor specified both a size of 5 bytes and payload of 1 bytes', VPaddingCell, 5, '\x02')
-    self.assertRaisesRegexp(ValueError, re.escape('VPaddingCell size (-15) cannot be negative'), VPaddingCell, -15)
-    self.assertRaisesRegexp(ValueError, re.escape('VPaddingCell constructor must specify payload or size'), VPaddingCell)
+    self.assertRaisesWith(ValueError, 'VPaddingCell constructor specified both a size of 5 bytes and payload of 1 bytes', VPaddingCell, 5, '\x02')
+    self.assertRaisesWith(ValueError, 'VPaddingCell size (-15) cannot be negative', VPaddingCell, -15)
+    self.assertRaisesWith(ValueError, 'VPaddingCell constructor must specify payload or size', VPaddingCell)
 
   def test_certs_cell(self):
     for cell_bytes, (certs, unused, link_protocol) in CERTS_CELLS.items():
@@ -329,8 +328,8 @@ class TestCell(unittest.TestCase):
 
     # truncated or missing certificates should error
 
-    self.assertRaisesRegexp(ValueError, 'CERTS cell should have a certificate with 3 bytes, but only had 1 remaining', Cell.pop, b'\x00\x00\x81\x00\x05\x01\x01\x00\x03\x08', 2)
-    self.assertRaisesRegexp(ValueError, 'CERTS cell indicates it should have 2 certificates, but only contained 1', Cell.pop, b'\x00\x00\x81\x00\x05\x02\x01\x00\x01\x08', 2)
+    self.assertRaisesWith(ValueError, 'CERTS cell should have a certificate with 3 bytes, but only had 1 remaining', Cell.pop, b'\x00\x00\x81\x00\x05\x01\x01\x00\x03\x08', 2)
+    self.assertRaisesWith(ValueError, 'CERTS cell indicates it should have 2 certificates, but only contained 1', Cell.pop, b'\x00\x00\x81\x00\x05\x02\x01\x00\x01\x08', 2)
 
   def test_auth_challenge_cell(self):
     for cell_bytes, (challenge, methods, unused, link_protocol) in AUTH_CHALLENGE_CELLS.items():
@@ -345,5 +344,5 @@ class TestCell(unittest.TestCase):
       self.assertEqual(unused, cell.unused)
       self.assertEqual(cell_bytes, cell.pack(link_protocol))
 
-    self.assertRaisesRegexp(ValueError, 'AUTH_CHALLENGE cell should have a payload of 38 bytes, but only had 16', Cell.pop, b'\x00\x00\x82\x00&' + CHALLENGE[:10] + b'\x00\x02\x00\x01\x00\x03', 2)
-    self.assertRaisesRegexp(ValueError, 'AUTH_CHALLENGE should have 3 methods, but only had 4 bytes for it', Cell.pop, b'\x00\x00\x82\x00&' + CHALLENGE + b'\x00\x03\x00\x01\x00\x03', 2)
+    self.assertRaisesWith(ValueError, 'AUTH_CHALLENGE cell should have a payload of 38 bytes, but only had 16', Cell.pop, b'\x00\x00\x82\x00&' + CHALLENGE[:10] + b'\x00\x02\x00\x01\x00\x03', 2)
+    self.assertRaisesWith(ValueError, 'AUTH_CHALLENGE should have 3 methods, but only had 4 bytes for it', Cell.pop, b'\x00\x00\x82\x00&' + CHALLENGE + b'\x00\x03\x00\x01\x00\x03', 2)
diff --git a/test/unit/client/size.py b/test/unit/client/size.py
index 392c77ff..ea08a0d5 100644
--- a/test/unit/client/size.py
+++ b/test/unit/client/size.py
@@ -2,7 +2,6 @@
 Unit tests for stem.client.Size.
 """
 
-import re
 import unittest
 
 from stem.client.datatype import Size
@@ -24,10 +23,10 @@ class TestSize(unittest.TestCase):
     self.assertEqual(b'\x00\x00\x00\x12', Size.LONG.pack(18))
     self.assertEqual(b'\x00\x00\x00\x00\x00\x00\x00\x12', Size.LONG_LONG.pack(18))
 
-    self.assertRaisesRegexp(ValueError, 'Size.pack encodes an integer, but was a str', Size.CHAR.pack, 'hi')
+    self.assertRaisesWith(ValueError, 'Size.pack encodes an integer, but was a str', Size.CHAR.pack, 'hi')
 
     bad_size = Size('BAD_SIZE', 1, '!H')
-    self.assertRaisesRegexp(ValueError, re.escape("'\\x00\\x12' is the wrong size for a BAD_SIZE field"), bad_size.pack, 18)
+    self.assertRaisesWith(ValueError, "'\\x00\\x12' is the wrong size for a BAD_SIZE field", bad_size.pack, 18)
 
   def test_unpack(self):
     self.assertEqual(18, Size.CHAR.unpack(b'\x12'))
@@ -38,7 +37,7 @@ class TestSize(unittest.TestCase):
     self.assertEqual(ord('a'), Size.CHAR.unpack(b'a'))
     self.assertEqual(24930, Size.SHORT.unpack(b'ab'))
 
-    self.assertRaisesRegexp(ValueError, re.escape("'\\x00\\x12' is the wrong size for a CHAR field"), Size.CHAR.unpack, '\x00\x12')
+    self.assertRaisesWith(ValueError, "'\\x00\\x12' is the wrong size for a CHAR field", Size.CHAR.unpack, '\x00\x12')
 
   def test_pop(self):
     self.assertEqual((18, b''), Size.CHAR.pop(b'\x12'))
@@ -46,5 +45,5 @@ class TestSize(unittest.TestCase):
     self.assertEqual((0, b'\x12'), Size.CHAR.pop(b'\x00\x12'))
     self.assertEqual((18, b''), Size.SHORT.pop(b'\x00\x12'))
 
-    self.assertRaisesRegexp(ValueError, "'' is the wrong size for a CHAR field", Size.CHAR.pop, '')
-    self.assertRaisesRegexp(ValueError, re.escape("'\\x12' is the wrong size for a SHORT field"), Size.SHORT.pop, '\x12')
+    self.assertRaisesWith(ValueError, "'' is the wrong size for a CHAR field", Size.CHAR.pop, '')
+    self.assertRaisesWith(ValueError, "'\\x12' is the wrong size for a SHORT field", Size.SHORT.pop, '\x12')
diff --git a/test/unit/control/controller.py b/test/unit/control/controller.py
index 3bdb7dce..6f162899 100644
--- a/test/unit/control/controller.py
+++ b/test/unit/control/controller.py
@@ -58,19 +58,19 @@ class TestControl(unittest.TestCase):
     msg_mock.return_value = ControlMessage.from_str('551 Address unknown\r\n')
 
     self.assertEqual(None, self.controller._last_address_exc)
-    self.assertRaisesRegexp(stem.OperationFailed, 'Address unknown', self.controller.get_info, 'address')
+    self.assertRaisesWith(stem.OperationFailed, 'Address unknown', self.controller.get_info, 'address')
     self.assertEqual('Address unknown', str(self.controller._last_address_exc))
     self.assertEqual(1, msg_mock.call_count)
 
     # now that we have a cached failure we should provide that back
 
-    self.assertRaisesRegexp(stem.OperationFailed, 'Address unknown', self.controller.get_info, 'address')
+    self.assertRaisesWith(stem.OperationFailed, 'Address unknown', self.controller.get_info, 'address')
     self.assertEqual(1, msg_mock.call_count)
 
     # invalidates the cache, transitioning from no address to having one
 
     msg_mock.return_value = ControlMessage.from_str('250-address=17.2.89.80\r\n250 OK\r\n', 'GETINFO')
-    self.assertRaisesRegexp(stem.OperationFailed, 'Address unknown', self.controller.get_info, 'address')
+    self.assertRaisesWith(stem.OperationFailed, 'Address unknown', self.controller.get_info, 'address')
     self.controller._handle_event(ControlMessage.from_str('650 STATUS_SERVER NOTICE EXTERNAL_ADDRESS ADDRESS=17.2.89.80 METHOD=DIRSERV\r\n'))
     self.assertEqual('17.2.89.80', self.controller.get_info('address'))
 
@@ -88,19 +88,19 @@ class TestControl(unittest.TestCase):
     get_conf_mock.return_value = None
 
     self.assertEqual(None, self.controller._last_fingerprint_exc)
-    self.assertRaisesRegexp(stem.OperationFailed, 'Not running in server mode', self.controller.get_info, 'fingerprint')
+    self.assertRaisesWith(stem.OperationFailed, 'Not running in server mode', self.controller.get_info, 'fingerprint')
     self.assertEqual('Not running in server mode', str(self.controller._last_fingerprint_exc))
     self.assertEqual(1, msg_mock.call_count)
 
     # now that we have a cached failure we should provide that back
 
-    self.assertRaisesRegexp(stem.OperationFailed, 'Not running in server mode', self.controller.get_info, 'fingerprint')
+    self.assertRaisesWith(stem.OperationFailed, 'Not running in server mode', self.controller.get_info, 'fingerprint')
     self.assertEqual(1, msg_mock.call_count)
 
     # ... but if we become a relay we'll call it again
 
     get_conf_mock.return_value = '443'
-    self.assertRaisesRegexp(stem.OperationFailed, 'Not running in server mode', self.controller.get_info, 'fingerprint')
+    self.assertRaisesWith(stem.OperationFailed, 'Not running in server mode', self.controller.get_info, 'fingerprint')
     self.assertEqual(2, msg_mock.call_count)
 
   @patch('stem.control.Controller.get_info')
@@ -512,7 +512,7 @@ class TestControl(unittest.TestCase):
     get_info_mock.side_effect = ControllerError('nope, too bad')
 
     exc_msg = 'Unable to determine our own fingerprint: nope, too bad'
-    self.assertRaisesRegexp(ControllerError, exc_msg, self.controller.get_network_status)
+    self.assertRaisesWith(ControllerError, exc_msg, self.controller.get_network_status)
     self.assertEqual('boom', self.controller.get_network_status(default = 'boom'))
 
     # successful request
@@ -535,7 +535,7 @@ class TestControl(unittest.TestCase):
     get_info_mock.side_effect = InvalidArguments(None, 'GETINFO request contained unrecognized keywords: ns/id/5AC9C5AA75BA1F18D8459B326B4B8111A856D290')
 
     exc_msg = "Tor was unable to provide the descriptor for '5AC9C5AA75BA1F18D8459B326B4B8111A856D290'"
-    self.assertRaisesRegexp(DescriptorUnavailable, exc_msg, self.controller.get_network_status, '5AC9C5AA75BA1F18D8459B326B4B8111A856D290')
+    self.assertRaisesWith(DescriptorUnavailable, exc_msg, self.controller.get_network_status, '5AC9C5AA75BA1F18D8459B326B4B8111A856D290')
 
   @patch('stem.control.Controller.get_info')
   def test_get_network_status(self, get_info_mock):
@@ -618,7 +618,7 @@ class TestControl(unittest.TestCase):
     that we raise a Timeout exception when it's elapsed.
     """
 
-    self.assertRaisesRegexp(stem.Timeout, 'Reached our 0.1 second timeout', self.controller.get_hidden_service_descriptor, '5g2upl4pq6kufc4m', await_result = True, timeout = 0.1)
+    self.assertRaisesWith(stem.Timeout, 'Reached our 0.1 second timeout', self.controller.get_hidden_service_descriptor, '5g2upl4pq6kufc4m', await_result = True, timeout = 0.1)
 
   def test_get_streams(self):
     """
diff --git a/test/unit/descriptor/certificate.py b/test/unit/descriptor/certificate.py
index 19d7c64d..28e0d20b 100644
--- a/test/unit/descriptor/certificate.py
+++ b/test/unit/descriptor/certificate.py
@@ -47,9 +47,6 @@ def certificate(version = 1, cert_type = 4, extension_data = []):
 
 
 class TestEd25519Certificate(unittest.TestCase):
-  def assert_raises(self, parse_arg, exc_msg):
-    self.assertRaisesRegexp(ValueError, re.escape(exc_msg), Ed25519Certificate.parse, parse_arg)
-
   def test_basic_parsing(self):
     """
     Parse a basic test certificate.
@@ -98,15 +95,19 @@ class TestEd25519Certificate(unittest.TestCase):
     Parse data that isn't base64 encoded.
     """
 
-    self.assert_raises('\x02\x0323\x04', "Ed25519 certificate wasn't propoerly base64 encoded (Incorrect padding):")
+    exc_msg = re.escape("Ed25519 certificate wasn't propoerly base64 encoded (Incorrect padding):")
+    self.assertRaisesRegexp(ValueError, exc_msg, Ed25519Certificate.parse, '\x02\x0323\x04')
 
   def test_too_short(self):
     """
     Parse data that's too short to be a valid certificate.
     """
 
-    self.assert_raises('', "Ed25519 certificate wasn't propoerly base64 encoded (empty):")
-    self.assert_raises('AQQABhtZAaW2GoBED1IjY3A6', 'Ed25519 certificate was 18 bytes, but should be at least 104')
+    exc_msg = "Ed25519 certificate wasn't propoerly base64 encoded (empty):"
+    self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, '')
+
+    exc_msg = 'Ed25519 certificate was 18 bytes, but should be at least 104'
+    self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, 'AQQABhtZAaW2GoBED1IjY3A6')
 
   def test_with_invalid_version(self):
     """
@@ -114,7 +115,8 @@ class TestEd25519Certificate(unittest.TestCase):
     Assert we raise if we don't handle a cert version yet.
     """
 
-    self.assert_raises(certificate(version = 2), 'Ed25519 certificate is version 2. Parser presently only supports version 1.')
+    exc_msg = 'Ed25519 certificate is version 2. Parser presently only supports version 1.'
+    self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, certificate(version = 2))
 
   def test_with_invalid_cert_type(self):
     """
@@ -122,30 +124,38 @@ class TestEd25519Certificate(unittest.TestCase):
     are reserved.
     """
 
-    self.assert_raises(certificate(cert_type = 0), 'Ed25519 certificate cannot have a type of 0. This is reserved to avoid conflicts with tor CERTS cells.')
-    self.assert_raises(certificate(cert_type = 7), 'Ed25519 certificate cannot have a type of 7. This is reserved for RSA identity cross-certification.')
+    exc_msg = 'Ed25519 certificate cannot have a type of 0. This is reserved to avoid conflicts with tor CERTS cells.'
+    self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, certificate(cert_type = 0))
+
+    exc_msg = 'Ed25519 certificate cannot have a type of 7. This is reserved for RSA identity cross-certification.'
+    self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, certificate(cert_type = 7))
 
   def test_truncated_extension(self):
     """
     Include an extension without as much data as it specifies.
     """
 
-    self.assert_raises(certificate(extension_data = [b'']), 'Ed25519 extension is missing header field data')
-    self.assert_raises(certificate(extension_data = [b'\x50\x00\x00\x00\x15\x12']), "Ed25519 extension is truncated. It should have 20480 bytes of data but there's only 2.")
+    exc_msg = 'Ed25519 extension is missing header field data'
+    self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, certificate(extension_data = [b'']))
+
+    exc_msg = "Ed25519 extension is truncated. It should have 20480 bytes of data but there's only 2."
+    self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, certificate(extension_data = [b'\x50\x00\x00\x00\x15\x12']))
 
   def test_extra_extension_data(self):
     """
     Include an extension with more data than it specifies.
     """
 
-    self.assert_raises(certificate(extension_data = [b'\x00\x01\x00\x00\x15\x12']), "Ed25519 certificate had 1 bytes of unused extension data")
+    exc_msg = 'Ed25519 certificate had 1 bytes of unused extension data'
+    self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, certificate(extension_data = [b'\x00\x01\x00\x00\x15\x12']))
 
   def test_truncated_signing_key(self):
     """
     Include an extension with an incorrect signing key size.
     """
 
-    self.assert_raises(certificate(extension_data = [b'\x00\x02\x04\x07\11\12']), "Ed25519 HAS_SIGNING_KEY extension must be 32 bytes, but was 2.")
+    exc_msg = 'Ed25519 HAS_SIGNING_KEY extension must be 32 bytes, but was 2.'
+    self.assertRaisesWith(ValueError, exc_msg, Ed25519Certificate.parse, certificate(extension_data = [b'\x00\x02\x04\x07\11\12']))
 
   @test.require.pynacl
   def test_validation_with_descriptor_key(self):
@@ -182,4 +192,4 @@ class TestEd25519Certificate(unittest.TestCase):
       desc = next(stem.descriptor.parse_file(descriptor_file, validate = False))
 
     cert = Ed25519Certificate.parse(certificate())
-    self.assertRaisesRegexp(ValueError, re.escape('Ed25519KeyCertificate signing key is invalid (Signature was forged or corrupt)'), cert.validate, desc)
+    self.assertRaisesWith(ValueError, 'Ed25519KeyCertificate signing key is invalid (Signature was forged or corrupt)', cert.validate, desc)
diff --git a/test/unit/descriptor/extrainfo_descriptor.py b/test/unit/descriptor/extrainfo_descriptor.py
index aa14b460..d649040a 100644
--- a/test/unit/descriptor/extrainfo_descriptor.py
+++ b/test/unit/descriptor/extrainfo_descriptor.py
@@ -4,7 +4,6 @@ Unit tests for stem.descriptor.extrainfo_descriptor.
 
 import datetime
 import functools
-import re
 import unittest
 
 import stem.descriptor
@@ -137,7 +136,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw
   @test.require.cryptography
   def test_descriptor_signing(self):
     RelayExtraInfoDescriptor.create(sign = True)
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of BridgeExtraInfoDescriptor not implemented', BridgeExtraInfoDescriptor.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of BridgeExtraInfoDescriptor not implemented', BridgeExtraInfoDescriptor.create, sign = True)
 
   def test_multiple_metrics_bridge_descriptors(self):
     """
@@ -192,7 +191,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw
     with open(get_resource('unparseable/extrainfo_nonascii_v3_reqs'), 'rb') as descriptor_file:
       desc_generator = stem.descriptor.parse_file(descriptor_file, 'extra-info 1.0', validate = True)
       exc_msg = "'dirreq-v3-reqs' line had non-ascii content: S?=4026597208,S?=4026597208,S?=4026597208,S?=4026597208,S?=4026597208,S?=4026597208,??=4026591624,6?=4026537520,6?=4026537520,6?=4026537520,us=8"
-      self.assertRaisesRegexp(ValueError, re.escape(exc_msg), next, desc_generator)
+      self.assertRaisesWith(ValueError, exc_msg, next, desc_generator)
 
   def test_minimal_extrainfo_descriptor(self):
     """
diff --git a/test/unit/descriptor/hidden_service_descriptor.py b/test/unit/descriptor/hidden_service_descriptor.py
index 1e8c135a..23067c62 100644
--- a/test/unit/descriptor/hidden_service_descriptor.py
+++ b/test/unit/descriptor/hidden_service_descriptor.py
@@ -275,7 +275,7 @@ class TestHiddenServiceDescriptor(unittest.TestCase):
 
   @test.require.cryptography
   def test_descriptor_signing(self):
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of HiddenServiceDescriptor not implemented', HiddenServiceDescriptor.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of HiddenServiceDescriptor not implemented', HiddenServiceDescriptor.create, sign = True)
 
   @test.require.cryptography
   def test_with_basic_auth(self):
diff --git a/test/unit/descriptor/microdescriptor.py b/test/unit/descriptor/microdescriptor.py
index 4fd14f5b..5f245619 100644
--- a/test/unit/descriptor/microdescriptor.py
+++ b/test/unit/descriptor/microdescriptor.py
@@ -95,7 +95,7 @@ class TestMicrodescriptor(unittest.TestCase):
 
   @test.require.cryptography
   def test_descriptor_signing(self):
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of Microdescriptor not implemented', Microdescriptor.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of Microdescriptor not implemented', Microdescriptor.create, sign = True)
 
   def test_unrecognized_line(self):
     """
@@ -205,4 +205,4 @@ class TestMicrodescriptor(unittest.TestCase):
     self.assertEqual({}, desc.identifiers)
 
     exc_msg = "There can only be one 'id' line per a key type, but 'rsa1024' appeared multiple times"
-    self.assertRaisesRegexp(ValueError, exc_msg, Microdescriptor, desc_text, validate = True)
+    self.assertRaisesWith(ValueError, exc_msg, Microdescriptor, desc_text, validate = True)
diff --git a/test/unit/descriptor/networkstatus/directory_authority.py b/test/unit/descriptor/networkstatus/directory_authority.py
index 81ad4a55..80d70927 100644
--- a/test/unit/descriptor/networkstatus/directory_authority.py
+++ b/test/unit/descriptor/networkstatus/directory_authority.py
@@ -54,7 +54,7 @@ class TestDirectoryAuthority(unittest.TestCase):
 
   @test.require.cryptography
   def test_descriptor_signing(self):
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of DirectoryAuthority not implemented', DirectoryAuthority.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of DirectoryAuthority not implemented', DirectoryAuthority.create, sign = True)
 
   def test_unrecognized_line(self):
     """
diff --git a/test/unit/descriptor/networkstatus/document_v2.py b/test/unit/descriptor/networkstatus/document_v2.py
index 5ff66eaf..a02ea7a5 100644
--- a/test/unit/descriptor/networkstatus/document_v2.py
+++ b/test/unit/descriptor/networkstatus/document_v2.py
@@ -106,4 +106,4 @@ TpQQk3nNQF8z6UIvdlvP+DnJV4izWVkQEZgUZgIVM0E=
 
   @test.require.cryptography
   def test_descriptor_signing(self):
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of NetworkStatusDocumentV2 not implemented', NetworkStatusDocumentV2.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of NetworkStatusDocumentV2 not implemented', NetworkStatusDocumentV2.create, sign = True)
diff --git a/test/unit/descriptor/networkstatus/document_v3.py b/test/unit/descriptor/networkstatus/document_v3.py
index b15a9aac..18d9088a 100644
--- a/test/unit/descriptor/networkstatus/document_v3.py
+++ b/test/unit/descriptor/networkstatus/document_v3.py
@@ -4,7 +4,6 @@ Unit tests for the NetworkStatusDocumentV3 of stem.descriptor.networkstatus.
 
 import datetime
 import io
-import re
 import unittest
 
 import stem.descriptor
@@ -367,7 +366,7 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w=
 
   @test.require.cryptography
   def test_descriptor_signing(self):
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of NetworkStatusDocumentV3 not implemented', NetworkStatusDocumentV3.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of NetworkStatusDocumentV3 not implemented', NetworkStatusDocumentV3.create, sign = True)
 
   def test_examples(self):
     """
@@ -413,7 +412,7 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w=
     # change a relay's nickname in the consensus so it's no longer validly signed
 
     consensus = stem.descriptor.networkstatus.NetworkStatusDocumentV3(consensus_content.replace(b'test002r', b'different_nickname'))
-    self.assertRaisesRegexp(ValueError, 'Network Status Document has 0 valid signatures out of 2 total, needed 1', consensus.validate_signatures, certs)
+    self.assertRaisesWith(ValueError, 'Network Status Document has 0 valid signatures out of 2 total, needed 1', consensus.validate_signatures, certs)
 
   def test_handlers(self):
     """
@@ -1246,7 +1245,7 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w=
 
     for attr, expected_exception in test_values:
       content = DirectoryAuthority.content(attr)
-      self.assertRaisesRegexp(ValueError, re.escape(expected_exception), DirectoryAuthority, content, True)
+      self.assertRaisesWith(ValueError, expected_exception, DirectoryAuthority, content, True)
 
       authority = DirectoryAuthority(content, False)
       self.assertEqual([], authority.shared_randomness_commitments)
diff --git a/test/unit/descriptor/networkstatus/key_certificate.py b/test/unit/descriptor/networkstatus/key_certificate.py
index 5115227c..0da8da11 100644
--- a/test/unit/descriptor/networkstatus/key_certificate.py
+++ b/test/unit/descriptor/networkstatus/key_certificate.py
@@ -141,7 +141,7 @@ GM9hAsAMRX9Ogqhq5UjDNqEsvDKuyVeyh7unSZEOip9Zr6K/+7VsVPNb8vfBRBjo
 
   @test.require.cryptography
   def test_descriptor_signing(self):
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of KeyCertificate not implemented', KeyCertificate.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of KeyCertificate not implemented', KeyCertificate.create, sign = True)
 
   def test_unrecognized_line(self):
     """
diff --git a/test/unit/descriptor/remote.py b/test/unit/descriptor/remote.py
index 75bda0a0..e6171852 100644
--- a/test/unit/descriptor/remote.py
+++ b/test/unit/descriptor/remote.py
@@ -3,7 +3,6 @@ Unit tests for stem.descriptor.remote.
 """
 
 import io
-import re
 import socket
 import time
 import unittest
@@ -163,7 +162,7 @@ class TestDescriptorDownloader(unittest.TestCase):
         validate = True,
       )
 
-      self.assertRaisesRegexp(stem.ProtocolError, "Response should begin with HTTP success, but was 'HTTP/1.0 500 Kaboom'", request.run)
+      self.assertRaisesWith(stem.ProtocolError, "Response should begin with HTTP success, but was 'HTTP/1.0 500 Kaboom'", request.run)
 
   @patch(URL_OPEN, _dirport_mock(TEST_DESCRIPTOR))
   def test_using_dirport(self):
@@ -382,8 +381,8 @@ class TestDescriptorDownloader(unittest.TestCase):
     }
 
     for endpoints, error_suffix in invalid_endpoints.items():
-      expected_error = re.escape('Endpoints must be an stem.ORPort, stem.DirPort, or two value tuple. ' + error_suffix)
-      self.assertRaisesRegexp(ValueError, expected_error, stem.descriptor.remote.Query, TEST_RESOURCE, 'server-descriptor 1.0', endpoints = endpoints)
+      expected_error = 'Endpoints must be an stem.ORPort, stem.DirPort, or two value tuple. ' + error_suffix
+      self.assertRaisesWith(ValueError, expected_error, stem.descriptor.remote.Query, TEST_RESOURCE, 'server-descriptor 1.0', endpoints = endpoints)
 
   @patch(URL_OPEN, _dirport_mock(TEST_DESCRIPTOR))
   def test_can_iterate_multiple_times(self):
diff --git a/test/unit/descriptor/router_status_entry.py b/test/unit/descriptor/router_status_entry.py
index b376f869..9d8bf8ac 100644
--- a/test/unit/descriptor/router_status_entry.py
+++ b/test/unit/descriptor/router_status_entry.py
@@ -168,9 +168,9 @@ class TestRouterStatusEntry(unittest.TestCase):
 
   @test.require.cryptography
   def test_descriptor_signing(self):
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of RouterStatusEntryV2 not implemented', RouterStatusEntryV2.create, sign = True)
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of RouterStatusEntryV3 not implemented', RouterStatusEntryV3.create, sign = True)
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of RouterStatusEntryMicroV3 not implemented', RouterStatusEntryMicroV3.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of RouterStatusEntryV2 not implemented', RouterStatusEntryV2.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of RouterStatusEntryV3 not implemented', RouterStatusEntryV3.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of RouterStatusEntryMicroV3 not implemented', RouterStatusEntryMicroV3.create, sign = True)
 
   def test_without_ed25519(self):
     """
diff --git a/test/unit/descriptor/server_descriptor.py b/test/unit/descriptor/server_descriptor.py
index 7a68613d..6e6d27d4 100644
--- a/test/unit/descriptor/server_descriptor.py
+++ b/test/unit/descriptor/server_descriptor.py
@@ -269,7 +269,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
   @test.require.cryptography
   def test_descriptor_signing(self):
     RelayDescriptor.create(sign = True)
-    self.assertRaisesRegexp(NotImplementedError, 'Signing of BridgeDescriptor not implemented', BridgeDescriptor.create, sign = True)
+    self.assertRaisesWith(NotImplementedError, 'Signing of BridgeDescriptor not implemented', BridgeDescriptor.create, sign = True)
 
   def test_router_status_entry(self):
     """
@@ -278,7 +278,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
 
     desc_without_fingerprint = RelayDescriptor.create()
     exc_msg = 'Server descriptor lacks a fingerprint. This is an optional field, but required to make a router status entry.'
-    self.assertRaisesRegexp(ValueError, exc_msg, desc_without_fingerprint.make_router_status_entry)
+    self.assertRaisesWith(ValueError, exc_msg, desc_without_fingerprint.make_router_status_entry)
 
     desc = RelayDescriptor.create(OrderedDict((
       ('router', 'caerSidi 71.35.133.197 9001 0 0'),
@@ -797,7 +797,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
     """
 
     exc_msg = "'proto' should be a series of 'key=value' pairs but was: Desc Link=1-4"
-    self.assertRaisesRegexp(ValueError, exc_msg, RelayDescriptor.create, {'proto': 'Desc Link=1-4'})
+    self.assertRaisesWith(ValueError, exc_msg, RelayDescriptor.create, {'proto': 'Desc Link=1-4'})
 
   def test_parse_with_non_int_version(self):
     """
@@ -805,7 +805,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
     """
 
     exc_msg = 'Protocol values should be a number or number range, but was: proto Desc=hi Link=1-4'
-    self.assertRaisesRegexp(ValueError, exc_msg, RelayDescriptor.create, {'proto': 'Desc=hi Link=1-4'})
+    self.assertRaisesWith(ValueError, exc_msg, RelayDescriptor.create, {'proto': 'Desc=hi Link=1-4'})
 
   def test_ntor_onion_key(self):
     """
diff --git a/test/unit/exit_policy/rule.py b/test/unit/exit_policy/rule.py
index 58c985e5..44e0f484 100644
--- a/test/unit/exit_policy/rule.py
+++ b/test/unit/exit_policy/rule.py
@@ -2,7 +2,6 @@
 Unit tests for the stem.exit_policy.ExitPolicyRule class.
 """
 
-import re
 import unittest
 
 from stem.exit_policy import AddressType, ExitPolicyRule, MicroExitPolicy
@@ -384,10 +383,10 @@ class TestExitPolicyRule(unittest.TestCase):
 
   def test_missing_port(self):
     exc_msg = "An exitpattern must be of the form 'addrspec:portspec': accept6 192.168.0.1/0"
-    self.assertRaisesRegexp(ValueError, re.escape(exc_msg), ExitPolicyRule, 'accept6 192.168.0.1/0')
+    self.assertRaisesWith(ValueError, exc_msg, ExitPolicyRule, 'accept6 192.168.0.1/0')
 
     exc_msg = "An exitpattern must be of the form 'addrspec:portspec': reject6 [2a00:1450:4001:081e:0000:0000:0000:200e]"
-    self.assertRaisesRegexp(ValueError, re.escape(exc_msg), ExitPolicyRule, 'reject6 [2a00:1450:4001:081e:0000:0000:0000:200e]')
+    self.assertRaisesWith(ValueError, exc_msg, ExitPolicyRule, 'reject6 [2a00:1450:4001:081e:0000:0000:0000:200e]')
 
   def test_ipv6_only_entries(self):
     # accept6/reject6 shouldn't match anything when given an ipv4 addresses
diff --git a/test/unit/manual.py b/test/unit/manual.py
index 04528ad9..cd2fce94 100644
--- a/test/unit/manual.py
+++ b/test/unit/manual.py
@@ -4,7 +4,6 @@ Unit testing for the stem.manual module.
 
 import io
 import os
-import re
 import sqlite3
 import tempfile
 import unittest
@@ -108,7 +107,7 @@ class TestManual(unittest.TestCase):
     self.assertEqual("If set, this option overrides the default location and file name for Tor's cookie file. (See CookieAuthentication above.)", stem.manual.query('SELECT description FROM torrc WHERE name=?', 'CookieAuthFile').fetchone()[0])
 
   def test_query_on_failure(self):
-    self.assertRaisesRegexp(sqlite3.OperationalError, 'near "hello": syntax error', stem.manual.query, 'hello world')
+    self.assertRaisesWith(sqlite3.OperationalError, 'near "hello": syntax error', stem.manual.query, 'hello world')
 
   def test_has_all_summaries(self):
     """
@@ -243,12 +242,12 @@ class TestManual(unittest.TestCase):
 
   def test_download_man_page_without_arguments(self):
     exc_msg = "Either the path or file_handle we're saving to must be provided"
-    self.assertRaisesRegexp(ValueError, exc_msg, stem.manual.download_man_page)
+    self.assertRaisesWith(ValueError, exc_msg, stem.manual.download_man_page)
 
   @patch('stem.util.system.is_available', Mock(return_value = False))
   def test_download_man_page_requires_a2x(self):
     exc_msg = 'We require a2x from asciidoc to provide a man page'
-    self.assertRaisesRegexp(IOError, exc_msg, stem.manual.download_man_page, '/tmp/no_such_file')
+    self.assertRaisesWith(IOError, exc_msg, stem.manual.download_man_page, '/tmp/no_such_file')
 
   @patch('tempfile.mkdtemp', Mock(return_value = '/no/such/path'))
   @patch('shutil.rmtree', Mock())
@@ -256,7 +255,7 @@ class TestManual(unittest.TestCase):
   @patch('stem.util.system.is_available', Mock(return_value = True))
   def test_download_man_page_when_unable_to_write(self):
     exc_msg = "Unable to download tor's manual from https://gitweb.torproject.org/tor.git/plain/doc/tor.1.txt to /no/such/path/tor.1.txt: unable to write to file"
-    self.assertRaisesRegexp(IOError, re.escape(exc_msg), stem.manual.download_man_page, '/tmp/no_such_file')
+    self.assertRaisesWith(IOError, exc_msg, stem.manual.download_man_page, '/tmp/no_such_file')
 
   @patch('tempfile.mkdtemp', Mock(return_value = '/no/such/path'))
   @patch('shutil.rmtree', Mock())
@@ -265,7 +264,7 @@ class TestManual(unittest.TestCase):
   @patch(URL_OPEN, Mock(side_effect = urllib.URLError('<urlopen error [Errno -2] Name or service not known>')))
   def test_download_man_page_when_download_fails(self):
     exc_msg = "Unable to download tor's manual from https://www.atagar.com/foo/bar to /no/such/path/tor.1.txt: <urlopen error <urlopen error [Errno -2] Name or service not known>>"
-    self.assertRaisesRegexp(IOError, re.escape(exc_msg), stem.manual.download_man_page, '/tmp/no_such_file', url = 'https://www.atagar.com/foo/bar')
+    self.assertRaisesWith(IOError, exc_msg, stem.manual.download_man_page, '/tmp/no_such_file', url = 'https://www.atagar.com/foo/bar')
 
   @patch('tempfile.mkdtemp', Mock(return_value = '/no/such/path'))
   @patch('shutil.rmtree', Mock())
@@ -275,7 +274,7 @@ class TestManual(unittest.TestCase):
   @patch(URL_OPEN, Mock(return_value = io.BytesIO(b'test content')))
   def test_download_man_page_when_a2x_fails(self):
     exc_msg = "Unable to run 'a2x -f manpage /no/such/path/tor.1.txt': call failed"
-    self.assertRaisesRegexp(IOError, exc_msg, stem.manual.download_man_page, '/tmp/no_such_file', url = 'https://www.atagar.com/foo/bar')
+    self.assertRaisesWith(IOError, exc_msg, stem.manual.download_man_page, '/tmp/no_such_file', url = 'https://www.atagar.com/foo/bar')
 
   @patch('tempfile.mkdtemp', Mock(return_value = '/no/such/path'))
   @patch('shutil.rmtree', Mock())
@@ -304,7 +303,7 @@ class TestManual(unittest.TestCase):
   @patch('stem.util.system.call', Mock(side_effect = OSError('man --encoding=ascii -P cat tor returned exit status 16')))
   def test_from_man_when_manual_is_unavailable(self):
     exc_msg = "Unable to run 'man --encoding=ascii -P cat tor': man --encoding=ascii -P cat tor returned exit status 16"
-    self.assertRaisesRegexp(IOError, exc_msg, stem.manual.Manual.from_man)
+    self.assertRaisesWith(IOError, exc_msg, stem.manual.Manual.from_man)
 
   @patch('stem.util.system.call', Mock(return_value = []))
   def test_when_man_is_empty(self):
diff --git a/test/unit/util/proc.py b/test/unit/util/proc.py
index 7ee4ecda..6ee29136 100644
--- a/test/unit/util/proc.py
+++ b/test/unit/util/proc.py
@@ -3,7 +3,6 @@ Unit testing code for the stem.util.proc functions.
 """
 
 import io
-import re
 import unittest
 
 import test
@@ -187,7 +186,7 @@ class TestProc(unittest.TestCase):
     listdir_mock.side_effect = OSError(error_msg)
 
     exc_msg = 'Unable to check number of file descriptors used: %s' % error_msg
-    self.assertRaisesRegexp(IOError, re.escape(exc_msg), proc.file_descriptors_used, 2118)
+    self.assertRaisesWith(IOError, exc_msg, proc.file_descriptors_used, 2118)
 
     # successful calls
 



More information about the tor-commits mailing list