diff --git a/tests/gis_tests/data/geometries.json b/tests/gis_tests/data/geometries.json index eb6c64b6d9..6856ac793a 100644 --- a/tests/gis_tests/data/geometries.json +++ b/tests/gis_tests/data/geometries.json @@ -11,12 +11,12 @@ {"wkt": "MULTIPOLYGON (((180 60, 240 160, 300 60, 180 60)), ((80 80, 180 60, 160 140, 240 160, 360 140, 300 60, 420 100, 320 280, 120 260, 80 80)))", "valid": true, "num_geom": 2, "n_p": 14} ], "errors": [ - {"wkt": "GEOMETR##!@#%#............a32515", "bad": true, "hex": false}, - {"wkt": "Foo.Bar", "bad": true, "hex": false}, - {"wkt": "POINT (5, 23)", "bad": true, "hex": false}, - {"wkt": "AAABBBDDDAAD##@#1113511111-098111111111111111533333333333333", "bad": true, "hex": true}, - {"wkt": "FFFFFFFFFFFFFFFFF1355555555555555555565111", "bad": true, "hex": true}, - {"wkt": "", "bad": true, "hex": false} + {"wkt": "GEOMETR##!@#%#............a32515", "bad": true, "hex": false, "msg": "String input unrecognized as WKT EWKT, and HEXEWKB."}, + {"wkt": "Foo.Bar", "bad": true, "hex": false, "msg": "String input unrecognized as WKT EWKT, and HEXEWKB."}, + {"wkt": "POINT (5, 23)", "bad": true, "hex": false, "msg": "Error encountered checking Geometry returned from GEOS C function \"GEOSWKTReader_read_r\"."}, + {"wkt": "AAABBBDDDAAD##@#1113511111-098111111111111111533333333333333", "bad": true, "hex": true, "msg": "String input unrecognized as WKT EWKT, and HEXEWKB."}, + {"wkt": "FFFFFFFFFFFFFFFFF1355555555555555555565111", "bad": true, "hex": true, "msg": "Error encountered checking Geometry returned from GEOS C function \"GEOSWKBReader_readHEX_r\"."}, + {"wkt": "", "bad": true, "hex": false, "msg": "String input unrecognized as WKT EWKT, and HEXEWKB."} ], "wkt_out": [ {"wkt": "POINT (110 130)", "ewkt": "POINT (110 130)", "kml": "110.0,130.0,0", "gml": "110,130"}, diff --git a/tests/gis_tests/geos_tests/test_geos.py b/tests/gis_tests/geos_tests/test_geos.py index 0051a88b07..01ed3ab834 100644 --- a/tests/gis_tests/geos_tests/test_geos.py +++ b/tests/gis_tests/geos_tests/test_geos.py @@ -28,6 +28,7 @@ from django.contrib.gis.shortcuts import numpy from django.template import Context from django.template.engine import Engine from django.test import SimpleTestCase +from django.utils.version import PY312 from ..test_data import TestDataMixin @@ -98,21 +99,28 @@ class GEOSTest(SimpleTestCase, TestDataMixin): "Testing the Error handlers." # string-based for err in self.geometries.errors: - with self.assertRaises((GEOSException, ValueError)): - fromstr(err.wkt) + with self.subTest(err=err.wkt): + with self.assertRaisesMessage((GEOSException, ValueError), err.msg): + fromstr(err.wkt) # Bad WKB - with self.assertRaises(GEOSException): + msg = ( + "Error encountered checking Geometry returned from GEOS C " + 'function "GEOSWKBReader_read_r".' + ) + with self.assertRaisesMessage(GEOSException, msg): GEOSGeometry(memoryview(b"0")) class NotAGeometry: pass # Some other object - with self.assertRaises(TypeError): + msg = "Improper geometry input type:" + with self.assertRaisesMessage(TypeError, msg): GEOSGeometry(NotAGeometry()) # None - with self.assertRaises(TypeError): + msg = "Improper geometry input type: " + with self.assertRaisesMessage(TypeError, msg): GEOSGeometry(None) def test_wkb(self): @@ -384,8 +392,10 @@ class GEOSTest(SimpleTestCase, TestDataMixin): self.assertAlmostEqual(mp.centroid[0], mpnt.centroid.tuple[0], 9) self.assertAlmostEqual(mp.centroid[1], mpnt.centroid.tuple[1], 9) - with self.assertRaises(IndexError): - mpnt.__getitem__(len(mpnt)) + mpnt_len = len(mpnt) + msg = f"invalid index: {mpnt_len}" + with self.assertRaisesMessage(IndexError, msg): + mpnt.__getitem__(mpnt_len) self.assertEqual(mp.centroid, mpnt.centroid.tuple) self.assertEqual(mp.coords, tuple(m.tuple for m in mpnt)) for p in mpnt: @@ -411,8 +421,10 @@ class GEOSTest(SimpleTestCase, TestDataMixin): self.assertEqual(ls, fromstr(line.wkt)) self.assertIs(ls == prev, False) # Use assertIs() to test __eq__. - with self.assertRaises(IndexError): - ls.__getitem__(len(ls)) + ls_len = len(ls) + msg = f"invalid index: {ls_len}" + with self.assertRaisesMessage(IndexError, msg): + ls.__getitem__(ls_len) prev = ls # Creating a LineString from a tuple, list, and numpy array @@ -501,8 +513,10 @@ class GEOSTest(SimpleTestCase, TestDataMixin): self.assertEqual(ls.geom_typeid, 1) self.assertIs(ls.empty, False) - with self.assertRaises(IndexError): - ml.__getitem__(len(ml)) + ml_len = len(ml) + msg = f"invalid index: {ml_len}" + with self.assertRaisesMessage(IndexError, msg): + ml.__getitem__(ml_len) self.assertEqual(ml.wkt, MultiLineString(*tuple(s.clone() for s in ml)).wkt) self.assertEqual( ml, MultiLineString(*tuple(LineString(s.tuple) for s in ml)) @@ -597,12 +611,16 @@ class GEOSTest(SimpleTestCase, TestDataMixin): self.assertEqual(p.ext_ring_cs, poly[0].tuple) # Testing __getitem__ # Testing __getitem__ and __setitem__ on invalid indices - with self.assertRaises(IndexError): - poly.__getitem__(len(poly)) - with self.assertRaises(IndexError): - poly.__setitem__(len(poly), False) - with self.assertRaises(IndexError): - poly.__getitem__(-1 * len(poly) - 1) + poly_len = len(poly) + msg = f"invalid index: {poly_len}" + with self.assertRaisesMessage(IndexError, msg): + poly.__getitem__(poly_len) + with self.assertRaisesMessage(IndexError, msg): + poly.__setitem__(poly_len, False) + negative_index = -1 * poly_len - 1 + msg = f"invalid index: {negative_index}" + with self.assertRaisesMessage(IndexError, msg): + poly.__getitem__(negative_index) # Testing __iter__ for r in poly: @@ -610,9 +628,13 @@ class GEOSTest(SimpleTestCase, TestDataMixin): self.assertEqual(r.geom_typeid, 2) # Testing polygon construction. - with self.assertRaises(TypeError): + msg = ( + "Parameter must be a sequence of LinearRings or " + "objects that can initialize to LinearRings" + ) + with self.assertRaisesMessage(TypeError, msg): Polygon(0, [1, 2, 3]) - with self.assertRaises(TypeError): + with self.assertRaisesMessage(TypeError, msg): Polygon("foo") # Polygon(shell, (hole1, ... holeN)) @@ -659,11 +681,13 @@ class GEOSTest(SimpleTestCase, TestDataMixin): self.assertEqual(mp.valid, mpoly.valid) if mp.valid: + mpoly_len = len(mpoly) self.assertEqual(mp.num_geom, mpoly.num_geom) self.assertEqual(mp.n_p, mpoly.num_coords) - self.assertEqual(mp.num_geom, len(mpoly)) - with self.assertRaises(IndexError): - mpoly.__getitem__(len(mpoly)) + self.assertEqual(mp.num_geom, mpoly_len) + msg = f"invalid index: {mpoly_len}" + with self.assertRaisesMessage(IndexError, msg): + mpoly.__getitem__(mpoly_len) for p in mpoly: self.assertEqual(p.geom_type, "Polygon") self.assertEqual(p.geom_typeid, 3) @@ -732,7 +756,8 @@ class GEOSTest(SimpleTestCase, TestDataMixin): def test_relate_pattern(self): "Testing relate() and relate_pattern()." g = fromstr("POINT (0 0)") - with self.assertRaises(GEOSException): + msg = "invalid intersection matrix pattern" + with self.assertRaisesMessage(GEOSException, msg): g.relate_pattern(0, "invalid pattern, yo") for rg in self.geometries.relate_geoms: a = fromstr(rg.wkt_a) @@ -805,7 +830,14 @@ class GEOSTest(SimpleTestCase, TestDataMixin): g = fromstr(bg.wkt) # Can't use a floating-point for the number of quadsegs. - with self.assertRaises(ctypes.ArgumentError): + if PY312: + msg = ( + "argument 4: TypeError: 'float' object " + "cannot be interpreted as an integer" + ) + else: + msg = "argument 4: TypeError: wrong type" + with self.assertRaisesMessage(ctypes.ArgumentError, msg): g.buffer(bg.width, quadsegs=1.1) self._test_buffer(self.geometries.buffer_geoms, "buffer") @@ -815,21 +847,50 @@ class GEOSTest(SimpleTestCase, TestDataMixin): g = fromstr(bg.wkt) # Can't use a floating-point for the number of quadsegs. - with self.assertRaises(ctypes.ArgumentError): + if PY312: + msg = ( + "argument 4: TypeError: 'float' object " + "cannot be interpreted as an integer" + ) + else: + msg = "argument 4: TypeError: wrong type" + with self.assertRaisesMessage(ctypes.ArgumentError, msg): g.buffer_with_style(bg.width, quadsegs=1.1) # Can't use a floating-point for the end cap style. - with self.assertRaises(ctypes.ArgumentError): + if PY312: + msg = ( + "argument 5: TypeError: 'float' object " + "cannot be interpreted as an integer" + ) + else: + msg = "argument 5: TypeError: wrong type" + with self.assertRaisesMessage(ctypes.ArgumentError, msg): g.buffer_with_style(bg.width, end_cap_style=1.2) # Can't use a end cap style that is not in the enum. - with self.assertRaises(GEOSException): + msg = ( + "Error encountered checking Geometry returned " + 'from GEOS C function "GEOSBufferWithStyle_r".' + ) + with self.assertRaisesMessage(GEOSException, msg): g.buffer_with_style(bg.width, end_cap_style=55) # Can't use a floating-point for the join style. - with self.assertRaises(ctypes.ArgumentError): + if PY312: + msg = ( + "argument 6: TypeError: 'float' object " + "cannot be interpreted as an integer" + ) + else: + msg = "argument 6: TypeError: wrong type" + with self.assertRaisesMessage(ctypes.ArgumentError, msg): g.buffer_with_style(bg.width, join_style=1.3) # Can't use a join style that is not in the enum. - with self.assertRaises(GEOSException): + msg = ( + "Error encountered checking Geometry returned from " + 'GEOS C function "GEOSBufferWithStyle_r".' + ) + with self.assertRaisesMessage(GEOSException, msg): g.buffer_with_style(bg.width, join_style=66) self._test_buffer( @@ -891,7 +952,14 @@ class GEOSTest(SimpleTestCase, TestDataMixin): self.assertEqual(4326, pnt.srid) pnt.srid = 3084 self.assertEqual(3084, pnt.srid) - with self.assertRaises(ctypes.ArgumentError): + if PY312: + msg = ( + "argument 3: TypeError: 'str' object " + "cannot be interpreted as an integer" + ) + else: + msg = "argument 3: TypeError: wrong type" + with self.assertRaisesMessage(ctypes.ArgumentError, msg): pnt.srid = "4326" # Testing SRID keyword on fromstr(), and on Polygon rings. @@ -970,7 +1038,12 @@ class GEOSTest(SimpleTestCase, TestDataMixin): poly = fromstr(p.wkt) # Should only be able to use __setitem__ with LinearRing geometries. - with self.assertRaises(TypeError): + msg = ( + "Parameter must be a sequence of LinearRings or " + "objects that can initialize to LinearRings" + ) + + with self.assertRaisesMessage(TypeError, msg): poly.__setitem__(0, LineString((1, 1), (2, 2))) # Constructing the new shell by adding 500 to every point in the old shell. @@ -1042,9 +1115,11 @@ class GEOSTest(SimpleTestCase, TestDataMixin): p[:] = (1, 2) self.assertEqual(p.wkt, Point(1, 2)) - with self.assertRaises(ValueError): + msg = "Must have at least 2 items" + with self.assertRaisesMessage(ValueError, msg): p[:] = (1,) - with self.assertRaises(ValueError): + msg = "Cannot have more than 3 items" + with self.assertRaisesMessage(ValueError, msg): p[:] = (1, 2, 3, 4, 5) def test_linestring_list_assignment(self): @@ -1056,7 +1131,8 @@ class GEOSTest(SimpleTestCase, TestDataMixin): ls[:] = ((0, 0), (1, 1), (2, 2)) self.assertEqual(ls, LineString((0, 0), (1, 1), (2, 2))) - with self.assertRaises(ValueError): + msg = "Must have at least 2 items" + with self.assertRaisesMessage(ValueError, msg): ls[:] = (1,) def test_linearring_list_assignment(self): @@ -1068,7 +1144,8 @@ class GEOSTest(SimpleTestCase, TestDataMixin): ls[:] = ((0, 0), (0, 1), (1, 1), (1, 0), (0, 0)) self.assertEqual(ls, LinearRing((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))) - with self.assertRaises(ValueError): + msg = "Must have at least 4 items" + with self.assertRaisesMessage(ValueError, msg): ls[:] = ((0, 0), (1, 1), (2, 2)) def test_polygon_list_assignment(self): @@ -1100,7 +1177,8 @@ class GEOSTest(SimpleTestCase, TestDataMixin): # Testing a 3D Point pnt = Point(2, 3, 8) self.assertEqual((2.0, 3.0, 8.0), pnt.coords) - with self.assertRaises(TypeError): + msg = "Dimension of value does not match." + with self.assertRaisesMessage(TypeError, msg): pnt.tuple = (1.0, 2.0) pnt.coords = (1.0, 2.0, 3.0) self.assertEqual((1.0, 2.0, 3.0), pnt.coords) @@ -1108,7 +1186,7 @@ class GEOSTest(SimpleTestCase, TestDataMixin): # Testing a 3D LineString ls = LineString((2.0, 3.0, 8.0), (50.0, 250.0, -117.0)) self.assertEqual(((2.0, 3.0, 8.0), (50.0, 250.0, -117.0)), ls.tuple) - with self.assertRaises(TypeError): + with self.assertRaisesMessage(TypeError, msg): ls.__setitem__(0, (1.0, 2.0)) ls[0] = (1.0, 2.0, 3.0) self.assertEqual((1.0, 2.0, 3.0), ls[0]) @@ -1190,17 +1268,20 @@ class GEOSTest(SimpleTestCase, TestDataMixin): if isinstance(g, Point): # IndexError is not raised in GEOS 3.8.0. if geos_version_tuple() != (3, 8, 0): - with self.assertRaises(IndexError): + msg = "invalid GEOS Geometry index:" + with self.assertRaisesMessage(IndexError, msg): g.x elif isinstance(g, Polygon): lr = g.shell self.assertEqual("LINEARRING EMPTY", lr.wkt) self.assertEqual(0, len(lr)) self.assertIs(lr.empty, True) - with self.assertRaises(IndexError): + msg = "invalid index: 0" + with self.assertRaisesMessage(IndexError, msg): lr.__getitem__(0) else: - with self.assertRaises(IndexError): + msg = "invalid index: 0" + with self.assertRaisesMessage(IndexError, msg): g.__getitem__(0) def test_collection_dims(self): @@ -1320,19 +1401,20 @@ class GEOSTest(SimpleTestCase, TestDataMixin): """Testing `transform` method (no SRID or negative SRID)""" g = GEOSGeometry("POINT (-104.609 38.255)", srid=None) - with self.assertRaises(GEOSException): + msg = "Calling transform() with no SRID set is not supported" + with self.assertRaisesMessage(GEOSException, msg): g.transform(2774) g = GEOSGeometry("POINT (-104.609 38.255)", srid=None) - with self.assertRaises(GEOSException): + with self.assertRaisesMessage(GEOSException, msg): g.transform(2774, clone=True) g = GEOSGeometry("POINT (-104.609 38.255)", srid=-1) - with self.assertRaises(GEOSException): + with self.assertRaisesMessage(GEOSException, msg): g.transform(2774) g = GEOSGeometry("POINT (-104.609 38.255)", srid=-1) - with self.assertRaises(GEOSException): + with self.assertRaisesMessage(GEOSException, msg): g.transform(2774, clone=True) def test_extent(self): @@ -1629,5 +1711,6 @@ class GEOSTest(SimpleTestCase, TestDataMixin): # Step into CoordSeq iterator. next(it) ls[:] = [] - with self.assertRaises(IndexError): + msg = "invalid index: 1" + with self.assertRaisesMessage(IndexError, msg): next(it) diff --git a/tests/gis_tests/geos_tests/test_geos_mutation.py b/tests/gis_tests/geos_tests/test_geos_mutation.py index c239ab3efe..642e96df45 100644 --- a/tests/gis_tests/geos_tests/test_geos_mutation.py +++ b/tests/gis_tests/geos_tests/test_geos_mutation.py @@ -2,8 +2,6 @@ # Modified from original contribution by Aryeh Leib Taurog, which was # released under the New BSD license. -import unittest - from django.contrib.gis.geos import ( LinearRing, LineString, @@ -12,6 +10,7 @@ from django.contrib.gis.geos import ( Polygon, fromstr, ) +from django.test import SimpleTestCase def api_get_distance(x): @@ -77,7 +76,7 @@ geos_function_tests = [ ] -class GEOSMutationTest(unittest.TestCase): +class GEOSMutationTest(SimpleTestCase): """ Tests Pythonic Mutability of Python GEOS geometry wrappers get/set/delitem on a slice, normal list methods @@ -88,9 +87,11 @@ class GEOSMutationTest(unittest.TestCase): p = Point(1, 2) for i in range(-2, 2): p._checkindex(i) - with self.assertRaises(IndexError): + msg = "invalid index: 2" + with self.assertRaisesMessage(IndexError, msg): p._checkindex(2) - with self.assertRaises(IndexError): + msg = "invalid index: -3" + with self.assertRaisesMessage(IndexError, msg): p._checkindex(-3) def test01_PointMutations(self): @@ -110,9 +111,10 @@ class GEOSMutationTest(unittest.TestCase): def test02_PointExceptions(self): "Testing Point exceptions" - with self.assertRaises(TypeError): + msg = "Invalid parameters given for Point initialization." + with self.assertRaisesMessage(TypeError, msg): Point(range(1)) - with self.assertRaises(TypeError): + with self.assertRaisesMessage(TypeError, msg): Point(range(4)) def test03_PointApi(self): diff --git a/tests/gis_tests/geos_tests/test_io.py b/tests/gis_tests/geos_tests/test_io.py index 79ec3d053e..e6d21db2a3 100644 --- a/tests/gis_tests/geos_tests/test_io.py +++ b/tests/gis_tests/geos_tests/test_io.py @@ -37,7 +37,11 @@ class GEOSIOTest(SimpleTestCase): def test02_wktwriter(self): # Creating a WKTWriter instance, testing its ptr property. wkt_w = WKTWriter() - with self.assertRaises(TypeError): + msg = ( + "Incompatible pointer type: " + "." + ) + with self.assertRaisesMessage(TypeError, msg): wkt_w.ptr = WKTReader.ptr_type() ref = GEOSGeometry("POINT (5 23)") @@ -71,8 +75,9 @@ class GEOSIOTest(SimpleTestCase): self.assertEqual(ref, geom) bad_input = (1, 5.23, None, False) + msg = "'wkb' must be bytes, str or memoryview." for bad_wkb in bad_input: - with self.assertRaises(TypeError): + with self.assertRaisesMessage(TypeError, msg): wkb_r.read(bad_wkb) def test04_wkbwriter(self): @@ -92,7 +97,8 @@ class GEOSIOTest(SimpleTestCase): # Ensuring bad byteorders are not accepted. for bad_byteorder in (-1, 2, 523, "foo", None): # Equivalent of `wkb_w.byteorder = bad_byteorder` - with self.assertRaises(ValueError): + msg = "Byte order parameter must be 0 (Big Endian) or 1 (Little Endian)." + with self.assertRaisesMessage(ValueError, msg): wkb_w._set_byteorder(bad_byteorder) # Setting the byteorder to 0 (for Big Endian) diff --git a/tests/gis_tests/geos_tests/test_mutable_list.py b/tests/gis_tests/geos_tests/test_mutable_list.py index a092f603cb..83c7ac7d50 100644 --- a/tests/gis_tests/geos_tests/test_mutable_list.py +++ b/tests/gis_tests/geos_tests/test_mutable_list.py @@ -4,9 +4,8 @@ # Modified from original contribution by Aryeh Leib Taurog, which was # released under the New BSD license. -import unittest - from django.contrib.gis.geos.mutable_list import ListMixin +from django.test import SimpleTestCase class UserListA(ListMixin): @@ -54,7 +53,7 @@ def nextRange(length): nextRange.start = 0 -class ListMixinTest(unittest.TestCase): +class ListMixinTest(SimpleTestCase): """ Tests base class ListMixin by comparing a list clone which is a ListMixin subclass with a real Python list. @@ -133,10 +132,18 @@ class ListMixinTest(unittest.TestCase): self.assertEqual(pl, ul[:], "set slice [%d:%d:%d]" % (i, j, k)) sliceLen = len(ul[i:j:k]) - with self.assertRaises(ValueError): + msg = ( + f"attempt to assign sequence of size {sliceLen + 1} " + f"to extended slice of size {sliceLen}" + ) + with self.assertRaisesMessage(ValueError, msg): setfcn(ul, i, j, k, sliceLen + 1) if sliceLen > 2: - with self.assertRaises(ValueError): + msg = ( + f"attempt to assign sequence of size {sliceLen - 1} " + f"to extended slice of size {sliceLen}" + ) + with self.assertRaisesMessage(ValueError, msg): setfcn(ul, i, j, k, sliceLen - 1) for k in self.step_range(): @@ -234,11 +241,12 @@ class ListMixinTest(unittest.TestCase): pl, ul = self.lists_of_len() for i in (-1 - self.limit, self.limit): - with self.assertRaises(IndexError): # 'set index %d' % i) + msg = f"invalid index: {i}" + with self.assertRaisesMessage(IndexError, msg): # 'set index %d' % i) setfcn(ul, i) - with self.assertRaises(IndexError): # 'get index %d' % i) + with self.assertRaisesMessage(IndexError, msg): # 'get index %d' % i) getfcn(ul, i) - with self.assertRaises(IndexError): # 'del index %d' % i) + with self.assertRaisesMessage(IndexError, msg): # 'del index %d' % i) delfcn(ul, i) def test06_list_methods(self): @@ -276,9 +284,11 @@ class ListMixinTest(unittest.TestCase): def popfcn(x, i): x.pop(i) - with self.assertRaises(IndexError): + msg = "invalid index: 3" + with self.assertRaisesMessage(IndexError, msg): popfcn(ul, self.limit) - with self.assertRaises(IndexError): + msg = "invalid index: -4" + with self.assertRaisesMessage(IndexError, msg): popfcn(ul, -1 - self.limit) pl, ul = self.lists_of_len() @@ -300,9 +310,10 @@ class ListMixinTest(unittest.TestCase): def removefcn(x, v): return x.remove(v) - with self.assertRaises(ValueError): + msg = "40 not found in object" + with self.assertRaisesMessage(ValueError, msg): indexfcn(ul, 40) - with self.assertRaises(ValueError): + with self.assertRaisesMessage(ValueError, msg): removefcn(ul, 40) def test07_allowed_types(self): @@ -315,9 +326,10 @@ class ListMixinTest(unittest.TestCase): def setfcn(x, i, v): x[i] = v - with self.assertRaises(TypeError): + msg = "Invalid type encountered in the arguments." + with self.assertRaisesMessage(TypeError, msg): setfcn(ul, 2, "hello") - with self.assertRaises(TypeError): + with self.assertRaisesMessage(TypeError, msg): setfcn(ul, slice(0, 3, 2), ("hello", "goodbye")) def test08_min_length(self): @@ -331,17 +343,19 @@ class ListMixinTest(unittest.TestCase): def setfcn(x, i): x[:i] = [] + msg = "Must have at least 3 items" for i in range(len(ul) - ul._minlength + 1, len(ul)): - with self.assertRaises(ValueError): + with self.assertRaisesMessage(ValueError, msg): delfcn(ul, i) - with self.assertRaises(ValueError): + with self.assertRaisesMessage(ValueError, msg): setfcn(ul, i) del ul[: len(ul) - ul._minlength] ul._maxlength = 4 for i in range(0, ul._maxlength - len(ul)): ul.append(i) - with self.assertRaises(ValueError): + msg = "Cannot have more than 4 items" + with self.assertRaisesMessage(ValueError, msg): ul.append(10) def test09_iterable_check(self): @@ -351,7 +365,8 @@ class ListMixinTest(unittest.TestCase): def setfcn(x, i, v): x[i] = v - with self.assertRaises(TypeError): + msg = "can only assign an iterable to a slice" + with self.assertRaisesMessage(TypeError, msg): setfcn(ul, slice(0, 3, 2), 2) def test10_checkindex(self): @@ -366,7 +381,8 @@ class ListMixinTest(unittest.TestCase): self.assertEqual(ul._checkindex(i), i, "_checkindex(pos index)") for i in (-self.limit - 1, self.limit): - with self.assertRaises(IndexError): + msg = f"invalid index: {i}" + with self.assertRaisesMessage(IndexError, msg): ul._checkindex(i) def test_11_sorting(self):