diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..8f618f0a --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +__pycache__/ +.pytest_cache/ +.venv/ +.vscode/ +.mypy_cache +poetry.lock \ No newline at end of file diff --git a/functions/level_1/five_title.py b/functions/level_1/five_title.py index b5914622..3e6bc77c 100644 --- a/functions/level_1/five_title.py +++ b/functions/level_1/five_title.py @@ -2,8 +2,8 @@ def change_copy_item(title: str, max_main_item_title_length: int = 100) -> str: - additional_copy_text: str = 'Copy of' - title_with_additional_copy_text: str = f'{additional_copy_text} {title}' + additional_copy_text: str = "Copy of" + title_with_additional_copy_text: str = f"{additional_copy_text} {title}" if len(title_with_additional_copy_text) >= max_main_item_title_length: return title @@ -11,6 +11,12 @@ def change_copy_item(title: str, max_main_item_title_length: int = 100) -> str: return title_with_additional_copy_text last_element = title.split()[-1] - element_in_brackets = last_element.split('(')[-1].split(')')[0] - has_copy_number = all([re.search(r'\(\d+\)', last_element), element_in_brackets.isdigit()]) - return title.replace(title.split()[-1], f'({int(element_in_brackets) + 1})') if has_copy_number else f'{title} (2)' + element_in_brackets = last_element.split("(")[-1].split(")")[0] + has_copy_number = all( + [re.search(r"\(\d+\)", last_element), element_in_brackets.isdigit()] + ) + return ( + title.replace(title.split()[-1], f"({int(element_in_brackets) + 1})") + if has_copy_number + else f"{title} (2)" + ) diff --git a/functions/level_1/four_bank_parser.py b/functions/level_1/four_bank_parser.py index d0924699..9b5c3370 100644 --- a/functions/level_1/four_bank_parser.py +++ b/functions/level_1/four_bank_parser.py @@ -22,12 +22,12 @@ class Expense(NamedTuple): def parse_ineco_expense(sms: SmsMessage, cards: list[BankCard]) -> Expense: - raw_sum, raw_details = sms.text.split(', ') - raw_details = raw_details.split(' authcode ')[0] - raw_card, raw_date, raw_time, spend_in = raw_details.split(' ', maxsplit=3) + raw_sum, raw_details = sms.text.split(", ") + raw_details = raw_details.split(" authcode ")[0] + raw_card, raw_date, raw_time, spend_in = raw_details.split(" ", maxsplit=3) return Expense( - amount=decimal.Decimal(raw_sum.split(' ')[-2]), + amount=decimal.Decimal(raw_sum.split(" ")[-2]), card=[c for c in cards if c.last_digits == raw_card[-4:]][0], spent_in=spend_in, - spent_at=datetime.datetime.strptime(f'{raw_date} {raw_time}', '%d.%m.%y %H:%M'), + spent_at=datetime.datetime.strptime(f"{raw_date} {raw_time}", "%d.%m.%y %H:%M"), ) diff --git a/functions/level_1/three_url_builder.py b/functions/level_1/three_url_builder.py index 072a438e..1e3257ef 100644 --- a/functions/level_1/three_url_builder.py +++ b/functions/level_1/three_url_builder.py @@ -1,9 +1,11 @@ from typing import Mapping -def build_url(host_name: str, relative_url: str, get_params: Mapping[str, str] = None) -> str: +def build_url( + host_name: str, relative_url: str, get_params: Mapping[str, str] = None +) -> str: get_params = get_params or {} - querypart = '' + querypart = "" if get_params: - querypart = '?' + '&'.join([f'{k}={v}' for (k, v) in get_params.items()]) - return f'{host_name}/{relative_url}{querypart}' + querypart = "?" + "&".join([f"{k}={v}" for (k, v) in get_params.items()]) + return f"{host_name}/{relative_url}{querypart}" diff --git a/functions/level_1/two_date_parser.py b/functions/level_1/two_date_parser.py index 4979a02b..4aeeeb62 100644 --- a/functions/level_1/two_date_parser.py +++ b/functions/level_1/two_date_parser.py @@ -14,5 +14,3 @@ def compose_datetime_from(date_str: str, time_str: str) -> datetime.datetime: int(hour_str), int(minute_str), ) - - diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..cdb8b9e2 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "testing-exercises" +version = "0.1.0" +description = "" +authors = ["denis sergeevich pekshev "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.12" +pytest = "7.2.1" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/tests/level_1/test_five_title.py b/tests/level_1/test_five_title.py index fe767004..83309280 100644 --- a/tests/level_1/test_five_title.py +++ b/tests/level_1/test_five_title.py @@ -1,5 +1,15 @@ +import pytest from functions.level_1.five_title import change_copy_item -def test_change_copy_item(): - pass +@pytest.mark.parametrize( + "title,max_main_item_title_length,expected", + [ + ("Copy of (1) (2) (3) (4)", 7, "Copy of (1) (2) (3) (4)"), # len condition + ("(1) (2) (3) (4)", 100, "Copy of (1) (2) (3) (4)"), # startwith condition + ("Copy of 1 2 3 4", 100, "Copy of 1 2 3 4 (2)"), # return False + ("Copy of (1) (2) (3) (4)", 100, "Copy of (1) (2) (3) (5)"), # return True + ], +) +def test_change_copy_item(title: str, max_main_item_title_length: int, expected: str): + assert change_copy_item(title, max_main_item_title_length) == expected diff --git a/tests/level_1/test_four_bank_parser.py b/tests/level_1/test_four_bank_parser.py index df6c1b41..29b9eaee 100644 --- a/tests/level_1/test_four_bank_parser.py +++ b/tests/level_1/test_four_bank_parser.py @@ -1,5 +1,52 @@ -from functions.level_1.four_bank_parser import BankCard, SmsMessage, Expense, parse_ineco_expense +import datetime +from decimal import Decimal +import pytest +from functions.level_1.four_bank_parser import ( + BankCard, + SmsMessage, + Expense, + parse_ineco_expense, +) +date_format = "%d.%m.%y %H:%M" -def test_parse_ineco_expense(): - pass +bank_card1 = BankCard(last_digits="4321", owner="denis pekshev") +bank_card2 = BankCard(last_digits="4789", owner="john smith") +bank_card3 = BankCard(last_digits="7654", owner="sarah connor") + + +@pytest.mark.parametrize( + "sms,cards,expected", + [ + ( + SmsMessage( + text="10000 99, 9874-2590-3658-4321 31.10.24 18:00 spent_in authcode 9874", + author="denis pekshev", + sent_at=datetime.datetime.strptime("31.10.24 18:00", date_format), + ), + [bank_card1, bank_card2, bank_card3], + Expense( + amount=Decimal("10000"), + card=bank_card1, + spent_in="spent_in", + spent_at=datetime.datetime.strptime("31.10.24 18:00", date_format), + ), + ), + ( + SmsMessage( + text="5 00, 9874-2590-3658-7654 31.10.24 18:00 spent_in authcode 9874", + author="sarah connor", + sent_at=datetime.datetime.strptime("31.10.24 18:00", date_format), + ), + [bank_card1, bank_card2, bank_card3], + Expense( + amount=Decimal("5"), + card=bank_card3, + spent_in="spent_in", + spent_at=datetime.datetime.strptime("31.10.24 18:00", date_format), + ), + ), + ], +) +def test_parse_ineco_expense(sms: SmsMessage, cards: list[BankCard], expected: Expense): + assert parse_ineco_expense(sms, cards) == expected diff --git a/tests/level_1/test_one_gender.py b/tests/level_1/test_one_gender.py index 31d0bc7f..009fa037 100644 --- a/tests/level_1/test_one_gender.py +++ b/tests/level_1/test_one_gender.py @@ -1,5 +1,15 @@ +import pytest from functions.level_1.one_gender import genderalize -def test_genderalize(): - pass +@pytest.mark.parametrize( + "verb_male,verb_female,gender,expected", + [ + ("Пошел", "Пошла", "male", "Пошел"), + ("Купил", "Купила", "female", "Купила"), + ("Тестировал", "Тестировала", "female", "Тестировала"), + ("Бегал", "Бегала", "male", "Бегал"), + ], +) +def test_genderalize(verb_male: str, verb_female: str, gender: str, expected: str): + assert genderalize(verb_male, verb_female, gender) == expected diff --git a/tests/level_1/test_three_url_builder.py b/tests/level_1/test_three_url_builder.py index bb7b54d2..133eb722 100644 --- a/tests/level_1/test_three_url_builder.py +++ b/tests/level_1/test_three_url_builder.py @@ -1,5 +1,29 @@ +from typing import Mapping +import pytest from functions.level_1.three_url_builder import build_url -def test_build_url(): - pass +@pytest.mark.parametrize( + "host_name,relative_url,get_params,expected", + [ + ( + "localhost", + "part1/part2", + {"id": "1", "name": "some-name", "value": "some-value"}, + "localhost/part1/part2?id=1&name=some-name&value=some-value", + ), + ( + "localhost", + "part1/part2", + None, + "localhost/part1/part2", + ), + ], +) +def test_build_url( + host_name: str, + relative_url: str, + get_params: Mapping[str, str], + expected: str, +): + assert build_url(host_name, relative_url, get_params) == expected diff --git a/tests/level_1/test_two_date_parser.py b/tests/level_1/test_two_date_parser.py index b0247049..060dfdfe 100644 --- a/tests/level_1/test_two_date_parser.py +++ b/tests/level_1/test_two_date_parser.py @@ -1,5 +1,46 @@ +import pytest +import datetime from functions.level_1.two_date_parser import compose_datetime_from -def test_compose_datetime_from(): - pass +@pytest.mark.parametrize( + "date_str,time_str,expected", + [ + ( + datetime.datetime.strftime(datetime.date.today(), "%d-%m-%Y"), # date_str + "08:35", # time_str + datetime.datetime.strptime( + f"{datetime.datetime.strftime(datetime.date.today(), "%d-%m-%Y")} 08:35", + "%d-%m-%Y %H:%M", + ), # expected + ), + ( + datetime.datetime.strftime(datetime.date.today(), "%d-%m-%Y"), # date_str + "23:59", # time_str + datetime.datetime.strptime( + f"{datetime.datetime.strftime(datetime.date.today(), "%d-%m-%Y")} 23:59", + "%d-%m-%Y %H:%M", + ), # expected + ), + ( + datetime.datetime.strftime(datetime.date.today(), "%d-%m-%Y"), # date_str + "00:01", # time_str + datetime.datetime.strptime( + f"{datetime.datetime.strftime(datetime.date.today(), "%d-%m-%Y")} 00:01", + "%d-%m-%Y %H:%M", + ), # expected + ), + ( + "tomorrow", # date_str + "00:01", # time_str + datetime.datetime.strptime( + f"{datetime.datetime.strftime(datetime.date.today() + datetime.timedelta(days=1), "%d-%m-%Y")} 00:01", + "%d-%m-%Y %H:%M", + ), # expected + ), + ], +) +def test_compose_datetime_from( + date_str: str, time_str: str, expected: datetime.datetime +): + assert compose_datetime_from(date_str, time_str) == expected