Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

TST: convert unittests to pytest #601

Merged
merged 2 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 27 additions & 31 deletions libpysal/cg/ops/tests/test_accessors.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
from ....io.geotable.file import read_files as rf
from .. import _accessors as to_test
from ...shapes import Point, Chain, Polygon, Rectangle, LineSegment
from ....common import pandas, RTOL, ATOL
from ....examples import get_path
import numpy as np
import unittest as ut
import pytest

PANDAS_EXTINCT = pandas is None
from ....common import ATOL, RTOL, pandas
from ....examples import get_path
from ....io.geotable.file import read_files as rf
from ...shapes import Chain, LineSegment, Point, Polygon, Rectangle
from .. import _accessors as to_test


@ut.skipIf(PANDAS_EXTINCT, "Missing pandas.")
class Test_Accessors(ut.TestCase):
def setUp(self):
class TestAccessors:
def setup_method(self):
self.polygons = rf(get_path("Polygon.shp"))
self.points = rf(get_path("Point.shp"))
self.lines = rf(get_path("Line.shp"))

def test_area(self):

with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.area(self.points)
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.area(self.lines)

areas = to_test.area(self.polygons).values
answer = [0.000284, 0.000263, 0.001536]
np.testing.assert_allclose(answer, areas, rtol=RTOL, atol=ATOL * 10)

def test_bbox(self):

with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.bbox(self.points)
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.bbox(self.lines)

