Skip to content

Commit

Permalink
tests: add first approval tests
Browse files Browse the repository at this point in the history
add custom reporter and comparator
  • Loading branch information
matthiasschaub committed May 2, 2024
1 parent 29e4308 commit 1259ed3
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 0 deletions.
26 changes: 26 additions & 0 deletions tests/comparator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from pathlib import Path

import geopandas
from approvaltests.core import FileComparator


class GeoJSONComparator(FileComparator):
def compare(self, received_path: str, approved_path: str) -> bool:
if not Path(approved_path).exists() or Path(approved_path).stat().st_size == 0:
return False

# TODO: find optimal UTM for every feature or different projection
df_received = geopandas.read_file(received_path).to_crs("EPSG:32632")
df_approved = geopandas.read_file(approved_path).to_crs("EPSG:32632")

if len(df_approved) != len(df_received):
return False

area_clipped = df_received.clip(df_approved).area
area_diff = df_approved.area - area_clipped
area_ratio = area_diff / df_approved.area
for r in area_ratio:
# TODO: what is the right threshold
if r > 0.01:
return False
return True
31 changes: 31 additions & 0 deletions tests/integration/test_approval.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from pathlib import Path

import pytest
from approvaltests import Options, verify_binary

from tests.comparator import GeoJSONComparator
from tests.reporter import SketchMapToolReporter

fixtures = Path(__file__).parent / "fixtures"


@pytest.mark.use_fixtures("vector")
@pytest.fixture(scope="session")
def vector_path(tmp_path_factory, uuid_digitize) -> bytes:
return tmp_path_factory.getbasetemp() / uuid_digitize / "vector.geojson"


@pytest.mark.use_fixtures("sketch_map_marked")
@pytest.fixture(scope="session")
def sketch_map_marked_path(tmp_path_factory, uuid_create) -> bytes:
return tmp_path_factory.getbasetemp() / uuid_create / "sketch-map-marked.png"


def test_smt_approver(sketch_map_marked_path, vector_path):
options = (
Options()
.with_reporter(SketchMapToolReporter(sketch_map=sketch_map_marked_path))
.with_comparator(GeoJSONComparator())
)
with open(vector_path, "rb") as f:
verify_binary(f.read(), ".geojson", options=options)
58 changes: 58 additions & 0 deletions tests/reporter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from pathlib import Path

import geopandas
import matplotlib.patches as mpatches
import numpy as np
from approvaltests import Reporter
from matplotlib import pyplot as plt
from matplotlib.widgets import Button
from PIL import Image


class Approver:
def __init__(self, approved_path: Path, received_path: Path, sketch_map: Path):
self.approved_path: Path = approved_path # geojson
self.received_path: Path = received_path # geojson
self.sketch_map: Path = sketch_map # jpg

def plot_difference(self, ax):
"""Plot difference between approved and received GeoJSON features."""
if self.approved_path.exists() and self.approved_path.stat().st_size != 0:
df_approved = geopandas.read_file(self.approved_path)
df_approved.plot(ax=ax, facecolor="none", edgecolor="blue")
df_received = geopandas.read_file(self.received_path)
df_received.plot(ax=ax, facecolor="none", edgecolor="red")

def plot_sketch_map(self, ax):
"""Plot sketch map image."""
image = np.asarray(Image.open(self.sketch_map))
ax.imshow(image)

def approve(self, *_):
self.received_path.replace(self.approved_path)
plt.close()

def open(self):
"""Open dialog for visual comparison."""
fig, axs = plt.subplots(1, 2)
fig.subplots_adjust(bottom=0.2)
self.plot_sketch_map(axs[0])
self.plot_difference(axs[1])

blue_patch = mpatches.Patch(color="blue", label="Approved")
red_patch = mpatches.Patch(color="red", label="Received")
axs[1].legend(handles=[blue_patch, red_patch])

ax_approve = fig.add_axes((0.45, 0.05, 0.1, 0.075))
button = Button(ax_approve, "Approve")
button.on_clicked(self.approve)
plt.show()


class SketchMapToolReporter(Reporter):
def __init__(self, sketch_map: Path):
self.sketch_map: Path = sketch_map

def report(self, received_path, approved_path):
Approver(Path(approved_path), Path(received_path), self.sketch_map).open()
return True

0 comments on commit 1259ed3

Please sign in to comment.