Spaces:
Sleeping
Sleeping
| 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]") | |
| 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, 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, 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) | |
| ] | |
| 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') | |