saving-willy-dev / tests /test_input_handling.py
vancauwe's picture
fix: adapt tests to refactor and explicit module names
8963e74
raw
history blame
7.07 kB
import pytest
from pathlib import Path
from input.input_validator import is_valid_email, is_valid_number
from input.input_validator import get_image_latlon, decimal_coords, get_image_datetime
# generate tests for is_valid_email
# - test with valid email
# - basic email with @ and .
# - test with email with multiple .
# - test with empty email
# - test with None email
# - test with non-string email
# - test with invalid email
# - test with email without @
# - test with email without .
# - test with email without domain
# - test with email without username
# - test with email without TLD
# - test with email with multiple @
# - test with email starting with the + sign
def test_is_valid_email_valid():
assert is_valid_email("[email protected]")
assert is_valid_email("[email protected]")
assert is_valid_email("[email protected]")
assert is_valid_email("[email protected]")
assert is_valid_email("[email protected]")
def test_is_valid_email_empty():
assert not is_valid_email("")
def test_is_valid_email_none():
with pytest.raises(TypeError):
is_valid_email(None)
def test_is_valid_email_non_string():
with pytest.raises(TypeError):
is_valid_email(123)
def test_is_valid_email_invalid():
assert not is_valid_email("a.bc")
assert not is_valid_email("a@bc")
assert not is_valid_email("a.b@cc")
assert not is_valid_email("@b.cc")
assert not is_valid_email("[email protected]")
assert not is_valid_email("a@b.")
assert not is_valid_email("a@bb.")
assert not is_valid_email("[email protected].")
assert not is_valid_email("a@[email protected]")
# not sure how xfails come through the CI pipeline yet.
# maybe better to just comment out this stuff until pipeline is setup, then can check /extend
@pytest.mark.xfail(reason="Bug identified, but while setting up CI having failing tests causes more headache")
def test_is_valid_email_invalid_plus():
assert not is_valid_email("[email protected]")
assert not is_valid_email("[email protected]")
def test_is_valid_number_valid():
# with a sign or without, fractional or integer are all valid
assert is_valid_number("123")
assert is_valid_number("123.456")
assert is_valid_number("-123")
assert is_valid_number("-123.456")
assert is_valid_number("+123")
assert is_valid_number("+123.456")
def test_is_valid_number_empty():
assert not is_valid_number("")
def test_is_valid_number_none():
with pytest.raises(TypeError):
is_valid_number(None)
def test_is_valid_number_invalid():
# func should return False for strings that are not numbers
assert not is_valid_number("abc")
assert not is_valid_number("123abc")
assert not is_valid_number("abc123")
assert not is_valid_number("123.456.789")
assert not is_valid_number("123,456")
assert not is_valid_number("123-456")
assert not is_valid_number("123+456")
def test_is_valid_number_valid():
assert is_valid_number("123")
assert is_valid_number("123.456")
assert is_valid_number("-123")
assert is_valid_number("-123.456")
assert is_valid_number("+123")
assert is_valid_number("+123.456")
def test_is_valid_number_empty():
assert not is_valid_number("")
def test_is_valid_number_none():
with pytest.raises(TypeError):
is_valid_number(None)
def test_is_valid_number_invalid():
assert not is_valid_number("abc")
assert not is_valid_number("123abc")
assert not is_valid_number("abc123")
assert not is_valid_number("123.456.789")
assert not is_valid_number("123,456")
assert not is_valid_number("123-456")
assert not is_valid_number("123+456")
# tests for get_image_datetime
# - testing with a valid image with complete, valid metadata
# - testing with a valid image with incomplete metadata (missing datetime info -- that's a legitimate case we should handle)
# - testing with a valid image with incomplete metadata (missing GPS info -- should not affect the datetime extraction)
# - testing with a valid image with no metadata
# - timezones too
test_data_pth = Path('tests/data/')
def test_get_image_datetime():
# this image has lat, lon, and datetime
f1 = test_data_pth / 'cakes.jpg'
assert get_image_datetime(f1) == "2024:10:24 15:59:45"
#"+02:00"
# hmm, the full datetime requires timezone, which is called OffsetTimeOriginal
# missing GPS loc: this should not interfere with the datetime
f2 = test_data_pth / 'cakes_no_exif_gps.jpg'
assert get_image_datetime(f2) == "2024:10:24 15:59:45"
# missng datetime -> expect None
f3 = test_data_pth / 'cakes_no_exif_datetime.jpg'
assert get_image_datetime(f3) == None
def test_get_image_latlon():
# this image has lat, lon, and datetime
f1 = test_data_pth / 'cakes.jpg'
assert get_image_latlon(f1) == (46.51860277777778, 6.562075)
# missing GPS loc
f2 = test_data_pth / 'cakes_no_exif_gps.jpg'
assert get_image_latlon(f2) == None
# missng datetime -> expect gps not affected
f3 = test_data_pth / 'cakes_no_exif_datetime.jpg'
assert get_image_latlon(f3) == (46.51860277777778, 6.562075)
# tests for get_image_latlon with empty file
def test_get_image_latlon_empty():
assert get_image_latlon("") == None
# tests for decimal_coords
# - without input, py raises TypeError
# - with the wrong length of input (expecting 3 elements in the tuple), expect ValueError
# - with string inputs instead of numeric, we get a TypeError (should the func bother checking this? happens as built in)
# - with ref direction not in ['N', 'S', 'E', 'W'], expect ValueError, try X, x, NW.
# - with valid inputs, expect the correct output
# test data for decimal_coords: (deg,min,sec), ref, expected output
coords_conversion_data = [
((30, 1, 2), 'W', -30.01722222),
((30, 1, 2), 'E', 30.01722222),
((30, 1, 2), 'N', 30.01722222),
((30, 1, 2), 'S', -30.01722222),
((46, 31, 6.97), 'N', 46.51860278),
((6, 33, 43.47), 'E', 6.56207500)
]
@pytest.mark.parametrize("input_coords, ref, expected_output", coords_conversion_data)
def test_decimal_coords(input_coords, ref, expected_output):
assert decimal_coords(input_coords, ref) == pytest.approx(expected_output)
def test_decimal_coords_no_input():
with pytest.raises(TypeError):
decimal_coords()
def test_decimal_coords_wrong_length():
with pytest.raises(ValueError):
decimal_coords((1, 2), 'W')
with pytest.raises(ValueError):
decimal_coords((30,), 'W')
with pytest.raises(ValueError):
decimal_coords((30, 1, 2, 4), 'W')
def test_decimal_coords_non_numeric():
with pytest.raises(TypeError):
decimal_coords(('1', '2', '3'), 'W')
def test_decimal_coords_invalid_ref():
with pytest.raises(ValueError):
decimal_coords((30, 1, 2), 'X')
with pytest.raises(ValueError):
decimal_coords((30, 1, 2), 'x')
with pytest.raises(ValueError):
decimal_coords((30, 1, 2), 'NW')