answer = [
Expand Down Expand Up @@ -60,7 +56,7 @@ def test_bbox(self):
np.testing.assert_allclose(ans, bbox, rtol=RTOL, atol=ATOL)

def test_bounding_box(self):
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.bounding_box(self.points)

line_rects = to_test.bounding_box(self.lines).tolist()
Expand Down Expand Up @@ -106,12 +102,12 @@ def test_bounding_box(self):
for bbox, answer in zip(pgon_bboxes, pgon_answers):
np.testing.assert_allclose(bbox, answer, atol=ATOL, rtol=RTOL)
for rectangle in line_rects + pgon_rects:
self.assertIsInstance(rectangle, Rectangle)
assert isinstance(rectangle, Rectangle)

def test_centroid(self):
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.centroid(self.points)
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.centroid(self.lines)

centroids = to_test.centroid(self.polygons).tolist()
Expand All @@ -127,16 +123,16 @@ def test_centroid(self):

def test_holes(self):
holed_polygons = rf(get_path("Polygon_Holes.shp"))
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.centroid(self.points)
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.centroid(self.lines)

no_holes = to_test.holes(self.polygons).tolist()
holes = to_test.holes(holed_polygons).tolist()

for elist in no_holes:
self.assertEqual(elist, [[]])
assert elist == [[]]

answers = [
[
Expand Down Expand Up @@ -195,7 +191,7 @@ def test_holes(self):
np.testing.assert_allclose(sub_hole, sub_answer, rtol=RTOL, atol=ATOL)

def test_len(self):
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.len(self.points)

line_len = to_test.len(self.lines)
Expand All @@ -212,7 +208,7 @@ def test_len(self):
np.testing.assert_allclose(pgon_len, pgon_answers, rtol=RTOL, atol=ATOL)

def test_parts(self):
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.parts(self.points)

line_parts = to_test.parts(self.lines)
Expand Down Expand Up @@ -318,9 +314,9 @@ def test_parts(self):
np.testing.assert_allclose(piece, sub_answer, rtol=RTOL, atol=ATOL)

def test_perimeter(self):
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.perimeter(self.points)
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.perimeter(self.lines)

pgon_perim = to_test.perimeter(self.polygons)
Expand All @@ -331,9 +327,9 @@ def test_perimeter(self):
)

def test_segments(self):
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.segments(self.points)
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.segments(self.polygons)

line_segments = to_test.segments(self.lines)
Expand Down Expand Up @@ -396,12 +392,12 @@ def test_segments(self):

for parts, points in zip(flattened, answers):
for piece, answer in zip(parts, points):
self.assertIsInstance(piece, LineSegment)
assert isinstance(piece, LineSegment)
p1, p2 = piece.p1, piece.p2
np.testing.assert_allclose([p1, p2], answer)

def test_vertices(self):
with self.assertRaises(AttributeError):
with pytest.raises(AttributeError):
to_test.vertices(self.points)

line_verts = to_test.vertices(self.lines).tolist()
Expand Down
20 changes: 10 additions & 10 deletions libpysal/cg/ops/tests/test_shapely.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import unittest as ut
import pytest
from .. import _shapely as sht
from ...shapes import Point, Chain, Polygon

Expand All @@ -10,9 +10,9 @@
from warnings import warn


@ut.skip("Skipping shapely during reorg.")
class Test_Shapely(ut.TestCase):
def setUp(self):
@pytest.mark.skip("Skipping shapely during reorg.")
class Test_Shapely:
def setup_method(self):
self.polygons = rf(get_path("Polygon.shp"))
self.points = rf(get_path("Point.shp"))
self.lines = rf(get_path("Line.shp"))
Expand All @@ -36,7 +36,7 @@ def compare(self, func_name, df, **kwargs):
if comp.is_shape(tabular) and comp.is_shape(shapely):
comp.equal(tabular, shapely)
else:
self.assertEqual(tabular, shapely)
assert tabular == shapely
except NotImplementedError as e:
warn("The shapely/PySAL bridge is not implemented: {}.".format(e))
return True
Expand Down Expand Up @@ -123,21 +123,21 @@ def test_has_z(self):
def test_is_empty(self):
"""
PySAL doesn't really support empty shapes. Like, the following errors out:

```
ps.cg.Polygon([[]])
```

and you can make it work by:

```
ps.cg.Polygon([[()]])
```

but that won't convert over to shapely.

So, we're only testing the negative here.

"""
for df in self.dframes:
self.compare("is_empty", df)
Expand Down Expand Up @@ -219,5 +219,5 @@ def test_interpolate(self):
if isinstance(df.geometry[0], Chain):
self.compare("interpolate", df, distance=np.random.randint(10))
else:
with self.assertRaises(TypeError):
with pytest.raises(TypeError):
self.compare("interpolate", df, distance=np.random.randint(10))
45 changes: 18 additions & 27 deletions libpysal/cg/ops/tests/test_tabular.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import unittest as ut
from .. import tabular as ta
from ....common import RTOL, ATOL, pandas, requires as _requires
import numpy as np

from ....common import ATOL, RTOL, pandas
from ....common import requires as _requires
from ....examples import get_path
from ...shapes import Polygon
from ....io import geotable as pdio
from ... import ops as GIS
import numpy as np

try:
import shapely as shp
except ImportError:
shp = None

PANDAS_EXTINCT = pandas is None
SHAPELY_EXTINCT = shp is None
from ...shapes import Polygon
from .. import tabular as ta


@ut.skipIf(PANDAS_EXTINCT or SHAPELY_EXTINCT, "Missing pandas or shapely.")
class Test_Tabular(ut.TestCase):
def setUp(self):
class TestTabular:
def setup_method(self):
import pandas as pd

self.columbus = pdio.read_files(get_path("columbus.shp"))
Expand All @@ -40,11 +32,11 @@ def test_round_trip(self):
import pandas as pd

geodf = GIS.tabular.to_gdf(self.columbus)
self.assertIsInstance(geodf, gpd.GeoDataFrame)
assert isinstance(geodf, gpd.GeoDataFrame)
new_df = GIS.tabular.to_df(geodf)
self.assertIsInstance(new_df, pd.DataFrame)
assert isinstance(new_df, pd.DataFrame)
for new, old in zip(new_df.geometry, self.columbus.geometry):
self.assertEqual(new, old)
assert new == old

def test_spatial_join(self):
pass
Expand All @@ -54,18 +46,17 @@ def test_spatial_overlay(self):

def test_dissolve(self):
out = GIS.tabular.dissolve(self.exdf, by="regime")
self.assertEqual(out[0].area, 2.0)
self.assertEqual(out[1].area, 2.0)
assert out[0].area == 2.0
assert out[1].area == 2.0

answer_vertices0 = set([(0, 0), (0, 1), (0, 2), (1, 2), (1, 1), (1, 0), (0, 0)])
answer_vertices1 = set([(2, 1), (2, 0), (1, 0), (1, 1), (1, 2), (2, 2), (2, 1)])

s0 = set([tuple(map(int,t)) for t in out[0].vertices])
s1 = set([tuple(map(int,t)) for t in out[1].vertices])

self.assertTrue(s0==answer_vertices0)
self.assertTrue(s1==answer_vertices1)
s0 = set([tuple(map(int, t)) for t in out[0].vertices])
s1 = set([tuple(map(int, t)) for t in out[1].vertices])

assert s0 == answer_vertices0
assert s1 == answer_vertices1

def test_clip(self):
pass
Expand All @@ -75,7 +66,7 @@ def test_erase(self):

def test_union(self):
new_geom = GIS.tabular.union(self.exdf)
self.assertEqual(new_geom.area, 4)
assert new_geom.area == 4

def test_intersection(self):
pass
Expand Down
4 changes: 2 additions & 2 deletions libpysal/cg/tests/test_ashapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@


@skipIf(GEOPANDAS_EXTINCT, "Geopandas is missing, so test will not run.")
class Test_Alpha_Shapes(TestCase):
def setUp(self):
class Test_Alpha_Shapes:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also occasionally sorted imports with ruff and changed Test_Rook to TestRook to make ruff happy but not consistently.

So are we OK with underscored class names for now or in general? I have no problem with "for now," especially not in this PR, but probably we'll want to take care of that soon. And I can loop that in with #589.

Copy link
Member Author

@martinfleis martinfleis Oct 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd change private bits like tests. We can have a discussion about public but I would probably keep those intact to avoid unnecessary deprecations.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

def setup_method(self):
eberly = geopandas.read_file(get_path("eberly_net.shp"))
eberly_vertices = eberly.geometry.apply(
lambda x: np.hstack(x.xy).reshape(2, 2).T
Expand Down
34 changes: 13 additions & 21 deletions libpysal/cg/tests/test_geoJSON.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
from ..shapes import Point, Chain, asShape
from ...io.fileio import FileIO as psopen
from ... import examples as pysal_examples
import doctest
import unittest


class test_MultiPloygon(unittest.TestCase):
class Testtest_MultiPloygon:
def test___init__1(self):
"""Tests conversion of polygons with multiple shells to
geoJSON multipolygons and back.

"""

ncovr = pysal_examples.load_example("NCOVR")
Expand All @@ -19,12 +17,12 @@ def test___init__1(self):
for poly in multipolygons:
json = poly.__geo_interface__
shape = asShape(json)
self.assertEqual(json["type"], "MultiPolygon")
self.assertEqual(str(shape.holes), str(poly.holes))
self.assertEqual(str(shape.parts), str(poly.parts))
assert json["type"] == "MultiPolygon"
assert str(shape.holes) == str(poly.holes)
assert str(shape.parts) == str(poly.parts)


class test_MultiLineString(unittest.TestCase):
class Testtest_MultiLineString:
def test_multipart_chain(self):
vertices = [
[Point((0, 0)), Point((1, 0)), Point((1, 5))],
Expand All @@ -39,22 +37,16 @@ def test_multipart_chain(self):
chain2 = Chain(vertices)

json = chain0.__geo_interface__
self.assertEqual(json["type"], "LineString")
self.assertEqual(len(json["coordinates"]), 3)
assert json["type"] == "LineString"
assert len(json["coordinates"]) == 3

json = chain1.__geo_interface__
self.assertEqual(json["type"], "LineString")
self.assertEqual(len(json["coordinates"]), 3)
assert json["type"] == "LineString"
assert len(json["coordinates"]) == 3

json = chain2.__geo_interface__
self.assertEqual(json["type"], "MultiLineString")
self.assertEqual(len(json["coordinates"]), 2)
assert json["type"] == "MultiLineString"
assert len(json["coordinates"]) == 2

chain3 = asShape(json)
self.assertEqual(chain2.parts, chain3.parts)


if __name__ == "__main__":
unittest.main()
# runner = unittest.TextTestRunner()
# runner.run(suite)
assert chain2.parts == chain3.parts
Loading