mirror of
https://github.com/ivuorinen/emoji.git
synced 2026-03-12 14:59:47 +00:00
feat: add pytest unit tests and CI workflow (#38)
* feat: add pytest unit tests and CI workflow Add 67 tests covering both create_listing.py and dedup.py with shared Pillow-based image fixtures. Add GitHub Actions workflow to run tests on Python file changes. * fix: address PR review feedback - Use monkeypatch.chdir(tmp_path) so tests write to temp dirs instead of polluting the repo's README.md and index.html - Strengthen unicode filename test to assert URL-encoded form (%C3%A9) - Move hashlib import to module level in test_dedup.py - Remove unused _zero_hash helper and Path import - Prefix unused tuple unpacking variables with underscore * fix: add docstrings and strengthen degenerate hash test - Add docstrings to all test classes, methods, and helper functions to achieve 100% docstring coverage - Strengthen test_skips_degenerate_hashes to assert groups == [] instead of only checking for no-crash * fix: use hardcoded MD5 digests and add fixture validation - Replace hashlib.md5() calls with known digest constants to remove hashlib import from test module - Add input validation to _make_gif fixture for clear error messages on empty colors or mismatched durations length
This commit is contained in:
89
tests/conftest.py
Normal file
89
tests/conftest.py
Normal file
@@ -0,0 +1,89 @@
|
||||
"""Shared test fixtures for emoji project tests."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from PIL import Image
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def make_png():
|
||||
"""Factory fixture: creates a small PNG image and returns its Path."""
|
||||
|
||||
def _make_png(
|
||||
directory: Path,
|
||||
name: str,
|
||||
color: tuple = (255, 0, 0, 255),
|
||||
size: tuple[int, int] = (4, 4),
|
||||
) -> Path:
|
||||
img = Image.new("RGBA", size, color)
|
||||
path = directory / name
|
||||
img.save(path, "PNG")
|
||||
return path
|
||||
|
||||
return _make_png
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def make_gif():
|
||||
"""Factory fixture: creates an animated GIF with multiple frames and returns its Path."""
|
||||
|
||||
def _make_gif(
|
||||
directory: Path,
|
||||
name: str,
|
||||
colors: list[tuple],
|
||||
durations: list[int],
|
||||
size: tuple[int, int] = (4, 4),
|
||||
) -> Path:
|
||||
if not colors:
|
||||
raise ValueError("colors must not be empty")
|
||||
if len(durations) != len(colors):
|
||||
raise ValueError(f"durations length ({len(durations)}) must match colors length ({len(colors)})")
|
||||
frames = [Image.new("RGBA", size, c) for c in colors]
|
||||
path = directory / name
|
||||
frames[0].save(
|
||||
path,
|
||||
save_all=True,
|
||||
append_images=frames[1:],
|
||||
duration=durations,
|
||||
loop=0,
|
||||
)
|
||||
return path
|
||||
|
||||
return _make_gif
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def make_jpg():
|
||||
"""Factory fixture: creates a small JPEG image and returns its Path."""
|
||||
|
||||
def _make_jpg(
|
||||
directory: Path,
|
||||
name: str,
|
||||
color: tuple = (255, 0, 0),
|
||||
size: tuple[int, int] = (4, 4),
|
||||
) -> Path:
|
||||
img = Image.new("RGB", size, color)
|
||||
path = directory / name
|
||||
img.save(path, "JPEG")
|
||||
return path
|
||||
|
||||
return _make_jpg
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def emoji_dir(tmp_path, make_png, make_gif, make_jpg):
|
||||
"""Creates a temp directory with several named test images."""
|
||||
d = tmp_path / "emoji"
|
||||
d.mkdir()
|
||||
make_png(d, "alpha.png", color=(255, 0, 0, 255))
|
||||
make_png(d, "beta.png", color=(0, 255, 0, 255))
|
||||
make_png(d, "gamma.png", color=(0, 0, 255, 255))
|
||||
make_jpg(d, "delta.jpg", color=(128, 128, 0))
|
||||
make_gif(
|
||||
d,
|
||||
"animated.gif",
|
||||
colors=[(255, 0, 0, 255), (0, 255, 0, 255)],
|
||||
durations=[100, 100],
|
||||
)
|
||||
return d
|
||||
Reference in New Issue
Block a user