refactor: rename test/ to tests/

This commit is contained in:
Konstantin Fickel 2026-02-15 17:30:44 +01:00
parent af2debc19b
commit f9ed0463f7
Signed by: kfickel
GPG key ID: A793722F9933C1A5
6 changed files with 16 additions and 17 deletions

View file

@ -0,0 +1,157 @@
from datetime import date, datetime, time
from streamd.localize.extract_datetime import (
extract_date_from_marker,
extract_datetime_from_file_name,
extract_datetime_from_marker,
extract_datetime_from_marker_list,
extract_time_from_marker,
)
class TestExtractDateTime:
def test_extract_date_from_file_name_valid(self):
file_name = "20230101-123456 Some Text.md"
assert datetime(2023, 1, 1, 12, 34, 56) == extract_datetime_from_file_name(
file_name
)
def test_extract_date_from_file_name_invalid(self):
file_name = "invalid-file-name.md"
assert extract_datetime_from_file_name(file_name) is None
def test_extract_date_from_file_name_without_time(self):
file_name = "20230101 Some Text.md"
assert datetime(2023, 1, 1, 0, 0, 0) == extract_datetime_from_file_name(
file_name
)
def test_extract_date_from_file_name_short_time(self):
file_name = "20230101-1234 Some Text.md"
assert datetime(2023, 1, 1, 12, 34, 0) == extract_datetime_from_file_name(
file_name
)
def test_extract_date_from_file_name_empty_string(self):
file_name = ""
assert extract_datetime_from_file_name(file_name) is None
def test_extract_date_from_file_name_with_full_path(self):
file_name = "/path/to/20230101-123456 Some Text.md"
assert datetime(2023, 1, 1, 12, 34, 56) == extract_datetime_from_file_name(
file_name
)
class TestExtractMarkerDateTime:
def test_extract_datetime_from_marker_valid(self):
marker = "20250101150000"
assert datetime(2025, 1, 1, 15, 0, 0) == extract_datetime_from_marker(marker)
def test_extract_datetime_from_marker_invalid_format(self):
assert extract_datetime_from_marker("2025010115000") is None # too short
assert extract_datetime_from_marker("202501011500000") is None # too long
assert extract_datetime_from_marker("2025-01-01T150000") is None # separators
assert extract_datetime_from_marker("2025010115000a") is None # non-digit
assert extract_datetime_from_marker("") is None
def test_extract_datetime_from_marker_invalid_values(self):
assert extract_datetime_from_marker("20250230120000") is None # Feb 30
assert extract_datetime_from_marker("20250101126000") is None # minute 60
assert extract_datetime_from_marker("20250101240000") is None # hour 24
class TestExtractMarkerDate:
def test_extract_date_from_marker_valid(self):
marker = "20250101"
assert date(2025, 1, 1) == extract_date_from_marker(marker)
def test_extract_date_from_marker_invalid_format(self):
assert extract_date_from_marker("2025010") is None # too short
assert extract_date_from_marker("202501011") is None # too long
assert extract_date_from_marker("2025-01-01") is None # separators
assert extract_date_from_marker("2025010a") is None # non-digit
assert extract_date_from_marker("") is None
def test_extract_date_from_marker_invalid_values(self):
assert extract_date_from_marker("20250230") is None # Feb 30
assert extract_date_from_marker("20251301") is None # month 13
assert extract_date_from_marker("20250132") is None # day 32
class TestExtractMarkerTime:
def test_extract_time_from_marker_valid(self):
marker = "150000"
assert time(15, 0, 0) == extract_time_from_marker(marker)
def test_extract_time_from_marker_invalid_format(self):
assert extract_time_from_marker("15000") is None # too short
assert extract_time_from_marker("1500000") is None # too long
assert extract_time_from_marker("15:00:00") is None # separators
assert extract_time_from_marker("15000a") is None # non-digit
assert extract_time_from_marker("") is None
def test_extract_time_from_marker_invalid_values(self):
assert extract_time_from_marker("240000") is None # hour 24
assert extract_time_from_marker("156000") is None # minute 60
assert extract_time_from_marker("150060") is None # second 60
class TestExtractDateTimeFromMarkerList:
def test_no_markers_inherits_datetime(self):
inherited = datetime(2025, 1, 2, 3, 4, 5)
assert inherited == extract_datetime_from_marker_list([], inherited)
def test_unrelated_markers_inherits_datetime(self):
inherited = datetime(2025, 1, 2, 3, 4, 5)
markers = ["not-a-marker", "2025-01-01", "1500", "1234567"]
assert inherited == extract_datetime_from_marker_list(markers, inherited)
def test_date_only_marker_sets_midnight(self):
inherited = datetime(2025, 6, 7, 8, 9, 10)
markers = ["20250101"]
assert datetime(2025, 1, 1, 0, 0, 0) == extract_datetime_from_marker_list(
markers, inherited
)
def test_time_only_marker_inherits_date(self):
inherited = datetime(2025, 6, 7, 8, 9, 10)
markers = ["150000"]
assert datetime(2025, 6, 7, 15, 0, 0) == extract_datetime_from_marker_list(
markers, inherited
)
def test_datetime_marker_overrides_both_date_and_time(self):
inherited = datetime(2025, 6, 7, 8, 9, 10)
markers = ["20250101150000"]
assert datetime(2025, 1, 1, 15, 0, 0) == extract_datetime_from_marker_list(
markers, inherited
)
def test_combined_date_and_time_markers(self):
inherited = datetime(2025, 6, 7, 8, 9, 10)
markers = ["20250101", "150000"]
assert datetime(2025, 1, 1, 15, 0, 0) == extract_datetime_from_marker_list(
markers, inherited
)
def test_first_marker_wins_when_multiple_dates_or_times(self):
inherited = datetime(2025, 6, 7, 8, 9, 10)
markers = ["20250101", "150000", "20250102", "160000"]
assert datetime(2025, 1, 1, 15, 0, 0) == extract_datetime_from_marker_list(
markers, inherited
)
def test_last_separated_date_and_time_win(self):
inherited = datetime(2025, 6, 7, 8, 9, 10)
markers = ["20250101", "150000", "20250102160000"]
assert datetime(2025, 1, 1, 15, 0, 0) == extract_datetime_from_marker_list(
markers, inherited
)
def test_invalid_date_or_time_markers_are_ignored(self):
inherited = datetime(2025, 6, 7, 8, 9, 10)
markers = ["20251301", "240000", "20250101", "150000"]
assert datetime(2025, 1, 1, 15, 0, 0) == extract_datetime_from_marker_list(
markers, inherited
)

