From c1bb42b0993caf83044e425ea481fbb2c1f40b57 Mon Sep 17 00:00:00 2001 From: nkorinek Date: Wed, 26 Feb 2020 15:38:29 -0700 Subject: [PATCH 01/14] Added a get_points() and assert_points() function to the vector tester. --- matplotcheck/vector.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index 10610602..c52e4676 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -237,6 +237,27 @@ def assert_collection_sorted_by_markersize(self, df_expected, sort_column): err_msg="Markersize not based on {0} values".format(sort_column), ) + def get_points(self): + """yeet""" + points = self.get_xy(points_only=True).sort_values(by="x") + points.reset_index(inplace=True, drop=True) + return points + + def assert_points(self, points_expected, m="Incorrect Line Data"): + """yote""" + if isinstance(points_expected, gpd.geodataframe.GeoDataFrame): + xy_expected = pd.DataFrame(columns=['x', 'y']) + xy_expected['x'] = points_expected.geometry.x + xy_expected['y'] = points_expected.geometry.y + xy_expected = xy_expected.sort_values(by="x") + xy_expected.reset_index(inplace=True, drop=True) + pd.testing.assert_frame_equal(left=self.get_points(), right=xy_expected) + else: + raise ValueError( + "points_expected is not expected type: GeoDataFrame" + ) + + ### LINES ### def _convert_multilines(self, df, column_title): From 6cd48e3c867e88e445878e941f1844800862ad0a Mon Sep 17 00:00:00 2001 From: nkorinek Date: Wed, 26 Feb 2020 16:43:03 -0700 Subject: [PATCH 02/14] Added in get_points() and assert_points() functions with tests --- matplotcheck/tests/test_vector.py | 56 +++++++++++++++++++++++++++++++ matplotcheck/vector.py | 9 +++-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/matplotcheck/tests/test_vector.py b/matplotcheck/tests/test_vector.py index e65a0611..6c3b06f5 100644 --- a/matplotcheck/tests/test_vector.py +++ b/matplotcheck/tests/test_vector.py @@ -20,6 +20,28 @@ def poly_geo_plot(basic_polygon_gdf): return VectorTester(axis) +@pytest.fixture +def point_geo_plot(pd_gdf): + """Create a point plot for testing""" + fig, ax = plt.subplots() + + pd_gdf.plot(ax=ax) + ax.set_title("My Plot Title", fontsize=30) + ax.set_xlabel("x label") + ax.set_ylabel("y label") + + axis = plt.gca() + + return VectorTester(axis) + + +@pytest.fixture +def bad_pd_gdf(pd_gdf): + """Create a point geodataframe with slightly wrong values for testing""" + return gpd.GeoDataFrame(geometry=gpd.points_from_xy( + pd_gdf.geometry.x + 1, pd_gdf.geometry.y + 1) + ) + def test_list_of_polygons_check(poly_geo_plot, basic_polygon): """Check that the polygon assert works with a list of polygons.""" x, y = basic_polygon.exterior.coords.xy @@ -85,3 +107,37 @@ def test_polygon_custom_fail_message(poly_geo_plot, basic_polygon): poly_list = [(x[0] + 0.5, x[1]) for x in list(zip(x, y))] poly_geo_plot.assert_polygons(poly_list, m="Test Message") plt.close() + + +def test_point_geometry_pass(point_geo_plot, pd_gdf): + """Check that the point geometry test recognizes correct points.""" + point_geo_plot.assert_points(points_expected=pd_gdf) + + +def test_point_geometry_fail(point_geo_plot, bad_pd_gdf): + """Check that the point geometry test recognizes incorrect points.""" + with pytest.raises(AssertionError, match="Incorrect Point Data"): + point_geo_plot.assert_points(points_expected=bad_pd_gdf) + + +def test_assert_point_fails_list(point_geo_plot, pd_gdf): + """ + Check that the point geometry test fails anything that's not a + GeoDataFrame + """ + list_geo = [list(pd_gdf.geometry.x), list(pd_gdf.geometry.y)] + with pytest.raises(ValueError, match="points_expected is not expected"): + point_geo_plot.assert_points(points_expected=list_geo) + +def test_get_points(point_geo_plot, pd_gdf): + """Tests that get_points returns correct values""" + xy_values = point_geo_plot.get_points() + assert(list(sorted(xy_values.x)) == sorted(list(pd_gdf.geometry.x))) + assert(list(sorted(xy_values.y)) == sorted(list(pd_gdf.geometry.y))) + + +def test_assert_points_custom_message(point_geo_plot, bad_pd_gdf): + """Tests that a custom error message is passed.""" + message = "Test message" + with pytest.raises(AssertionError, match="Test message"): + point_geo_plot.assert_points(points_expected=bad_pd_gdf, m=message) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index c52e4676..1242e411 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -243,7 +243,7 @@ def get_points(self): points.reset_index(inplace=True, drop=True) return points - def assert_points(self, points_expected, m="Incorrect Line Data"): + def assert_points(self, points_expected, m="Incorrect Point Data"): """yote""" if isinstance(points_expected, gpd.geodataframe.GeoDataFrame): xy_expected = pd.DataFrame(columns=['x', 'y']) @@ -251,7 +251,12 @@ def assert_points(self, points_expected, m="Incorrect Line Data"): xy_expected['y'] = points_expected.geometry.y xy_expected = xy_expected.sort_values(by="x") xy_expected.reset_index(inplace=True, drop=True) - pd.testing.assert_frame_equal(left=self.get_points(), right=xy_expected) + try: + pd.testing.assert_frame_equal( + left=self.get_points(), right=xy_expected + ) + except AssertionError: + raise AssertionError(m) else: raise ValueError( "points_expected is not expected type: GeoDataFrame" From 5e6a175f29591515af47aeb4f0a025e6685ca1d4 Mon Sep 17 00:00:00 2001 From: nkorinek Date: Wed, 26 Feb 2020 16:47:19 -0700 Subject: [PATCH 03/14] Added proper documentation --- matplotcheck/vector.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index 1242e411..07384fd6 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -238,13 +238,30 @@ def assert_collection_sorted_by_markersize(self, df_expected, sort_column): ) def get_points(self): - """yeet""" + """Returns a Pandas dataframe with all x, y values for points on axis. + + Returns + ------- + output: DataFrame with columns 'x' and 'y'. Each row represents one + points coordinates. + """ points = self.get_xy(points_only=True).sort_values(by="x") points.reset_index(inplace=True, drop=True) return points def assert_points(self, points_expected, m="Incorrect Point Data"): - """yote""" + """ + Asserts the point data in Axes ax is equal to points_expected data + with error message m. + If points_expected not a GeoDataFrame, test fails. + + Parameters + ---------- + points_expected : GeoDataFrame + GeoDataFrame with the expected points for the axis. + m : string (default = "Incorrect Point Data") + String error message if assertion is not met. + """ if isinstance(points_expected, gpd.geodataframe.GeoDataFrame): xy_expected = pd.DataFrame(columns=['x', 'y']) xy_expected['x'] = points_expected.geometry.x From 408ab38682a71c979e5defed7a3f4bb74528719b Mon Sep 17 00:00:00 2001 From: nkorinek Date: Wed, 26 Feb 2020 16:54:45 -0700 Subject: [PATCH 04/14] Small fix to please codacy --- matplotcheck/tests/test_vector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matplotcheck/tests/test_vector.py b/matplotcheck/tests/test_vector.py index 6c3b06f5..99ac3a95 100644 --- a/matplotcheck/tests/test_vector.py +++ b/matplotcheck/tests/test_vector.py @@ -23,7 +23,7 @@ def poly_geo_plot(basic_polygon_gdf): @pytest.fixture def point_geo_plot(pd_gdf): """Create a point plot for testing""" - fig, ax = plt.subplots() + _, ax = plt.subplots() pd_gdf.plot(ax=ax) ax.set_title("My Plot Title", fontsize=30) From 8325ed9c0bee00f44808baba7bc17cd5e9368f99 Mon Sep 17 00:00:00 2001 From: nkorinek Date: Wed, 26 Feb 2020 17:06:20 -0700 Subject: [PATCH 05/14] black --- matplotcheck/tests/test_vector.py | 14 +++++++++----- matplotcheck/vector.py | 7 +++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/matplotcheck/tests/test_vector.py b/matplotcheck/tests/test_vector.py index 99ac3a95..952df150 100644 --- a/matplotcheck/tests/test_vector.py +++ b/matplotcheck/tests/test_vector.py @@ -38,9 +38,12 @@ def point_geo_plot(pd_gdf): @pytest.fixture def bad_pd_gdf(pd_gdf): """Create a point geodataframe with slightly wrong values for testing""" - return gpd.GeoDataFrame(geometry=gpd.points_from_xy( - pd_gdf.geometry.x + 1, pd_gdf.geometry.y + 1) - ) + return gpd.GeoDataFrame( + geometry=gpd.points_from_xy( + pd_gdf.geometry.x + 1, pd_gdf.geometry.y + 1 + ) + ) + def test_list_of_polygons_check(poly_geo_plot, basic_polygon): """Check that the polygon assert works with a list of polygons.""" @@ -129,11 +132,12 @@ def test_assert_point_fails_list(point_geo_plot, pd_gdf): with pytest.raises(ValueError, match="points_expected is not expected"): point_geo_plot.assert_points(points_expected=list_geo) + def test_get_points(point_geo_plot, pd_gdf): """Tests that get_points returns correct values""" xy_values = point_geo_plot.get_points() - assert(list(sorted(xy_values.x)) == sorted(list(pd_gdf.geometry.x))) - assert(list(sorted(xy_values.y)) == sorted(list(pd_gdf.geometry.y))) + assert list(sorted(xy_values.x)) == sorted(list(pd_gdf.geometry.x)) + assert list(sorted(xy_values.y)) == sorted(list(pd_gdf.geometry.y)) def test_assert_points_custom_message(point_geo_plot, bad_pd_gdf): diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index 07384fd6..988cc677 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -263,9 +263,9 @@ def assert_points(self, points_expected, m="Incorrect Point Data"): String error message if assertion is not met. """ if isinstance(points_expected, gpd.geodataframe.GeoDataFrame): - xy_expected = pd.DataFrame(columns=['x', 'y']) - xy_expected['x'] = points_expected.geometry.x - xy_expected['y'] = points_expected.geometry.y + xy_expected = pd.DataFrame(columns=["x", "y"]) + xy_expected["x"] = points_expected.geometry.x + xy_expected["y"] = points_expected.geometry.y xy_expected = xy_expected.sort_values(by="x") xy_expected.reset_index(inplace=True, drop=True) try: @@ -279,7 +279,6 @@ def assert_points(self, points_expected, m="Incorrect Point Data"): "points_expected is not expected type: GeoDataFrame" ) - ### LINES ### def _convert_multilines(self, df, column_title): From 7ac5d41ac3131913dd7d3dbb8c5fd2e6f571bcc1 Mon Sep 17 00:00:00 2001 From: nkorinek Date: Thu, 27 Feb 2020 10:38:39 -0700 Subject: [PATCH 06/14] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index de1bc962..aac3da87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +* Created functions to test point geometries in VectorTester (@nkorinek, #176) ## [0.1.2] * Created a vignette covering the testing of histograms (@ryla5068, #149) From c75e42152e3ec06d0f8c4feadfca6703edba505d Mon Sep 17 00:00:00 2001 From: nkorinek Date: Mon, 16 Mar 2020 15:41:13 -0600 Subject: [PATCH 07/14] Rough draft for bug fix --- matplotcheck/vector.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index 45018a68..e6c8e7c4 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -270,11 +270,23 @@ def assert_points(self, points_expected, m="Incorrect Point Data"): String error message if assertion is not met. """ if isinstance(points_expected, gpd.geodataframe.GeoDataFrame): + points = self.get_points() xy_expected = pd.DataFrame(columns=["x", "y"]) xy_expected["x"] = points_expected.geometry.x xy_expected["y"] = points_expected.geometry.y xy_expected = xy_expected.sort_values(by="x") xy_expected.reset_index(inplace=True, drop=True) + if len(points) != len(xy_expected): + points_zeros = (points['x'] == 0) & (points['y'] == 0) + if points_zeros.any(): + expected_zeros = (xy_expected['x'] == 0) & (xy_expected['y'] == 0) + keep = expected_zeros.sum() + zeros_index_vals = points_zeros.index[points_zeros.tolist()] + for i in range(keep): + points_zeros.at[zeros_index_vals[i]] = False + points = points[~points_zeros].reset_index(inplace=True, drop=True) + else: + raise AssertionError("points_expected's length does not match the stored data's length.") try: pd.testing.assert_frame_equal( left=self.get_points(), right=xy_expected From 075052cb53f62b2a63e5addf17ed2c4fda2c32a6 Mon Sep 17 00:00:00 2001 From: nkorinek Date: Mon, 16 Mar 2020 15:57:34 -0600 Subject: [PATCH 08/14] Fixed bug with multiple geometries plotted alongside bug with identical x values causing failure! --- matplotcheck/vector.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index e6c8e7c4..4b694f2e 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -252,7 +252,7 @@ def get_points(self): output: DataFrame with columns 'x' and 'y'. Each row represents one points coordinates. """ - points = self.get_xy(points_only=True).sort_values(by="x") + points = self.get_xy(points_only=True).sort_values(by=["x", "y"]) points.reset_index(inplace=True, drop=True) return points @@ -274,23 +274,28 @@ def assert_points(self, points_expected, m="Incorrect Point Data"): xy_expected = pd.DataFrame(columns=["x", "y"]) xy_expected["x"] = points_expected.geometry.x xy_expected["y"] = points_expected.geometry.y - xy_expected = xy_expected.sort_values(by="x") + xy_expected = xy_expected.sort_values(by=["x", "y"]) xy_expected.reset_index(inplace=True, drop=True) if len(points) != len(xy_expected): - points_zeros = (points['x'] == 0) & (points['y'] == 0) + points_zeros = (points["x"] == 0) & (points["y"] == 0) if points_zeros.any(): - expected_zeros = (xy_expected['x'] == 0) & (xy_expected['y'] == 0) + expected_zeros = (xy_expected["x"] == 0) & ( + xy_expected["y"] == 0 + ) keep = expected_zeros.sum() - zeros_index_vals = points_zeros.index[points_zeros.tolist()] + zeros_index_vals = points_zeros.index[ + points_zeros.tolist() + ] for i in range(keep): - points_zeros.at[zeros_index_vals[i]] = False - points = points[~points_zeros].reset_index(inplace=True, drop=True) + points_zeros.at[zeros_index_vals[i]] = False + points = points[~points_zeros].reset_index(drop=True) else: - raise AssertionError("points_expected's length does not match the stored data's length.") + raise AssertionError( + "points_expected's length does not match the stored" + "data's length." + ) try: - pd.testing.assert_frame_equal( - left=self.get_points(), right=xy_expected - ) + pd.testing.assert_frame_equal(left=points, right=xy_expected) except AssertionError: raise AssertionError(m) else: From a7927259eaf243458a2e6701f538f3647ae1c4b4 Mon Sep 17 00:00:00 2001 From: nkorinek Date: Mon, 16 Mar 2020 16:00:03 -0600 Subject: [PATCH 09/14] typo --- matplotcheck/vector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index 4b694f2e..a2894079 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -216,7 +216,7 @@ def sort_collection_by_markersize(self): return df def assert_collection_sorted_by_markersize(self, df_expected, sort_column): - """Asserts a collection of points vary in size by column expresse din + """Asserts a collection of points vary in size by column expressed in sort_column Parameters From 6876a504d6c9c3d09ba4b861da600d9a80d71382 Mon Sep 17 00:00:00 2001 From: nkorinek Date: Tue, 17 Mar 2020 13:02:31 -0600 Subject: [PATCH 10/14] Fixed small bug with markersize --- matplotcheck/vector.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index a2894079..038a4b4d 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -196,22 +196,23 @@ def sort_collection_by_markersize(self): """ df = pd.DataFrame(columns=("x", "y", "markersize")) for c in self.ax.collections: - offsets, markersizes = c.get_offsets(), c.get_sizes() - x_data, y_data = ( - [offset[0] for offset in offsets], - [offset[1] for offset in offsets], - ) - if len(markersizes) == 1: - markersize = [markersizes[0]] * len(offsets) - df2 = pd.DataFrame( - {"x": x_data, "y": y_data, "markersize": markersize} - ) - df = df.append(df2) - elif len(markersizes) == len(offsets): - df2 = pd.DataFrame( - {"x": x_data, "y": y_data, "markersize": markersizes} + if isinstance(c, matplotlib.collections.PathCollection): + offsets, markersizes = c.get_offsets(), c.get_sizes() + x_data, y_data = ( + [offset[0] for offset in offsets], + [offset[1] for offset in offsets], ) - df = df.append(df2) + if len(markersizes) == 1: + markersize = [markersizes[0]] * len(offsets) + df2 = pd.DataFrame( + {"x": x_data, "y": y_data, "markersize": markersize} + ) + df = df.append(df2) + elif len(markersizes) == len(offsets): + df2 = pd.DataFrame( + {"x": x_data, "y": y_data, "markersize": markersizes} + ) + df = df.append(df2) df = df.sort_values(by="markersize").reset_index(drop=True) return df From b73e4ef761fd41d52d5b650f367ec780464c5177 Mon Sep 17 00:00:00 2001 From: nkorinek Date: Tue, 17 Mar 2020 13:20:25 -0600 Subject: [PATCH 11/14] Added comments explaining code --- matplotcheck/vector.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index 038a4b4d..c7410820 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -277,7 +277,10 @@ def assert_points(self, points_expected, m="Incorrect Point Data"): xy_expected["y"] = points_expected.geometry.y xy_expected = xy_expected.sort_values(by=["x", "y"]) xy_expected.reset_index(inplace=True, drop=True) + # Fix for failure if more than points were plotted in matplotlib if len(points) != len(xy_expected): + # Checks if there are extra 0, 0 coords in the DataFrame + # returned from self.get_points and removes them. points_zeros = (points["x"] == 0) & (points["y"] == 0) if points_zeros.any(): expected_zeros = (xy_expected["x"] == 0) & ( From d2a1972736d60a9feb2c279fac762731f41e1abd Mon Sep 17 00:00:00 2001 From: nkorinek Date: Wed, 18 Mar 2020 10:15:01 -0600 Subject: [PATCH 12/14] Taking out redundant tests --- matplotcheck/vector.py | 57 ------------------------------------------ 1 file changed, 57 deletions(-) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index c7410820..655a1e6c 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -21,63 +21,6 @@ def __init__(self, ax): """Initialize the vector tester""" super(VectorTester, self).__init__(ax) - def assert_legend_no_overlay_content( - self, m="Legend overlays plot contents" - ): - """Asserts that each legend does not overlay plot contents with error - message m - - Parameters - --------- - m: string - error message if assertion is not met - """ - plot_extent = self.ax.get_window_extent().get_points() - legends = self.get_legends() - for leg in legends: - leg_extent = leg.get_window_extent().get_points() - legend_left = leg_extent[1][0] < plot_extent[0][0] - legend_right = leg_extent[0][0] > plot_extent[1][0] - legend_below = leg_extent[1][1] < plot_extent[0][1] - assert legend_left or legend_right or legend_below, m - - def _legends_overlap(self, b1, b2): - """Helper function for assert_no_legend_overlap - Boolean value if points of window extents for b1 and b2 overlap - - Parameters - ---------- - b1: bounding box of window extents - b2: bounding box of window extents - - Returns - ------ - boolean value that says if bounding boxes b1 and b2 overlap - """ - x_overlap = (b1[0][0] <= b2[1][0] and b1[0][0] >= b2[0][0]) or ( - b1[1][0] <= b2[1][0] and b1[1][0] >= b2[0][0] - ) - y_overlap = (b1[0][1] <= b2[1][1] and b1[0][1] >= b2[0][1]) or ( - b1[1][1] <= b2[1][1] and b1[1][1] >= b2[0][1] - ) - return x_overlap and y_overlap - - def assert_no_legend_overlap(self, m="Legends overlap eachother"): - """Asserts there are no two legends in Axes ax that overlap each other - with error message m - - Parameters - ---------- - m: string error message if assertion is not met - """ - legends = self.get_legends() - n = len(legends) - for i in range(n - 1): - leg_extent1 = legends[i].get_window_extent().get_points() - for j in range(i + 1, n): - leg_extent2 = legends[j].get_window_extent().get_points() - assert not self._legends_overlap(leg_extent1, leg_extent2), m - """ Check Data """ def _convert_length(self, arr, n): From 7e59d4779ab905a67dcce2a900f886616c3b62cd Mon Sep 17 00:00:00 2001 From: nkorinek Date: Wed, 18 Mar 2020 12:36:45 -0600 Subject: [PATCH 13/14] Typo --- matplotcheck/vector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index 655a1e6c..61f9c00c 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -103,7 +103,7 @@ def get_points_by_attributes(self): return sorted([sorted(p) for p in points_grouped]) def assert_points_grouped_by_type( - self, data_exp, sort_column, m="Point attribtues not accurate by type" + self, data_exp, sort_column, m="Point attributes not accurate by type" ): """Asserts that the points on Axes ax display attributes based on their type with error message m From 3b8a20b91cd72ab4faf72879ff0fe3ae0eedab91 Mon Sep 17 00:00:00 2001 From: nkorinek Date: Wed, 18 Mar 2020 14:30:27 -0600 Subject: [PATCH 14/14] Fixing how vector checks for truth value of a dataframe --- matplotcheck/vector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matplotcheck/vector.py b/matplotcheck/vector.py index 61f9c00c..ab77c8da 100644 --- a/matplotcheck/vector.py +++ b/matplotcheck/vector.py @@ -455,7 +455,7 @@ def assert_lines_grouped_by_type( grouped_exp = sorted([sorted(l) for l in grouped_exp]) plt.close(fig) np.testing.assert_equal(groups, grouped_exp, m) - elif not lines_expected: + elif lines_expected is None: pass else: raise ValueError(