View file

@ -0,0 +1,367 @@
import pytest
from streamd.localize.repository_configuration import (
Dimension,
Marker,
MarkerPlacement,
RepositoryConfiguration,
merge_dimensions,
merge_markers,
merge_repository_configuration,
merge_single_dimension,
merge_single_marker,
)
class TestMergeSingleDimension:
def test_second_overrides_display_name_when_non_empty(self):
base = Dimension(display_name="Base", comment="c1", propagate=True)
second = Dimension(display_name="Second", comment="c2", propagate=False)
merged = merge_single_dimension(base, second)
assert merged.display_name == "Second"
assert merged.comment == "c2"
assert merged.propagate is False
def test_second_empty_display_name_falls_back_to_base(self):
base = Dimension(display_name="Base", comment="c1", propagate=True)
second = Dimension(display_name="", comment="c2", propagate=False)
merged = merge_single_dimension(base, second)
assert merged.display_name == "Base"
assert merged.comment == "c2"
assert merged.propagate is False
def test_second_comment_none_does_not_erase_base_comment(self):
base = Dimension(display_name="Base", comment="keep", propagate=True)
second = Dimension(display_name="Second", comment=None, propagate=False)
merged = merge_single_dimension(base, second)
assert merged.display_name == "Second"
assert merged.comment == "keep"
def test_second_comment_non_none_overrides_base_comment(self):
base = Dimension(display_name="Base", comment="c1", propagate=True)
second = Dimension(display_name="Second", comment="c2", propagate=True)
merged = merge_single_dimension(base, second)
assert merged.comment == "c2"
def test_second_propagate_overrides_base_when_provided(self):
base = Dimension(display_name="Base", comment="c1", propagate=True)
second = Dimension(display_name="Second", comment="c2", propagate=False)
merged = merge_single_dimension(base, second)
assert merged.propagate is False
def test_propagate_merging_retains_base_when_second_not_provided(self):
base = Dimension(display_name="Base", comment="c1", propagate=True)
second = Dimension(display_name="Second", comment="c2")
merged = merge_single_dimension(base, second)
assert merged.propagate is True
class TestMergeDimensions:
def test_adds_new_keys_from_second(self):
base = {"a": Dimension(display_name="A", propagate=True)}
second = {"b": Dimension(display_name="B", propagate=False)}
merged = merge_dimensions(base, second)
assert set(merged.keys()) == {"a", "b"}
assert merged["a"].display_name == "A"
assert merged["b"].display_name == "B"
def test_merges_existing_keys(self):
base = {"a": Dimension(display_name="A", comment="c1", propagate=True)}
second = {"a": Dimension(display_name="A2", comment=None, propagate=False)}
merged = merge_dimensions(base, second)
assert merged["a"].display_name == "A2"
assert merged["a"].comment == "c1"
assert merged["a"].propagate is False
def test_does_not_mutate_inputs(self):
base = {"a": Dimension(display_name="A", comment="c1", propagate=True)}
second = {"b": Dimension(display_name="B", comment="c2", propagate=False)}
merged = merge_dimensions(base, second)
assert "b" not in base
assert "a" not in second
assert set(merged.keys()) == {"a", "b"}
class TestMergeSingleMarker:
def test_second_overrides_display_name_when_non_empty(self):
base = Marker(
display_name="Base",
placements=[MarkerPlacement(dimension="project", value=None)],
)
second = Marker(
display_name="Second",
placements=[MarkerPlacement(dimension="timesheet", value="coding")],
)
merged = merge_single_marker(base, second)
assert merged.display_name == "Second"
assert merged.placements == [
MarkerPlacement(dimension="project", value=None, if_with=set()),
MarkerPlacement(dimension="timesheet", value="coding", if_with=set()),
]
def test_second_empty_display_name_falls_back_to_base(self):
base = Marker(display_name="Base", placements=[])
second = Marker(display_name="", placements=[])
merged = merge_single_marker(base, second)
assert merged.display_name == "Base"
def test_appends_new_placements(self):
base = Marker(
display_name="Base",
placements=[
MarkerPlacement(dimension="project"),
],
)
second = Marker(
display_name="Second",
placements=[
MarkerPlacement(
if_with={"Timesheet"}, dimension="timesheet", value="x"
),
],
)
merged = merge_single_marker(base, second)
assert merged.placements == [
MarkerPlacement(dimension="project"),
MarkerPlacement(if_with={"Timesheet"}, dimension="timesheet", value="x"),
]
def test_deduplicates_by_identity_and_second_overrides_base(self):
base = Marker(
display_name="Base",
placements=[
MarkerPlacement(if_with={"A"}, dimension="d", value="v"),
MarkerPlacement(if_with={"B"}, dimension="d", value="v2"),
],
)
second = Marker(
display_name="Second",
placements=[
MarkerPlacement(if_with={"A"}, dimension="d", value="v"),
MarkerPlacement(if_with={"C"}, dimension="d", value="v3"),
],
)
merged = merge_single_marker(base, second)
assert merged.placements == [
MarkerPlacement(if_with={"A"}, dimension="d", value="v"),
MarkerPlacement(if_with={"B"}, dimension="d", value="v2"),
MarkerPlacement(if_with={"C"}, dimension="d", value="v3"),
]
def test_identity_is_order_insensitive_for_if_with(self):
base = Marker(
display_name="Base",
placements=[MarkerPlacement(if_with={"A", "B"}, dimension="d", value="v")],
)
second = Marker(
display_name="Second",
placements=[MarkerPlacement(if_with={"B", "A"}, dimension="d", value="v2")],
)
merged = merge_single_marker(base, second)
# With `if_with` as a set, identity is order-insensitive; second overrides base.
assert merged.placements == [
MarkerPlacement(if_with={"A", "B"}, dimension="d", value="v2"),
]
class TestMergeMarkers:
def test_adds_new_marker_keys_from_second(self):
base = {"M1": Marker(display_name="M1", placements=[])}
second = {"M2": Marker(display_name="M2", placements=[])}
merged = merge_markers(base, second)
assert set(merged.keys()) == {"M1", "M2"}
def test_merges_existing_marker_keys(self):
base = {
"M": Marker(
display_name="Base",
placements=[MarkerPlacement(dimension="project")],
)
}
second = {
"M": Marker(
display_name="Second",
placements=[
MarkerPlacement(
if_with={"Timesheet"}, dimension="timesheet", value="coding"
)
],
)
}
merged = merge_markers(base, second)
assert merged["M"].display_name == "Second"
assert merged["M"].placements == [
MarkerPlacement(dimension="project", value=None, if_with=set()),
MarkerPlacement(
if_with={"Timesheet"}, dimension="timesheet", value="coding"
),
]
def test_does_not_mutate_inputs(self):
base = {"M1": Marker(display_name="M1", placements=[])}
second = {"M2": Marker(display_name="M2", placements=[])}
merged = merge_markers(base, second)
assert "M2" not in base
assert "M1" not in second
assert set(merged.keys()) == {"M1", "M2"}
class TestMergeRepositoryConfiguration:
def test_merges_dimensions_and_markers(self):
base = RepositoryConfiguration(
dimensions={
"project": Dimension(
display_name="Project", comment="c1", propagate=True
),
"moment": Dimension(
display_name="Moment", comment="c2", propagate=True
),
},
markers={
"Streamd": Marker(
display_name="Streamd",
placements=[MarkerPlacement(dimension="project")],
)
},
)
second = RepositoryConfiguration(
dimensions={
"project": Dimension(display_name="Project2", propagate=False),
"timesheet": Dimension(
display_name="Timesheet", comment="c3", propagate=False
),
},
markers={
"Streamd": Marker(
display_name="Streamd2",
placements=[
MarkerPlacement(
if_with={"Timesheet"}, dimension="timesheet", value="coding"
)
],
),
"JobHunting": Marker(
display_name="JobHunting",
placements=[MarkerPlacement(dimension="project")],
),
},
)
merged = merge_repository_configuration(base, second)
assert set(merged.dimensions.keys()) == {"project", "moment", "timesheet"}
assert merged.dimensions["project"].display_name == "Project2"
assert merged.dimensions["project"].comment == "c1"
assert merged.dimensions["project"].propagate is False
assert merged.dimensions["moment"].display_name == "Moment"
assert merged.dimensions["timesheet"].display_name == "Timesheet"
assert set(merged.markers.keys()) == {"Streamd", "JobHunting"}
assert merged.markers["Streamd"].display_name == "Streamd2"
assert merged.markers["Streamd"].placements == [
MarkerPlacement(dimension="project", value=None, if_with=set()),
MarkerPlacement(
if_with={"Timesheet"}, dimension="timesheet", value="coding"
),
]
assert merged.markers["JobHunting"].placements == [
MarkerPlacement(dimension="project", value=None, if_with=set())
]
def test_does_not_mutate_base_or_second(self):
base = RepositoryConfiguration(
dimensions={"a": Dimension(display_name="A", propagate=True)},
markers={"M": Marker(display_name="M", placements=[])},
)
second = RepositoryConfiguration(
dimensions={"b": Dimension(display_name="B", propagate=False)},
markers={"N": Marker(display_name="N", placements=[])},
)
_ = merge_repository_configuration(base, second)
assert set(base.dimensions.keys()) == {"a"}
assert set(second.dimensions.keys()) == {"b"}
assert set(base.markers.keys()) == {"M"}
assert set(second.markers.keys()) == {"N"}
def test_merge_is_associative_for_non_conflicting_inputs(self):
a = RepositoryConfiguration(
dimensions={"d1": Dimension(display_name="D1", propagate=True)},
markers={"m1": Marker(display_name="M1", placements=[])},
)
b = RepositoryConfiguration(
dimensions={"d2": Dimension(display_name="D2", propagate=False)},
markers={"m2": Marker(display_name="M2", placements=[])},
)
c = RepositoryConfiguration(
dimensions={"d3": Dimension(display_name="D3", propagate=False)},
markers={"m3": Marker(display_name="M3", placements=[])},
)
left = merge_repository_configuration(merge_repository_configuration(a, b), c)
right = merge_repository_configuration(a, merge_repository_configuration(b, c))
assert left == right
assert set(left.dimensions.keys()) == {"d1", "d2", "d3"}
assert set(left.markers.keys()) == {"m1", "m2", "m3"}
@pytest.mark.parametrize(
("base", "second", "expected_propagate"),
[
(
RepositoryConfiguration(
dimensions={"d": Dimension(display_name="D", propagate=True)},
markers={},
),
RepositoryConfiguration(
dimensions={"d": Dimension(display_name="D2")},
markers={},
),
True,
)
],
)
def test_merge_repository_configuration_propagate_preserves_base_when_omitted(
base: RepositoryConfiguration,
second: RepositoryConfiguration,
expected_propagate: bool,
):
merged = merge_repository_configuration(base, second)
assert merged.dimensions["d"].propagate is expected_propagate