From d0652925298be7759c2f53644d2bd3e7c6c6096f Mon Sep 17 00:00:00 2001 From: Beloded1 Date: Sun, 21 May 2023 00:54:10 +0400 Subject: [PATCH 01/11] Do tests, except bank parser. This part doesn't work. --- ...st_five_title.cpython-310-pytest-7.2.1.pyc | Bin 0 -> 1564 bytes tests/level_1/test_five_title.py | 8 +++++- tests/level_1/test_four_bank_parser.py | 25 ++++++++++++++++-- tests/level_1/test_one_gender.py | 4 ++- tests/level_1/test_three_url_builder.py | 12 ++++++++- tests/level_1/test_two_date_parser.py | 18 +++++++++++-- 6 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 tests/level_1/__pycache__/test_five_title.cpython-310-pytest-7.2.1.pyc diff --git a/tests/level_1/__pycache__/test_five_title.cpython-310-pytest-7.2.1.pyc b/tests/level_1/__pycache__/test_five_title.cpython-310-pytest-7.2.1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e883bfbbedfce098207a51743ed115d6f5ff0e6 GIT binary patch literal 1564 zcmcIkO^+Kj7`Ep#$$oXa0u_YBNC>o+P_#+QZi^aJSW&4G?S+rSD3Udeon)xz1ABJ2 z2{RYU35grWJv2w|`~xohhPn1s)L&3>=Sl%? z8Vt}BGfT&(#>!%LWupq6%w?V2 z3Nc_ibD^q}+bjG4{{;P7sL%t$FbjiqTikjtaQh8@_a<&XK)&X7ta=XRxI zr_r(VDjh*fw{RGOTXONv(!IU#Zo#csZXLn}@sg?61PFd=j79`6_deWB7gvbt{n!9+ zGHJj0UpYrjtMjDtRg=Nt6bXm+O$GcaK7mg|R9fkwAqiFHtp5js&Yp=}aVd z13}{;;$@erV9NCh<>u#=+F=rZDP{KzwsY`8-SBrLw?UkzUmbor{uVBU8h^n>!Z;hJGWniQGBwt! zgz*gMaybbVuOn(K_%RoBQ03_~Jm&QY_tQoBR;A?mH&368(uZ=2Pw^jy+yO|sW#>#* zxdwsq9a Date: Sun, 21 May 2023 12:24:06 +0400 Subject: [PATCH 02/11] Add gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..033df5fb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.venv +__pycache__ From c75874d117b51affd1d398d65336f8aba8c4ac64 Mon Sep 17 00:00:00 2001 From: Beloded1 Date: Sun, 21 May 2023 12:24:24 +0400 Subject: [PATCH 03/11] Del pycache --- .../test_five_title.cpython-310-pytest-7.2.1.pyc | Bin 1564 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/level_1/__pycache__/test_five_title.cpython-310-pytest-7.2.1.pyc diff --git a/tests/level_1/__pycache__/test_five_title.cpython-310-pytest-7.2.1.pyc b/tests/level_1/__pycache__/test_five_title.cpython-310-pytest-7.2.1.pyc deleted file mode 100644 index 5e883bfbbedfce098207a51743ed115d6f5ff0e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1564 zcmcIkO^+Kj7`Ep#$$oXa0u_YBNC>o+P_#+QZi^aJSW&4G?S+rSD3Udeon)xz1ABJ2 z2{RYU35grWJv2w|`~xohhPn1s)L&3>=Sl%? z8Vt}BGfT&(#>!%LWupq6%w?V2 z3Nc_ibD^q}+bjG4{{;P7sL%t$FbjiqTikjtaQh8@_a<&XK)&X7ta=XRxI zr_r(VDjh*fw{RGOTXONv(!IU#Zo#csZXLn}@sg?61PFd=j79`6_deWB7gvbt{n!9+ zGHJj0UpYrjtMjDtRg=Nt6bXm+O$GcaK7mg|R9fkwAqiFHtp5js&Yp=}aVd z13}{;;$@erV9NCh<>u#=+F=rZDP{KzwsY`8-SBrLw?UkzUmbor{uVBU8h^n>!Z;hJGWniQGBwt! zgz*gMaybbVuOn(K_%RoBQ03_~Jm&QY_tQoBR;A?mH&368(uZ=2Pw^jy+yO|sW#>#* zxdwsq9a Date: Tue, 23 May 2023 11:11:01 +0000 Subject: [PATCH 04/11] Fixed bugs. --- tests/level_1/test_five_title.py | 8 ++++++-- tests/level_1/test_four_bank_parser.py | 19 +++++++------------ tests/level_1/test_one_gender.py | 8 +++++--- tests/level_1/test_three_url_builder.py | 4 +++- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/tests/level_1/test_five_title.py b/tests/level_1/test_five_title.py index 013157da..a4033a2a 100644 --- a/tests/level_1/test_five_title.py +++ b/tests/level_1/test_five_title.py @@ -1,11 +1,15 @@ from functions.level_1.five_title import change_copy_item -def test_change_copy_item(): +def test_change_copy_item_add_copy(): assert change_copy_item('My Item') == 'Copy of My Item' + +def test_change_copy_item_increase_number_of_copy(): assert change_copy_item('Copy of My Item (2)') == 'Copy of My Item (3)' +def test_change_copy_item_behavior_for_long_title(): assert change_copy_item('Very long title with many words', max_main_item_title_length=10) == 'Very long title with many words' - assert change_copy_item("Copy of My Item") == "Copy of My Item" +def test_change_copy_item_for_basic_case_with_text(): + assert change_copy_item("Copy of My Item") == "Copy of My Item (2)" \ No newline at end of file diff --git a/tests/level_1/test_four_bank_parser.py b/tests/level_1/test_four_bank_parser.py index 499211f2..53b8ea4a 100644 --- a/tests/level_1/test_four_bank_parser.py +++ b/tests/level_1/test_four_bank_parser.py @@ -3,24 +3,19 @@ import pytest import decimal -def test_parse_ineco_expense(): +def test_parse_ineco_expense_succes(): sms = SmsMessage( - text="100.00 RUB. CARD1234, authcode 1234. 01.01.23 11:30", + text="100.00 CARD1234, authcode1234 01.01.23 11:30 Alfa", author="Alfa Bank", sent_at=datetime.datetime(2023, 1, 1, 11, 30) ) cards = [ BankCard(last_digits="1234", owner= "Alex"), - BankCard(last_digits="5678", owner= "Alexandr"), + BankCard(last_digits="1234", owner= "Alexandr"), ] + result = parse_ineco_expense(sms, cards) - expected = Expense( - amount=decimal.Decimal("100.00"), - card=BankCard(last_digits="1234"), - spent_in="CARD1234", - spent_at=datetime.datetime(2023, 1, 1, 11, 30), - ) - assert result == expected + + assert result.amount == decimal.Decimal("100.00") + assert result.card.last_digits == '1234' - with pytest.raises(ValueError): - parse_ineco_expense(sms, cards) \ No newline at end of file diff --git a/tests/level_1/test_one_gender.py b/tests/level_1/test_one_gender.py index 514f2232..75bc4339 100644 --- a/tests/level_1/test_one_gender.py +++ b/tests/level_1/test_one_gender.py @@ -1,7 +1,9 @@ from functions.level_1.one_gender import genderalize -def test_genderalize(): +def test_genderalize_is_male(): assert genderalize('говорил', 'говорила', 'male') == 'говорил' - assert genderalize('говорил', 'говорила', 'female') == 'говорила' - assert genderalize('говорил', 'говорила', 'transgender') == 'говорила' \ No newline at end of file + +def test_genderalize_is_not_male(): + assert genderalize('говорил', 'говорила', 'any str, except "male"') == 'говорила' + diff --git a/tests/level_1/test_three_url_builder.py b/tests/level_1/test_three_url_builder.py index d7d55d03..038e53f0 100644 --- a/tests/level_1/test_three_url_builder.py +++ b/tests/level_1/test_three_url_builder.py @@ -1,15 +1,17 @@ from functions.level_1.three_url_builder import build_url -def test_build_url(): +def test_build_url_with_relative_url(): result = build_url("example.com", "path/to/resource") expected = "example.com/path/to/resource" assert result == expected +def test_build_url_with_relative_url_and_get_params(): result = build_url("example.com", "path/to/resource", {"param1": "value1", "param2": "value2"}) expected = "example.com/path/to/resource?param1=value1¶m2=value2" assert result == expected +def test_build_url_with_relative_url_and_empty_get_params(): result = build_url("example.com", "path", {}) expected = "example.com/path" assert result == expected \ No newline at end of file From 62b9a13d9965e4a2a2a94c3f07688d3d92c77f2f Mon Sep 17 00:00:00 2001 From: Beloded1 Date: Fri, 26 May 2023 16:47:08 +0400 Subject: [PATCH 05/11] Did a level 1_5 tests. --- tests/level_1_5/test_five_replace_word.py | 11 +++++++++ tests/level_1_5/test_four_sentiment.py | 25 +++++++++++++++++++++ tests/level_1_5/test_one_median.py | 13 +++++++++++ tests/level_1_5/test_three_first.py | 23 +++++++++++++++++++ tests/level_1_5/test_two_square_equation.py | 10 +++++++++ 5 files changed, 82 insertions(+) create mode 100644 tests/level_1_5/test_five_replace_word.py create mode 100644 tests/level_1_5/test_four_sentiment.py create mode 100644 tests/level_1_5/test_one_median.py create mode 100644 tests/level_1_5/test_three_first.py create mode 100644 tests/level_1_5/test_two_square_equation.py diff --git a/tests/level_1_5/test_five_replace_word.py b/tests/level_1_5/test_five_replace_word.py new file mode 100644 index 00000000..97380352 --- /dev/null +++ b/tests/level_1_5/test_five_replace_word.py @@ -0,0 +1,11 @@ +from functions.level_1_5.five_replace_word import replace_word + +def test_replace_word_starts_with_low_letter(): + assert replace_word('the big black car', 'big', 'black') == 'the black black car' + +def test_replace_word_starts_with_capital_letter(): + assert replace_word('the big black car', 'Big', 'Black') == 'the Black black car' + +def test_replace_word_if_replace_word_not_find_in_text(): + assert replace_word('the big black car', 'black', 'small') == 'the big small car' + diff --git a/tests/level_1_5/test_four_sentiment.py b/tests/level_1_5/test_four_sentiment.py new file mode 100644 index 00000000..24ab3353 --- /dev/null +++ b/tests/level_1_5/test_four_sentiment.py @@ -0,0 +1,25 @@ +from functions.level_1_5.four_sentiment import check_tweet_sentiment + +def test_check_tweet_sentiment_with_only_good_words(): + text = 'This text with only good words' + good_words = ['good', 'best', 'perfect'] + bad_words = ['bad', 'scary', 'terrible'] + assert check_tweet_sentiment(text, good_words, bad_words) == 'GOOD' + +def test_check_tweet_sentiment_with_only_bad_words(): + text = 'This text with only bad words' + good_words = ['good', 'best', 'perfect'] + bad_words = ['bad', 'scary', 'terrible'] + assert check_tweet_sentiment(text, good_words, bad_words) == 'BAD' + +def test_check_tweet_sentiment_with_equal_good_and_bad_words(): + text = 'This text with good and bad words' + good_words = ['good', 'best', 'perfect'] + bad_words = ['bad', 'scary', 'terrible'] + assert check_tweet_sentiment(text, good_words, bad_words) == None + +def test_check_tweet_sentiment_without_good_and_bad_words(): + text = 'This text without needed words' + good_words = ['good', 'best', 'perfect'] + bad_words = ['bad', 'scary', 'terrible'] + assert check_tweet_sentiment(text, good_words, bad_words) == None \ No newline at end of file diff --git a/tests/level_1_5/test_one_median.py b/tests/level_1_5/test_one_median.py new file mode 100644 index 00000000..f8cfc202 --- /dev/null +++ b/tests/level_1_5/test_one_median.py @@ -0,0 +1,13 @@ +from functions.level_1_5.one_median import get_median_value + +def test_get_median_value_with_empty_items(): + items = [] + assert get_median_value(items) == None + +# def test_get_median_value_with_even_len_of_items(): # Сломал голову. Но если число элементов в списке четное, функция не работает. Баг. +# items = [2, 1, 4, 3] +# assert get_median_value(items) == 1 + +def test_get_median_value_with_odd_len_of_items(): + items = [1, 3, 6, 8, 9, 10] + assert get_median_value(items) == 9 diff --git a/tests/level_1_5/test_three_first.py b/tests/level_1_5/test_three_first.py new file mode 100644 index 00000000..e5ee2b9e --- /dev/null +++ b/tests/level_1_5/test_three_first.py @@ -0,0 +1,23 @@ +from functions.level_1_5.three_first import first +import pytest + +def test_first_with_items(): + items = [5, 7, 1, 15] + assert first(items) == 5 + +def test_first_with_empty_items_and_default_is_NOT_SET(): + items = [] + default = "NOT_SET" + with pytest.raises(AttributeError): + first(items) + +def test_first_with_empty_items_and_default_is_None(): + items = [] + default = None + assert first(items, default) == None + +def test_first_with_empty_items_and_default_is_int(): + items = [] + default = 0 + assert first(items, default) == 0 + diff --git a/tests/level_1_5/test_two_square_equation.py b/tests/level_1_5/test_two_square_equation.py new file mode 100644 index 00000000..1a06b6c1 --- /dev/null +++ b/tests/level_1_5/test_two_square_equation.py @@ -0,0 +1,10 @@ +from functions.level_1_5.two_square_equation import solve_square_equation + +def test_solve_square_equation_if_discriminant_is_negatibe(): + assert solve_square_equation(1.0, 1.0, 1.0) == (None, None) + +def test_solve_square_equation_if_discriminant_is_positive(): + assert solve_square_equation(1.0, -3.0, 2.0) == (1.0, 2.0) + + + From 8c93360ebd45622a94b6c8190f160c54729d10ce Mon Sep 17 00:00:00 2001 From: Beloded1 Date: Fri, 26 May 2023 20:17:38 +0400 Subject: [PATCH 06/11] Add mark.xfails and fixed some bugs --- tests/level_1_5/test_five_replace_word.py | 10 ++++---- tests/level_1_5/test_four_sentiment.py | 8 +++--- tests/level_1_5/test_one_median.py | 28 ++++++++++++++------- tests/level_1_5/test_three_first.py | 12 ++++++--- tests/level_1_5/test_two_square_equation.py | 17 +++++++++++-- 5 files changed, 51 insertions(+), 24 deletions(-) diff --git a/tests/level_1_5/test_five_replace_word.py b/tests/level_1_5/test_five_replace_word.py index 97380352..93d22e02 100644 --- a/tests/level_1_5/test_five_replace_word.py +++ b/tests/level_1_5/test_five_replace_word.py @@ -1,11 +1,11 @@ from functions.level_1_5.five_replace_word import replace_word -def test_replace_word_starts_with_low_letter(): +def test__replace_word__starts_with_low_letter(): assert replace_word('the big black car', 'big', 'black') == 'the black black car' -def test_replace_word_starts_with_capital_letter(): - assert replace_word('the big black car', 'Big', 'Black') == 'the Black black car' +def test__replace_word__starts_with_capital_letter(): + assert replace_word('the big black car', 'Big', 'Red') == 'the Red black car' -def test_replace_word_if_replace_word_not_find_in_text(): - assert replace_word('the big black car', 'black', 'small') == 'the big small car' +def test__replace_word__if_replace_word_not_find_in_text(): + assert replace_word('the big black car', 'red', 'small') == 'the big black car' diff --git a/tests/level_1_5/test_four_sentiment.py b/tests/level_1_5/test_four_sentiment.py index 24ab3353..8c72b653 100644 --- a/tests/level_1_5/test_four_sentiment.py +++ b/tests/level_1_5/test_four_sentiment.py @@ -1,24 +1,24 @@ from functions.level_1_5.four_sentiment import check_tweet_sentiment -def test_check_tweet_sentiment_with_only_good_words(): +def test__check_tweet_sentiment__with_only_good_words(): text = 'This text with only good words' good_words = ['good', 'best', 'perfect'] bad_words = ['bad', 'scary', 'terrible'] assert check_tweet_sentiment(text, good_words, bad_words) == 'GOOD' -def test_check_tweet_sentiment_with_only_bad_words(): +def test__check_tweet_sentiment__with_only_bad_words(): text = 'This text with only bad words' good_words = ['good', 'best', 'perfect'] bad_words = ['bad', 'scary', 'terrible'] assert check_tweet_sentiment(text, good_words, bad_words) == 'BAD' -def test_check_tweet_sentiment_with_equal_good_and_bad_words(): +def test__check_tweet_sentiment__with_equal_good_and_bad_words(): text = 'This text with good and bad words' good_words = ['good', 'best', 'perfect'] bad_words = ['bad', 'scary', 'terrible'] assert check_tweet_sentiment(text, good_words, bad_words) == None -def test_check_tweet_sentiment_without_good_and_bad_words(): +def test__check_tweet_sentiment__without_good_and_bad_words(): text = 'This text without needed words' good_words = ['good', 'best', 'perfect'] bad_words = ['bad', 'scary', 'terrible'] diff --git a/tests/level_1_5/test_one_median.py b/tests/level_1_5/test_one_median.py index f8cfc202..1d79301f 100644 --- a/tests/level_1_5/test_one_median.py +++ b/tests/level_1_5/test_one_median.py @@ -1,13 +1,23 @@ from functions.level_1_5.one_median import get_median_value +import pytest -def test_get_median_value_with_empty_items(): - items = [] - assert get_median_value(items) == None -# def test_get_median_value_with_even_len_of_items(): # Сломал голову. Но если число элементов в списке четное, функция не работает. Баг. -# items = [2, 1, 4, 3] -# assert get_median_value(items) == 1 +def test__get_median_value__with_empty_items(): + assert get_median_value([]) == None -def test_get_median_value_with_odd_len_of_items(): - items = [1, 3, 6, 8, 9, 10] - assert get_median_value(items) == 9 + +@pytest.mark.xfail +def test__get_median_value__with_even_len_of_items(): + assert get_median_value([2, 1, 4, 3]) == 1 + + +@pytest.mark.xfail(reason='Incorrect calculation') +def test__get_median_value__with_more_even_items(): + items = [2, 1, 4, 3, 5, 6] + assert get_median_value([2, 1, 4, 3, 5, 6]) == 3 + + +@pytest.mark.xfail(reason='Incorrect calculation') +def test__get_median_value__with_odd_len_of_items(): + items = [1, 3, 6, 8, 9] + assert get_median_value([1, 3, 6, 8, 9]) == 6 diff --git a/tests/level_1_5/test_three_first.py b/tests/level_1_5/test_three_first.py index e5ee2b9e..f6011dd6 100644 --- a/tests/level_1_5/test_three_first.py +++ b/tests/level_1_5/test_three_first.py @@ -1,22 +1,26 @@ from functions.level_1_5.three_first import first import pytest -def test_first_with_items(): + +def test__first__with_items(): items = [5, 7, 1, 15] assert first(items) == 5 -def test_first_with_empty_items_and_default_is_NOT_SET(): + +def test__first__with_empty_items_and_default_is_NOT_SET(): items = [] default = "NOT_SET" with pytest.raises(AttributeError): first(items) -def test_first_with_empty_items_and_default_is_None(): + +def test__first__with_empty_items_and_default_is_None(): items = [] default = None assert first(items, default) == None -def test_first_with_empty_items_and_default_is_int(): + +def test__first__with_empty_items_and_default_is_int(): items = [] default = 0 assert first(items, default) == 0 diff --git a/tests/level_1_5/test_two_square_equation.py b/tests/level_1_5/test_two_square_equation.py index 1a06b6c1..853782ef 100644 --- a/tests/level_1_5/test_two_square_equation.py +++ b/tests/level_1_5/test_two_square_equation.py @@ -1,10 +1,23 @@ from functions.level_1_5.two_square_equation import solve_square_equation +import pytest -def test_solve_square_equation_if_discriminant_is_negatibe(): + +def test__solve_square_equation__if_discriminant_is_negative(): assert solve_square_equation(1.0, 1.0, 1.0) == (None, None) -def test_solve_square_equation_if_discriminant_is_positive(): + +def test__solve_square_equation__if_discriminant_is_positive(): assert solve_square_equation(1.0, -3.0, 2.0) == (1.0, 2.0) +@pytest.mark.xfail +def test__solve_square_equation__if_discriminant_is_equal_to_zero(): + assert solve_square_equation(1.0, -2.0, 1.0) == (1, None) + + +def test__solve_square_equation__if_square_coefficient_is_equal_to_zero(): + assert solve_square_equation(0, 2.0, 1) == (-0.5, None) + +def test__solve_square_equation__if_square_coefficient_and__linear_coefficients_are_equal_to_zero(): + assert solve_square_equation(0, 0, 1) == (None, None) \ No newline at end of file From ebea2d19b06167f9152d3fe9d766fd621ebfc7b4 Mon Sep 17 00:00:00 2001 From: Beloded1 Date: Fri, 26 May 2023 20:38:10 +0400 Subject: [PATCH 07/11] Fix more tests. --- tests/level_1_5/test_five_replace_word.py | 6 ++---- tests/level_1_5/test_four_sentiment.py | 3 +++ tests/level_1_5/test_one_median.py | 2 -- tests/level_1_5/test_three_first.py | 19 ++++++------------- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/tests/level_1_5/test_five_replace_word.py b/tests/level_1_5/test_five_replace_word.py index 93d22e02..b0d32bcc 100644 --- a/tests/level_1_5/test_five_replace_word.py +++ b/tests/level_1_5/test_five_replace_word.py @@ -1,10 +1,8 @@ from functions.level_1_5.five_replace_word import replace_word -def test__replace_word__starts_with_low_letter(): - assert replace_word('the big black car', 'big', 'black') == 'the black black car' +def test__replace_word__starts_with_case_irrelevant(): + assert replace_word('the big black car', 'big', 'Black') == 'the Black black car' -def test__replace_word__starts_with_capital_letter(): - assert replace_word('the big black car', 'Big', 'Red') == 'the Red black car' def test__replace_word__if_replace_word_not_find_in_text(): assert replace_word('the big black car', 'red', 'small') == 'the big black car' diff --git a/tests/level_1_5/test_four_sentiment.py b/tests/level_1_5/test_four_sentiment.py index 8c72b653..10618f19 100644 --- a/tests/level_1_5/test_four_sentiment.py +++ b/tests/level_1_5/test_four_sentiment.py @@ -6,18 +6,21 @@ def test__check_tweet_sentiment__with_only_good_words(): bad_words = ['bad', 'scary', 'terrible'] assert check_tweet_sentiment(text, good_words, bad_words) == 'GOOD' + def test__check_tweet_sentiment__with_only_bad_words(): text = 'This text with only bad words' good_words = ['good', 'best', 'perfect'] bad_words = ['bad', 'scary', 'terrible'] assert check_tweet_sentiment(text, good_words, bad_words) == 'BAD' + def test__check_tweet_sentiment__with_equal_good_and_bad_words(): text = 'This text with good and bad words' good_words = ['good', 'best', 'perfect'] bad_words = ['bad', 'scary', 'terrible'] assert check_tweet_sentiment(text, good_words, bad_words) == None + def test__check_tweet_sentiment__without_good_and_bad_words(): text = 'This text without needed words' good_words = ['good', 'best', 'perfect'] diff --git a/tests/level_1_5/test_one_median.py b/tests/level_1_5/test_one_median.py index 1d79301f..184549f2 100644 --- a/tests/level_1_5/test_one_median.py +++ b/tests/level_1_5/test_one_median.py @@ -13,11 +13,9 @@ def test__get_median_value__with_even_len_of_items(): @pytest.mark.xfail(reason='Incorrect calculation') def test__get_median_value__with_more_even_items(): - items = [2, 1, 4, 3, 5, 6] assert get_median_value([2, 1, 4, 3, 5, 6]) == 3 @pytest.mark.xfail(reason='Incorrect calculation') def test__get_median_value__with_odd_len_of_items(): - items = [1, 3, 6, 8, 9] assert get_median_value([1, 3, 6, 8, 9]) == 6 diff --git a/tests/level_1_5/test_three_first.py b/tests/level_1_5/test_three_first.py index f6011dd6..4b238b3f 100644 --- a/tests/level_1_5/test_three_first.py +++ b/tests/level_1_5/test_three_first.py @@ -3,25 +3,18 @@ def test__first__with_items(): - items = [5, 7, 1, 15] - assert first(items) == 5 + assert first([5, 7, 1, 15]) == 5 -def test__first__with_empty_items_and_default_is_NOT_SET(): - items = [] - default = "NOT_SET" +def test__first__with_empty_items_and_default_is_not_set(): with pytest.raises(AttributeError): - first(items) + first([]) -def test__first__with_empty_items_and_default_is_None(): - items = [] - default = None - assert first(items, default) == None +def test__first__with_empty_items_and_default_is_none(): + assert first([], None) == None def test__first__with_empty_items_and_default_is_int(): - items = [] - default = 0 - assert first(items, default) == 0 + assert first([], 0) == 0 From c2c34087cd720fc6c55881d00e53a04bc7bb3321 Mon Sep 17 00:00:00 2001 From: Beloded1 Date: Mon, 5 Jun 2023 11:56:40 +0400 Subject: [PATCH 08/11] Rename some functions, add parametrize and cov-branch --- .coverage | Bin 0 -> 53248 bytes coverage.xml | 161 ++++++++++++++++++++ requirements.txt | 3 + setup.cfg | 9 ++ tests/level_1/test_five_title.py | 23 ++- tests/level_1/test_four_bank_parser.py | 5 +- tests/level_1/test_one_gender.py | 14 +- tests/level_1/test_three_url_builder.py | 32 ++-- tests/level_1/test_two_date_parser.py | 21 +-- tests/level_1_5/test_five_replace_word.py | 18 ++- tests/level_1_5/test_four_sentiment.py | 25 ++- tests/level_1_5/test_one_median.py | 8 +- tests/level_1_5/test_three_first.py | 18 ++- tests/level_1_5/test_two_square_equation.py | 24 ++- 14 files changed, 311 insertions(+), 50 deletions(-) create mode 100644 .coverage create mode 100644 coverage.xml create mode 100644 setup.cfg diff --git a/.coverage b/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..ba21007b0d6e85fda9790bdb02ce426e65fb1dfc GIT binary patch literal 53248 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 + + + + + C:\Users\Beloded\projects\testing_exercises\functions\level_1 + C:\Users\Beloded\projects\testing_exercises\functions\level_1_5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/requirements.txt b/requirements.txt index 805eb2a9..1b6e276a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,4 @@ pytest==7.2.1 +pytest-cov==4.1.0 +pytest-testdox +mypy==1.3.0 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 00000000..fb486c14 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,9 @@ +[tool:pytest] +addopts = + --cov=functions/level_1 + --cov=functions/level_1_5 + --cov-report=xml:coverage.xml + --cov-report=html + --cov-branch + --cov-fail-under=70 + --testdox diff --git a/tests/level_1/test_five_title.py b/tests/level_1/test_five_title.py index a4033a2a..cf263f6c 100644 --- a/tests/level_1/test_five_title.py +++ b/tests/level_1/test_five_title.py @@ -1,15 +1,26 @@ from functions.level_1.five_title import change_copy_item +import pytest - -def test_change_copy_item_add_copy(): +def test__change_copy_item__add_copy(): assert change_copy_item('My Item') == 'Copy of My Item' -def test_change_copy_item_increase_number_of_copy(): +def test__change_copy_item__increase_number_of_copy(): assert change_copy_item('Copy of My Item (2)') == 'Copy of My Item (3)' -def test_change_copy_item_behavior_for_long_title(): +def test__change_copy_item__behavior_for_long_title(): assert change_copy_item('Very long title with many words', max_main_item_title_length=10) == 'Very long title with many words' -def test_change_copy_item_for_basic_case_with_text(): +def test__change_copy_item__for_basic_case_with_text(): assert change_copy_item("Copy of My Item") == "Copy of My Item (2)" - \ No newline at end of file + +@pytest.mark.parametrize( + 'title, max_main_item_title_length, expected_result', + [ + ('My Item', 100, 'Copy of My Item'), + ('Copy of My Item (2)', 100, 'Copy of My Item (3)'), + ('Very long title with many words', 10, 'Very long title with many words'), + ('Copy of My Item', 100, 'Copy of My Item (2)'), + ] +) +def test__change_copy_item(title, max_main_item_title_length, expected_result): + assert change_copy_item(title, max_main_item_title_length) == expected_result diff --git a/tests/level_1/test_four_bank_parser.py b/tests/level_1/test_four_bank_parser.py index 53b8ea4a..655bf06e 100644 --- a/tests/level_1/test_four_bank_parser.py +++ b/tests/level_1/test_four_bank_parser.py @@ -1,9 +1,8 @@ -from functions.level_1.four_bank_parser import BankCard, SmsMessage, Expense, parse_ineco_expense +from functions.level_1.four_bank_parser import BankCard, SmsMessage, parse_ineco_expense import datetime -import pytest import decimal -def test_parse_ineco_expense_succes(): +def test__parse_ineco_expense__succes(): sms = SmsMessage( text="100.00 CARD1234, authcode1234 01.01.23 11:30 Alfa", author="Alfa Bank", diff --git a/tests/level_1/test_one_gender.py b/tests/level_1/test_one_gender.py index 75bc4339..5039b0df 100644 --- a/tests/level_1/test_one_gender.py +++ b/tests/level_1/test_one_gender.py @@ -1,9 +1,19 @@ from functions.level_1.one_gender import genderalize +import pytest -def test_genderalize_is_male(): +def test__genderalize__is_male(): assert genderalize('говорил', 'говорила', 'male') == 'говорил' -def test_genderalize_is_not_male(): +def test__genderalize__is_not_male(): assert genderalize('говорил', 'говорила', 'any str, except "male"') == 'говорила' +@pytest.mark.parametrize( + 'verb_male, verb_female, gender, expected_result', + [ + ('говорил', 'говорила', 'male', 'говорил'), + ('говорил', 'говорила', 'any str, except "male', 'говорила'), + ] +) +def test__genderalize(verb_male, verb_female, gender, expected_result): + assert genderalize(verb_male, verb_female, gender) == expected_result \ No newline at end of file diff --git a/tests/level_1/test_three_url_builder.py b/tests/level_1/test_three_url_builder.py index 038e53f0..31c4fb4f 100644 --- a/tests/level_1/test_three_url_builder.py +++ b/tests/level_1/test_three_url_builder.py @@ -1,17 +1,31 @@ from functions.level_1.three_url_builder import build_url +import pytest -def test_build_url_with_relative_url(): +def test__build_url__with_relative_url(): result = build_url("example.com", "path/to/resource") - expected = "example.com/path/to/resource" - assert result == expected + expected_result = "example.com/path/to/resource" + assert result == expected_result -def test_build_url_with_relative_url_and_get_params(): + +def test__build_url__with_relative_url_and_get_params(): result = build_url("example.com", "path/to/resource", {"param1": "value1", "param2": "value2"}) - expected = "example.com/path/to/resource?param1=value1¶m2=value2" - assert result == expected + expected_result = "example.com/path/to/resource?param1=value1¶m2=value2" + assert result == expected_result + -def test_build_url_with_relative_url_and_empty_get_params(): +def test__build_url__with_relative_url_and_empty_get_params(): result = build_url("example.com", "path", {}) - expected = "example.com/path" - assert result == expected \ No newline at end of file + expected_result = "example.com/path" + assert result == expected_result + +@pytest.mark.parametrize( + 'host_name, relative_url, get_params, expected_result', + [ + ('example.com', 'path/to/resource', None, 'example.com/path/to/resource'), + ('example.com', 'path/to/resource', {"param1": "value1", "param2": "value2"}, 'example.com/path/to/resource?param1=value1¶m2=value2'), + ('example.com', 'path', {}, 'example.com/path'), + ] +) +def test__build_url(host_name, relative_url, get_params, expected_result): + assert build_url(host_name, relative_url, get_params) == expected_result diff --git a/tests/level_1/test_two_date_parser.py b/tests/level_1/test_two_date_parser.py index af1821ca..209995d1 100644 --- a/tests/level_1/test_two_date_parser.py +++ b/tests/level_1/test_two_date_parser.py @@ -3,17 +3,20 @@ import datetime, pytest -def test_compose_datetime_from_today(): - result = compose_datetime_from("today", "10:30") - expected = datetime.datetime.now().replace(hour=10, minute=30, second=0, microsecond=0) - assert result == expected -def test_compose_datetime_from_tomorrow(): - result = compose_datetime_from("tomorrow", "14:45") - expected = (datetime.datetime.now() + datetime.timedelta(days=1)).replace(hour=14, minute=45, second=0, microsecond=0) - assert result == expected +@pytest.mark.parametrize( + 'date_str, time_str, expected_result', + [ + ("today", "10:30", datetime.datetime.now().replace(hour=10, minute=30, second=0, microsecond=0)), + ("tomorrow", "14:45", (datetime.datetime.now() + datetime.timedelta(days=1)).replace(hour=14, minute=45, second=0, microsecond=0)), + ] +) +def test__compose_datetime__from(date_str, time_str, expected_result): + result = compose_datetime_from(date_str, time_str) + assert result == expected_result -def test_compose_datetime_wrong_time_format(): + +def test__compose_datetime__wrong_time_format(): with pytest.raises(ValueError): compose_datetime_from("today", "10-30") diff --git a/tests/level_1_5/test_five_replace_word.py b/tests/level_1_5/test_five_replace_word.py index b0d32bcc..baeff30d 100644 --- a/tests/level_1_5/test_five_replace_word.py +++ b/tests/level_1_5/test_five_replace_word.py @@ -1,9 +1,23 @@ from functions.level_1_5.five_replace_word import replace_word +import pytest def test__replace_word__starts_with_case_irrelevant(): - assert replace_word('the big black car', 'big', 'Black') == 'the Black black car' + assert replace_word('the big black car', 'big', 'Cool') == 'the Cool black car' -def test__replace_word__if_replace_word_not_find_in_text(): +def test__replace_word__unchanged_when_replace_word_not_found_in_text(): assert replace_word('the big black car', 'red', 'small') == 'the big black car' + +@pytest.mark.parametrize( + 'text, replace_from, replace_to, expected_result', + [ + ('the big black car', 'big', 'Cool', 'the Cool black car'), + ('the big black car', 'red', 'small', 'the big black car'), + ('the BIG black car', 'big', 'cool', 'the cool black car'), + ('the big black car', 'big', 'COOL', 'the COOL black car'), + ('the big black car', 'BIG', 'cool', 'the cool black car'), + ] +) +def test__replace_word(text, replace_from, replace_to, expected_result): + assert replace_word(text, replace_from, replace_to) == expected_result \ No newline at end of file diff --git a/tests/level_1_5/test_four_sentiment.py b/tests/level_1_5/test_four_sentiment.py index 10618f19..93dcc3a5 100644 --- a/tests/level_1_5/test_four_sentiment.py +++ b/tests/level_1_5/test_four_sentiment.py @@ -1,28 +1,43 @@ from functions.level_1_5.four_sentiment import check_tweet_sentiment +import pytest -def test__check_tweet_sentiment__with_only_good_words(): + +def test__check_tweet_sentiment__return_good_when_only_good_words_found(): text = 'This text with only good words' good_words = ['good', 'best', 'perfect'] bad_words = ['bad', 'scary', 'terrible'] assert check_tweet_sentiment(text, good_words, bad_words) == 'GOOD' -def test__check_tweet_sentiment__with_only_bad_words(): +def test__check_tweet_sentiment__return_bad_when_only_bad_words_found(): text = 'This text with only bad words' good_words = ['good', 'best', 'perfect'] bad_words = ['bad', 'scary', 'terrible'] assert check_tweet_sentiment(text, good_words, bad_words) == 'BAD' -def test__check_tweet_sentiment__with_equal_good_and_bad_words(): +def test__check_tweet_sentiment__return_none_when_equal_good_and_bad_words_found(): text = 'This text with good and bad words' good_words = ['good', 'best', 'perfect'] bad_words = ['bad', 'scary', 'terrible'] assert check_tweet_sentiment(text, good_words, bad_words) == None -def test__check_tweet_sentiment__without_good_and_bad_words(): +def test__check_tweet_sentiment__return_none_when_no_good_and_bad_words_found(): text = 'This text without needed words' good_words = ['good', 'best', 'perfect'] bad_words = ['bad', 'scary', 'terrible'] - assert check_tweet_sentiment(text, good_words, bad_words) == None \ No newline at end of file + assert check_tweet_sentiment(text, good_words, bad_words) == None + + +@pytest.mark.parametrize( + 'text, good_words, bad_words, expected_result', + [ + ('This text with only good words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], 'GOOD'), + ('This text with only bad words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], 'BAD'), + ('This text with good and bad words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], None), + ('This text without needed words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], None), + ] +) +def test__check_tweet_sentiment(text, good_words, bad_words, expected_result): + assert check_tweet_sentiment(text, good_words, bad_words) == expected_result \ No newline at end of file diff --git a/tests/level_1_5/test_one_median.py b/tests/level_1_5/test_one_median.py index 184549f2..c0653068 100644 --- a/tests/level_1_5/test_one_median.py +++ b/tests/level_1_5/test_one_median.py @@ -2,20 +2,20 @@ import pytest -def test__get_median_value__with_empty_items(): +def test__get_median_value__return_none_if_empty_items_found(): assert get_median_value([]) == None @pytest.mark.xfail -def test__get_median_value__with_even_len_of_items(): +def test__get_median_value__return_midle_index_if_even_len_of_items_found(): assert get_median_value([2, 1, 4, 3]) == 1 @pytest.mark.xfail(reason='Incorrect calculation') -def test__get_median_value__with_more_even_items(): +def test__get_median_value__return_middle_index_if_more_even_items_found(): assert get_median_value([2, 1, 4, 3, 5, 6]) == 3 @pytest.mark.xfail(reason='Incorrect calculation') -def test__get_median_value__with_odd_len_of_items(): +def test__get_median_value__return_middle_index_if_odd_len_of_items_found(): assert get_median_value([1, 3, 6, 8, 9]) == 6 diff --git a/tests/level_1_5/test_three_first.py b/tests/level_1_5/test_three_first.py index 4b238b3f..70ca1197 100644 --- a/tests/level_1_5/test_three_first.py +++ b/tests/level_1_5/test_three_first.py @@ -2,19 +2,29 @@ import pytest -def test__first__with_items(): +def test__first__return_first_item_if_items_is_not_empty(): assert first([5, 7, 1, 15]) == 5 -def test__first__with_empty_items_and_default_is_not_set(): +def test__first__raise_error_if_empty_items_and_default_are_not_set(): with pytest.raises(AttributeError): first([]) -def test__first__with_empty_items_and_default_is_none(): +def test__first__return_none_if_empty_items_found_and_default_is_none(): assert first([], None) == None -def test__first__with_empty_items_and_default_is_int(): +def test__first__return_default_if_empty_items_found_and_default_is_int(): assert first([], 0) == 0 +@pytest.mark.parametrize( + 'items, default, expected_result', + [ + ([5, 7, 1, 15], None, 5), + ([], None, None), + ([], 0, 0), + ] +) +def test__first(items, default, expected_result): + assert first(items, default) == expected_result \ No newline at end of file diff --git a/tests/level_1_5/test_two_square_equation.py b/tests/level_1_5/test_two_square_equation.py index 853782ef..9fec03f8 100644 --- a/tests/level_1_5/test_two_square_equation.py +++ b/tests/level_1_5/test_two_square_equation.py @@ -2,22 +2,34 @@ import pytest -def test__solve_square_equation__if_discriminant_is_negative(): +def test__solve_square_equation__return_none_if_discriminant_is_negative(): assert solve_square_equation(1.0, 1.0, 1.0) == (None, None) -def test__solve_square_equation__if_discriminant_is_positive(): +def test__solve_square_equation__return_two_roots_if_discriminant_is_positive(): assert solve_square_equation(1.0, -3.0, 2.0) == (1.0, 2.0) @pytest.mark.xfail -def test__solve_square_equation__if_discriminant_is_equal_to_zero(): +def test__solve_square_equation__return_one_root_if_discriminant_is_equal_to_zero(): assert solve_square_equation(1.0, -2.0, 1.0) == (1, None) -def test__solve_square_equation__if_square_coefficient_is_equal_to_zero(): +def test__solve_square_equation__return_one_root_if_square_coefficient_is_equal_to_zero(): assert solve_square_equation(0, 2.0, 1) == (-0.5, None) -def test__solve_square_equation__if_square_coefficient_and__linear_coefficients_are_equal_to_zero(): - assert solve_square_equation(0, 0, 1) == (None, None) \ No newline at end of file +def test__solve_square_equation__return_none_if_square_coefficient_and__linear_coefficients_are_equal_to_zero(): + assert solve_square_equation(0, 0, 1) == (None, None) + +@pytest.mark.parametrize( + 'square_coefficient, linear_coefficient, const_coefficient, expected_result', + [ + (1.0, 1.0, 1.0, (None, None)), + (1.0, -3.0, 2.0, (1.0, 2.0)), + (1.0, -2.0, 1.0, (1, 1)), + (0, 0, 1, (None, None)), + ] +) +def test__solve_square_equation(square_coefficient, linear_coefficient, const_coefficient, expected_result): + assert solve_square_equation(square_coefficient, linear_coefficient, const_coefficient) == expected_result \ No newline at end of file From 822f39b359b73ffba815c81463e98e37dc18b133 Mon Sep 17 00:00:00 2001 From: Beloded1 Date: Tue, 6 Jun 2023 17:24:12 +0400 Subject: [PATCH 09/11] Did tests at level_1_7 --- .coverage | Bin 53248 -> 61440 bytes coverage.xml | 109 +++++++++++++- functions/level_1_7/four_fraud.py | 2 +- setup.cfg | 1 + tests/level_1_7/test_four_fraud.py | 140 ++++++++++++++++++ .../level_1_7/test_one_avg_daily_expenses.py | 50 +++++++ tests/level_1_7/test_three_is_subscription.py | 59 ++++++++ .../level_1_7/test_two_expense_categorizer.py | 26 ++++ 8 files changed, 384 insertions(+), 3 deletions(-) create mode 100644 tests/level_1_7/test_four_fraud.py create mode 100644 tests/level_1_7/test_one_avg_daily_expenses.py create mode 100644 tests/level_1_7/test_three_is_subscription.py create mode 100644 tests/level_1_7/test_two_expense_categorizer.py diff --git a/.coverage b/.coverage index ba21007b0d6e85fda9790bdb02ce426e65fb1dfc..59e2675f77ced21f567016635137e153326629ee 100644 GIT binary patch literal 61440 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 diff --git a/coverage.xml b/coverage.xml index cd180497..4530ddd9 100644 --- a/coverage.xml +++ b/coverage.xml @@ -1,13 +1,14 @@ - + C:\Users\Beloded\projects\testing_exercises\functions\level_1 C:\Users\Beloded\projects\testing_exercises\functions\level_1_5 + C:\Users\Beloded\projects\testing_exercises\functions\level_1_7 - + @@ -68,6 +69,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -82,6 +104,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -114,6 +188,20 @@ + + + + + + + + + + + + + + @@ -138,6 +226,23 @@ + + + + + + + + + + + + + + + + + diff --git a/functions/level_1_7/four_fraud.py b/functions/level_1_7/four_fraud.py index d70ee572..0ce92676 100644 --- a/functions/level_1_7/four_fraud.py +++ b/functions/level_1_7/four_fraud.py @@ -22,6 +22,6 @@ def find_fraud_expenses(history: list[Expense]) -> list[Expense]: for spent_in, spent_at, amount in fraud_signs: fraud_transactions += [ e for e in history - if e.spent_in == spent_at and e.spent_at == spent_at and e.amount == amount + if e.spent_in == spent_in and e.spent_at == spent_at and e.amount == amount # Выявил ошибку. Исправил. Было:if e.spent_in == spent_at ] return fraud_transactions diff --git a/setup.cfg b/setup.cfg index fb486c14..4cb359b1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,6 +2,7 @@ addopts = --cov=functions/level_1 --cov=functions/level_1_5 + --cov=functions/level_1_7 --cov-report=xml:coverage.xml --cov-report=html --cov-branch diff --git a/tests/level_1_7/test_four_fraud.py b/tests/level_1_7/test_four_fraud.py new file mode 100644 index 00000000..2fe928f1 --- /dev/null +++ b/tests/level_1_7/test_four_fraud.py @@ -0,0 +1,140 @@ +from functions.level_1_7.four_fraud import find_fraud_expenses +from functions.level_1_7.models import Expense, BankCard, ExpenseCategory, Currency +from decimal import Decimal +from datetime import datetime +import pytest + +def test__find_fraud_expenses__if_get_more_than_max_amount(): + history = [ + Expense( + amount=Decimal('5000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + Expense( + amount=Decimal('5001.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + Expense( + amount=Decimal('6001.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + + ] + + expected_fraud_transactions = [] + + fraud_transactions = find_fraud_expenses(history) + assert fraud_transactions == expected_fraud_transactions + + +def test__find_fraud_expenses__if_get_less_than_min_chain_length(): + history = [ + Expense( + amount=Decimal('1000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + Expense( + amount=Decimal('2000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + ] + + fraud_transactions = find_fraud_expenses(history) + assert fraud_transactions == [] + +@pytest.mark.xfail(reason='Incorrect work of function') # Думаю функция реализована неправильно. Но может я не разобрался просто. +def test__find_fraud_expenses__if_get_multiple_fraud_chains(): + history = [ + Expense( + amount=Decimal('1000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + Expense( + amount=Decimal('2000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + Expense( + amount=Decimal('3000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + Expense( + amount=Decimal('4000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + ] + + expected_fraud_transactions = [ + Expense( + amount=Decimal('1000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + Expense( + amount=Decimal('2000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + Expense( + amount=Decimal('3000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + Expense( + amount=Decimal('4000.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='The best drinking bar', + spent_at=datetime(2023, 6, 4, 23, 0, 0), + category=ExpenseCategory.BAR_RESTAURANT, + ), + ] + + fraud_transactions = find_fraud_expenses(history) + assert fraud_transactions == expected_fraud_transactions + + diff --git a/tests/level_1_7/test_one_avg_daily_expenses.py b/tests/level_1_7/test_one_avg_daily_expenses.py new file mode 100644 index 00000000..a8ecde6b --- /dev/null +++ b/tests/level_1_7/test_one_avg_daily_expenses.py @@ -0,0 +1,50 @@ +import decimal +from datetime import datetime +import pytest +from functions.level_1_7.models import Expense, BankCard, Currency +from functions.level_1_7.one_avg_daily_expenses import calculate_average_daily_expenses + +@pytest.mark.parametrize( + 'expenses, expected_result', + [ + ( + [ + Expense( + amount=decimal.Decimal('100.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='Funny Shop', + spent_at=datetime(2023, 6, 1, 12, 0, 0, 0), + category=None + ), + Expense( + amount=decimal.Decimal('200.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='Funny Shop', + spent_at=datetime(2023, 6, 1, 13, 0, 0, 0), + category=None + ), + Expense( + amount=decimal.Decimal('300.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='Funny Shop', + spent_at=datetime(2023, 6, 2, 14, 0, 0, 0), + category=None + ), + Expense( + amount=decimal.Decimal('400.00'), + currency=Currency.RUB, + card=BankCard(last_digits='1234', owner='Alexandr'), + spent_in='Funny Shop', + spent_at=datetime(2023, 6, 2, 15, 0, 0, 0), + category=None + ), + ], + decimal.Decimal('500.00') + ), + ] +) +def test__calculate_average_daily_expenses(expenses, expected_result): + assert calculate_average_daily_expenses(expenses) == expected_result diff --git a/tests/level_1_7/test_three_is_subscription.py b/tests/level_1_7/test_three_is_subscription.py new file mode 100644 index 00000000..90a0a584 --- /dev/null +++ b/tests/level_1_7/test_three_is_subscription.py @@ -0,0 +1,59 @@ +from functions.level_1_7.three_is_subscription import is_subscription +from functions.level_1_7.models import Expense +import pytest +from datetime import datetime + + +@pytest.mark.parametrize( + "expense, history, expected_result", + [ + ( + Expense(amount=100, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 6, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), + [ + Expense(amount=100, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 1, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), + Expense(amount=200, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 2, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), + Expense(amount=300, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 3, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), + Expense(amount=400, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 4, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), + Expense(amount=500, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 5, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), + ], + True + ), + ( + Expense(amount=500, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 6, 5, 0, 0), category='ONLINE_SUBSCRIPTIONS'), + [ + Expense(amount=500, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 1, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), + Expense(amount=500, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 2, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), + Expense(amount=500, currency='RUB', card='1234', spent_in='Cofeshop', spent_at=datetime(2023, 3, 1, 0, 0), category='BAR_RESTAURANT'), + ], + False + ), + ] +) +def test__is_subscription(expense, history, expected_result): + assert is_subscription(expense, history) == expected_result + + + + + + + + + + + + + + + + + + + + + + + + + +# def test__is_subscription(expense, history) \ No newline at end of file diff --git a/tests/level_1_7/test_two_expense_categorizer.py b/tests/level_1_7/test_two_expense_categorizer.py new file mode 100644 index 00000000..8cfc9779 --- /dev/null +++ b/tests/level_1_7/test_two_expense_categorizer.py @@ -0,0 +1,26 @@ +from functions.level_1_7.two_expense_categorizer import guess_expense_category +from functions.level_1_7.models import Expense, ExpenseCategory +import pytest +from datetime import datetime + +@pytest.mark.parametrize( + 'expense, ExpenseCategory', + [ + (Expense(amount=10000, currency='RUB', card='1234', spent_in='Bastard place', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + ExpenseCategory.BAR_RESTAURANT), + (Expense(amount=1000, currency='RUB', card='1234', spent_in='clean house', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + ExpenseCategory.SUPERMARKET), + (Expense(amount=10, currency='USD', card='1234', spent_in='Netflix', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + ExpenseCategory.ONLINE_SUBSCRIPTIONS), + (Expense(amount=3000, currency='RUB', card='1234', spent_in='Wonder pharm', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + ExpenseCategory.MEDICINE_PHARMACY), + (Expense(amount=2000, currency='RUB', card='1234', spent_in='kino park', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + ExpenseCategory.THEATRES_MOVIES_CULTURE), + (Expense(amount=2000, currency='RUB', card='1234', spent_in='www.taxi.yandex.ru', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + ExpenseCategory.TRANSPORT), + (Expense(amount=5000, currency='RUB', card='1234', spent_in='Y Ashota', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + None), + ] +) +def test__guess_expense_category(expense:Expense, ExpenseCategory:ExpenseCategory | None)->ExpenseCategory | None: + assert guess_expense_category(expense) == ExpenseCategory \ No newline at end of file From 3e0daba038c474a6756f8d493bdae79ffce2845d Mon Sep 17 00:00:00 2001 From: Beloded1 Date: Thu, 8 Jun 2023 15:34:44 +0400 Subject: [PATCH 10/11] Add some fixttures --- .coverage | Bin 61440 -> 61440 bytes conftest.py | 22 ++++++++ coverage.xml | 2 +- .../level_1_7/test_one_avg_daily_expenses.py | 2 +- tests/level_1_7/test_three_is_subscription.py | 52 ++++++++++-------- 5 files changed, 54 insertions(+), 24 deletions(-) create mode 100644 conftest.py diff --git a/.coverage b/.coverage index 59e2675f77ced21f567016635137e153326629ee..82735a4ad5be9513b94eb242aa249251e7f191f0 100644 GIT binary patch literal 61440 zcmeI53wT_`b;s}f&fMp&ELm@99pv{LurY=JCU!!=U_*>?KtWzfD_fwKwUV(3A?!kd zQbGu&fl@=Mn}FLwN`WSX5<(J6ff7Ozno#QIVQgZkgB^;&HgdLS?zv~Z5|%zvk*_VC z1+RXZojZ5tKXd=PGjq@CQ|B)49LS_Pdi%T61F7Sbgrcg-X{nT=C>;KU@Q)rgfI+{& zPqlC?wOlu1DlZO^Xkop6btZWco8bZJ8|AVp?bWbZ7e2 zpLgua2@}-oGEtk-{cZ5SJFGR3aHJ`p?0|yWdi&c&?OXfPJ#FhV*;%P{v4w5DP|r;R z*xLTy?zscKsjkkRsF^+4&VkO}o>XR2rfqN_(|*(j&Jv>01H>zB4V1N3G-xdz8K0{} zog)Vy<;XaDd~gR;uBVq|J#wHpH5?q(xo5Du6(ql8u)9xm4jh3e9_StI$kC1+=#3lu zzWe4VeR-t4!@83s7d?tc4fb?y7|awqe^%gr1Mc0`wqI68%$1Eab0nwd*tr2EB%mgAX(AK*#)1O|KnG?T?w(vhakYMP{=T_yi#?gjOaR{`` zFQSvHw(QE?b1`%OvTDBQ8nTNc;*kXSQus zE~y=@IdQ(0`7yAZZP=9+6>1Kz2;ocOpE;}%BIU>>Fyf8i{a3#)J+MCY-nxrqsQ6UV zsywM;w2F%=w9FUJ*3}njQI)T&j@0i4(-;5rVO16>N2+{QX7lWg=`L`SzI10lT(aQ7 z_zsW~8Qas4Io;YjI1r6r@oO|Z#e2_@`eFe`ekbiA*YqemT;3~tv)N8~TNQ6x*~OHa znz}xn6)u#WnriLs?aHKk@VxsuR7r2%BF8 z7ad(+0Nvf`p7!|tO1uqYso?$M;uPmW6M+L$Q{ke_!X-MQOe!>fRX7%vKc^2g5v6vg z+wpQ2ol;WbW$QEVDGuL_mZk?X1D)NOl*kfQCK_0mrL(EF{tUbb@1@hH>SGN9(OWI^ z#j}_tGx1R_*QnZ+GiR!~!T4fCpJ~a$n|gPesvZBT4I3mQUOX~hR)FEcr=8MqBD5=! zL;Q+o5axzG*orDpuK2T#Gu?+;s^Pl|{4XC;0jYpgKq?>=kP1izqyka_sen{KDj*e* z3Viq!&{a*f#r$6jf2o9f;YmKE0#X5~fK)&#AQg}bNCl(HCJKUDSF%J?RL6XqN{=L82@rG>kdaCf->|7HVat)&7|0jYpgKq?>=kP1izqyka_ zsen{KDj*dg1w6f8rBwjU(QA3U2q5=kP1izqyka_sX(m2#YscSE&15u=JT@Z6Mn`kjaW~<7k1e9O!TB%x1F9#rXT?uFS?vSIhjC6PgDu>xCSBnVxK>1-`x` zv#z(l^YTnTMD;c&p!|=HyZrV28Th7;Y)f{qHQUzT*(bgL080N%2&JDo-qPWV5L(h3 z*R`~#JG(YhJF-yxxd9YEb-cxQ^bYp7bo8eO+o8w{eJJw8@fEos(mT6h5WdKvB?CWV zHO}*(?CIk!JJPxX0@??J1n&4HSkNpK?#{G#rbVZn??91r$6L)v)oi9mgnsvkny%qc z?1FI@+qp5*(x2(;f-kUXxeUI{1xjAUpyb)(Dmm&g2$IjV^ridZN`q2Y+feHKah4kO z)nI>DOY2}~S9?_M3Jc0TW_;y}{#uuTZ#@weJ>P@^$JbxYQE#=TdoDfF{uRdf>)9cC zYoK!gzAB(^^VvES*f_q1x3qNjbPlw%h~l(y7YEMR4R+ckykvzs?&d;qCG`{g|4HW) zN>~L;FM_Z#5@ZhM$^P3K<7A|Fx#sen{KDj*e*3P=T{0#X4| zpvA~7QOEV6dCd8L@-s&6qvJ1sl=*++Vk39zxJw^({vV!aV6`M(&t#mOE_zZ;ijdjyC@{KY)4;oBtc<81Suq=kP1izqyisG1$0$ce6jzp zhC>ScFCS6?sen{KDj*e*3P=T{0#X5~fK)&#AQg}bd=kP1izqyj|+#QwjW{}<(uAQg}bNCl(Y?v)X!GJ1L3~#SK+^hKMtP>p9sGm-WP5SZx3$@uL&;?`@)W}IXo{s zBRnNMKAaJz!ik|5YQcfvjbLZ+a_~a%RPb2vV6ZK?E4VedA-F2o7<2`#!J6QlU}>;8 zm>*0F8iR>}7ij(g{|$eq|FZvr|CIlj|DeCkzstYXzroM>m-*d(yMLj-(*L-BvVW{U z&2R9_eaBb4x4k{y4(}!JdGAU1X2J)&d%P{)E#CFsmEM4NiMQ5U?Jf6C_ZE3`ye6;K zOM1-xt-Igdg&KI3)oXt*;)8?#k&UQ|BPH<*9lbnf;>nMCbf1UrF zzsR5AkMoE4Hhw3+ggY&l!P7P6Tv#VVL%7wos}*X*C!KenH?zhysY-)nENzhqx)f7b4^ zGxmk{3VWG-l0DC!Y}eSKZCD4bH>_8zm#ptw-?hGB-DmxU^=0ditgEa+>r!j2b-s0$ zb(*!nnqf6sP@8HFg^RYCLaz&v?YR-`Hy0X547xjE%;n##-Zi<4ogJ<9K7b(O^t4n0{D) zQ~#B|UH_r}l>QI;1Nv9>JM=H=*XWz|9=%Op1B30u`e6Bmrpi?{SzX8S3u3Hd`Qs6j zLo9zBVgm43#4y3~^AQ7|<>w*#NtU0BSPzBGLEH&A8?ga!7Ghlk%g;ott!DWdG45jd z=`q%_{4~T}fKw5x0jD6=z+sbPe3j*!Vyt2LV-Q~j{0L$-;3UMVJuII>tb`I85i2TL zz5#Jh1qO zmm*HAWw}cbD<-mBCt@OCx%G%iz;$tIlI1!Og9?_*#F${Yc0^D-*M`V_mTN_Hq2g&o z7$3Q{aRz8v3!>2WVnhqH{S4v|G@=>Nv{>#UM5AEmE(GLi0NQ?9B=P`SwkCSn56f8Y z0>m~rVG8KAbS5GO+Frw~Qc&qFMSmYs_TBR{t?#&VWhf#^ab&q4H{gtOyR z=*i`X92$8R;t;g#Ohf}J`AI}(u-qAODzx_#h&H5tJWjP)ZW*ElsY?+}z>mclK%3KJ zwCvmxK(6{A$Y~;x`*5yPqnAAnRXhdJhRS>tkwNOoaVpf{Bt#QVyBN`e3@0LrepnP| zfPOduQS^gwU9Ng?+Q@Xd2d72Pb;}O39D1&s07TDq!E!I?JKwI-(!Ya~%dHpyxW^KsoeW2OKDe zp6j@f0X^3dXG70*#M#hu9U&fiu45fyIrLn|0zuGookM`=xsDjF=(&#hF3X|kIwt6d zp6k2|h@R^hfatl70h*)dItFw#dag4Bh@R_+7Nh4nhanX`*AXp7&*d&;K+okSG#)*d z+i(i>T+RW}bGc|ddM>x1ZNhU^m5ZuJrmOM-_zAi$H%vPxTo;BGoB>Uj3vY`|my1O7 zTqa~f&t+odq31FO5IvWLASrq-6a9{!%Y<>D=Q7V{Xt~Vw7&tMHWzY_ETLuGFm@QYCVMkWW!9CGvZ7?46SsOklqRqnaVCb^;0mjf| zZAcUztEx6M3O&|_mZHVlP?N}ERU6Ka4r{~t(O_*jzwlSC+J+suD~C4?^j52&*}_`6 zY84n7tECm}$X7Wep{ts8yBV6QnW|&xsb*t}p{1G)jSL;tY}mojP|b!0hJI@9Xkcik zW_<%gH#O_(8JekCTgQZ#s;XI2%OWpTP57LFUTW^HW@x2mRe_|i(1oUhOVeJG_hl%nro9@ zVd#lkY7#?B)L;yvBWm@H3=L6xrJkW5YB1i=4z;R!hHj|UyvEQBH5g^+g&KT1JvFO z82X=P2Mp~`a}P3fKMi^h%})cLLGRO`ABFX)swS)f>7Z>3=i{oTF*H6fLx#Sm=>|jF z(_ob8;sCA{EY0MQzhJ5GQ+O-P#nf=0n309yKA6M56}H0P0^Aio8onIE6^v%!|&OTo24UvOdI2PlHzzU@5g zoawA~9(G!tzjE$!ZgH-4E{ECvsZPR~<{anLIR<~4@8Jhvmj4U>7@x(P`HlQ5`~iMD zAK+K<^?WJJ^B3`Qo?t&`Z`(hD`TbM&*X&2_t#-M6n|-65vIp#|?3MN+d%fLkFSTdc%o?(GTKlZ$U~a#~ z+GO2qU1L3AJ#1~WPO-YJR%^9&rgf|}#i}viwgTwe*I`!wBlBzKQ|6=QR`bi|4dx>A z^JcS|HP^wceyKUjOqt9qH-?P6jISHNFsdI=M>eSi9bq(q);@WC;W|4QP zGm2cRPAA?~t4<@Xu2rWJ*Ho)hiu|fNxyUtY6Y;Ax>M_LCHR?x*tM;gqh%2kr6mdnR z+DN>oLTw-}FR1mzVW8F#*Hx*tMc%2_6uC~VE^@tEMI3}`C9xl<6NybA@Jabh;4e2ds- z%45W)t^5PAHKaUB41M)YV(64ZMQ#_i+xGODhi(Ck`tQ5kvnx zSmZM0?}(uv9w7DtF{55ewSN7>Gkm_f#mDrWSDs?*Al~+ z{R3iWNV$eMbd;-!VU*;F!JBf#p08XL6%R9O*ZVx7<6cR~ozD?k_7z3spCueJFDEpu z&4fl_6OZ2IU?zTZ8N1LKzYG)e_3_JAVI3uEg^oC2Xh(g(Yz!OyEx=Obne$7$#0348o5R`oYPBj(-xN zJG7Y4aZe;SfPcP7=7M{*!D9a(_-4Ul?f>gH zDpCIb&i+3fyH=F{-`W3%W1GaWALRZ&Uu51b${e}>59!y7^bd0XAIdyllqvTAfu{)` zeg7YFSdb&y|L2R0LxM-{|3mtYD1F5KKcqh^(#P8WhdlR)Jbc9dKcwFz(ns$9L;6OM zKGyy}s56LINT@7OYA8;O&67By3i~bBp?*Bu&7^mUL{eQkle@mo~wf_%! zUVs{mwf_%U?uXil{eQr%P~w>T|B&ZOk!P&^f5>y8$TQadKjc{`@{G0r4|&R>JY($t z^F`VlBG2!>{|`q#3`dT+|8G4Pd4&Id_y3_xaXtGZ_x~aN43R!^{~yvt|HF-D!}tFo zUHFtg*8V?Vq>BFcNACYa`t~S&jQxMe^GK9u#Qr~|-woqs#Qr~|-T=9y{eNK5|K7;` ze@O3$(qaD}SoFU)a{nLFPZ#OG`~E*1$>7NM?Ek|@hkYV_{sMmnMERHbmUqZ|17iGt z;ynv@`acK}{&#pcd3kRm#P?t9o#%bRJK38D(fw7P=PB-6?rwLx`vOGvKjPjGcl&?Y zy#eC-``r%rLWt@=9q#s@;WoHs5YvCidBfS^`~>dvf82S<+2(9-A8 z;hgNuyV(K0oxi~L@F)2r{62m+zm;DPk^OzVov-1``Dy(4 z-~V!tJcCp~Dj*e*3P=T{0w06|@jM;Aokd+(7i@RAzjZ2GGuBkSqEApi)`=vVsB~gdNV%mnqv6aNPjTX~3Y8+ch z>{{uXcIg^;X&l?g*tNJV2?|(?*Ri8pdU5TVa+I!sm#mTxi)kAc$5s;GHgZinE;Ae% z$42Q#3to%Yx8s_X#IcpGjE}jd9hV-A7ROe));-pmHkC7K99v1O+xv-WgS(^Oe;ixs z3b_A%V$?>Bbt{R7D_!>vO5)f`*SCkov6aNPja<`?)$vPX*Gl8nMvYM`iEk^7X)_>R zjmjJr#|Ck7@wGZ)9h-8Otf~)-X&V;DRubP<8q-!9$5y(&4Sn_g1|~f-J;}g4LibEa5YXGO z!XmINvMjpDvWOZH5djrZkyT_7l|@81YL?XyV$dwFg^+}fy{G!z)9D#AS#+}BezMh& zp5Ij0t*-i4-T$4cx~KbtXD#U+%BFh;bN!j2^!r$nX&O5=oo0*)_!q)Ide{I4{Q^I= zDjo|3n|I!6ez=Tz){QK@$Uifj>)qi`bARIXi|gGx?TqMx7t}*3pcGIFCccAzVp$6Czj?Vjn(y!s=K zT|Z%hc5SxYrcAC2{&z>T1`_r(<!GnE#04MIKF4qw!Se4N(D@zn;mNxu#qIh@leB9uEe{kaPe*6(P`(0U#Gt7pk1=%Q>tl}_ zd6tYEB=Rik>q`&zlusFXbQ(JcMsxK!a}bG<$;lHfJs4+%n*N`THd$GyL%OqXuyf>C zE036b7ETcG0?O7iJkTXimAq_2*Wj9LF0(Q_FMbtm;s1Id!O)p6tojotjWu*CL!e`R z1)ZqTvg@0hwSp)Qqqw)?ANGhLL_N6|8>N@}vzh#Gj*MhqCP_!^aY;Hy;#Z(Kb8V}B zar0QsiSu>LkAX+FVb|ByX%U_g(wF2vb3`L#%AQkT)P>;PSATV8XjS@;>n@X_;?qs5 z{>ZwqDlV(gF<(AgS6`4QSNYn;vikjC`tqMXqRKL5PnAEAT{m}4rVrd?b*485r!06d zUIEfFV|NBJXF3Omhsxtu{#qWM^4hbfzF5GX-${GOHM5)@PVc3I`Ft;2R^??Ye*~qb zr?1N7r3>Y!r#lA+`?8q{3d-LgX9sc;Lbj+SI^6O+7E7wdf*NHAJ(&o>B zla9_Wfd2l>KzDq-l9ypD6}(@bobr9pMBu>mbT}#VaEgv9lM0Prm5xQ_&sz-!o8vbQ?s z%V#-D=JHRuXp&~v&z`MC!|}<8KGTthi+X>CsvZBD7%@mjy|`z*oC$^tf9+I{6RBO5 z9P(Fu2Wf8DgPo`X<%<8-ac25ZOD%kd!T;)^6i^B%1(X6x0i}RaKq;UUPzopolmbct zrNDbn0bNUIww(Vb!r!p)Rd`YlrGQdEDWDWk3Md7X0!jg;fKosypcGIFCR?tOy+c0slk3mL6HZJx5$o; z-htksjt(erxeEmzKE47Mmd8W>(qZ_ZiHexpB<2)=>xK+=i5;1!f_YdyC&O_%dYN&57_Cr3_ffI zNmQem+Wc(nThe&vq$#UQ11|YlmWPj1_h4KP1>u@RJs43 za!zL9gJC9gf^P(w!1cf4FZXTlA@4lTavyTLUDNqIWKj>LfKosypcGIFCM2C;Fz_I54?gx!%=J?AVG5>e=gQlbA|6-XD9W?H0{?YuO zf5?ayj=$Kw%>V6kjcD%pO5V%--#X8T=8w13z0Cj3@ekRN^M7Of{k6CGzrG*pIb!~w zI33(XjLS``=l|;S|L78?ekui&0!jg;fKosypcGIFC2{eLz8ugIZ5DWDWk3Md7X0!jg;fKosypcGIF zCvzhA)KAhfjx(hhGct3-1nZ4{r*u2`>*Njd9XA%DL5)v z5X=bLg4)0dn7`fM=D+Cw!hhC((*L&quz##AyWQR9ZgMxc&$v&xkGc=IpL6eUZ*i}4uX2ani`^COGIxo4oO_r%&z<5nxgmVV z!A|ED=S63O^JC|G&NrO^>*_r6L4ij&Q---Va z&x;?3$HYToz4)}aMO-Vc5SNM`ae-JWP83Iq`C__g6*a=I{A#|I_w!DE9zUHQ#~1NA`~Y6hJ+9f??cdwKwtr?nZGXpp*#3fjr~L{0I{QjH zXRox|?X&EY>?7@i?WuN?9omMq(|W~v(b{1B*!r&Zb?ZLspRC)gk6RzLhOJAi71p`d z2drbQh1M)+zdDuu?=tzVoMt@%tmZ(&l$A#%YBNkp6TLWpSDybvH7wY=aX7A?Er0SYZ;*acT6iWIcL zDZiXd?c@c47(iEXMAy3*l`CF;O>pG=P}U?WkX(2;rcP4J6i$|*vXUyc$O2p|ic+`V9Z90##h*PHVs2g$P6drZOsZ)8> ziP#3I8N|si@@NHOdNPkX5GSR1bP;0fBpzLe_+l%M+T+wV9$kRg0IACnn_lM8hY;c9 zh|WiZGa@<<@#T6REsIkdcyume0IBC7*1o}`4T@Ok?&vjimf6;SY z0S!mbb&Jqi^jz0~N}}hw9J&lW*EK)`^jz15RPyg`Vpg zmK{mY6&f5Cl`U7e@LuS+j({qn<2p7}1|8RdKZYW7Tt^NybX>=Tx0Q~oX^sUM%9g7+ zvTx9H9oaYNxsL1`>A6C4;BCv6D;#)RbX-xhn@8xlA_<6&E2Q}7xI%UmI zv_;1i!sBST!r9HyZv~7av|FK91WI3r=h=cqsY--xnXd0S6(zYnk$F4p||qg21je<&^B~d8~PTF)izy@zG~Yh zM_aXp$N%It%W!Pow6jq6&ahhN+=$j_r!KH0#n#nmw+cbA@j;;wKoug@* z(4MkqY9_Q1J=27mpkN1tg(M>MdJ2nxvj?;pmY%T>8)=^|nbI9a3-G#L*!2wlToecU)14Rh_KI?6m>Vn(G&IHEsmC`!w5h})L{gmA?h#!&=2*uT#k0A zTP{a8)cG!sW~f8|pcm@U7ifk0F3XlqC^S96(Fb+i;%I|9T>GR8YSJ0XCa5K#XVC-` z;Q#1>32-2^zyyp`bif4E6Aduo_#FK&;TAdCUjjxdx?cju7Mfpz!=H|2l@o9cD|?@o zfRTdUmw=Ii)|Y^hBAriYa7LAVPb5lK!W58FvNZS!rj>xXm=?Y!XJjF)0K63bDttEl ze)#3^li@w#VwnH04X+OS!_M%$aEZS&I5PM|@Uzeh7lrk(4lp^?f?o&QgWm^F2X_YF zffax+1lI*;1y=^SU}ew_bN_>bsX>$f^&kuknDxKnZ}5NYf7kz#f1`i9f44u`Ki|LF zUkCI4F8_3Yj(?o*!i=B!i@YCt+r4exZ@iy-U-cgMPWI0B?)5J8{?WVD`)ltiFYm4L zj`nI`w!gq@^=$W9_jR}E{>t6re&1c}_Pd{SzYKH!d)%wto7}bTd2T1n^=G?>I&V5J zyJ_bIx6b*g>o_In+s;$YgYex3H#>JY*EnmP6)@93$2r9boTHru&NQbS zX~T9e%<&!j2z#D=fIZQA!@ASjV*S#324?tQv+lKSu`aikSp!z5b(*!nN?6mZCMz(v z!>s;#^EvZL^HKAD^KSDt^Dy%xX1kd;SHi6R1app=Hn~}A6pcHLuNki!zcgNgS^am7 zdyP)xW5zAU<;DPf5awyd0^|M0w8YxPFxTE{?WwEiN3@&IN^6KX$^@~Ym0Ue z@#Yq79&uZXHkY`iO`Aj9+^Eg2@JrgP3O8#riC=2gW)L?vYtxCF8ntN^-l9#daFaHL zcuSLZAaP@pb^vk1Hf=I-eWR8puB+E35pS#0+K6jQS}SoFXf4Do4O(-BH)~B5ZqXVm z+^RJY2ccF^><8LJV$;{^h`}Cei5*v)Kr9@shM2?LmDuK5lGw7fkl3iz0^*{j`403E z7)Hv_Jc*h}q)M6_=YUzS<`4%dO%OwCIWg4UCWhKu#N5|RVux!6G1OSE@Y`CV!Z22d z-xeAp=7N=ocXIXzV!On46B{-w#w|%E*gKRA-^H>kZdJ0xcE-st4`w@vVd?N~Vp!zc zPVBhsEn?xYH;H!$_Fu%j#NHq_IeR^>L6~5#QL=8bSBVokdnK+-SYrPfC&QeWZ6lt& zk^P={)@=4W;+eD9%fvHgvaQ6^XRzNAPn*uR5Ko!LULxK&g>5FDGL^kZ+%|=6BA)yr z`wek=GW#|0q%`{v;?_y*1>zT5*}oIFwy}-G4Xx}~#7!@=UlKPqv0o6^H?j@HFW0kw zBd%{?KPL|A+0Te;-(b%ZPpD--C9avko+D1xu%8eoQ|wvdFv|WxUBKrbyvdGpGL(hJmcw&)#ju>?MEOBieyN4Kh|1%Y?Wp@+10sALn zugLBqc0Klw#KL8F5*G#gG%>XA4r2KBuYVvmIQtYae0|p^iD4+*P7GhZ_4mZ^m07nD z8z%d^3R~>fSSk2^wNJ!Kxg~Z>oCBuY>~D!}!EPqzMfNwuFh*}8Hf?qzu~lR@5JL}s zoEUoWdSYndU&l3oZ(+MGu7Oix*Ty+u=FL7voZQX+iWvImnhMvjtBIi>3dCN(B4XjO zkCuyvnYFX~BZR`aicl|INw`~FL0Hm193xD_FDK-?*Ad!$Eum#!M(FNdL+I=tCKS#P zp)K-+)~;LytxE}aS*r<6Yp{av3{=qUCw#~3BQ(rQDpkkIqbCUm{C2pxARp>WP5wCpn~C{8CVno9^x z>jQ*F>9n{FmT_uaajSGn{4&hkPp;sOlPbthB;3JIAhh}MgrayHp)D2@TK2JoMe`U! z(|SLlQ93%VjA(I8NUqE_#@(%jnd(im?#|<=QK)-;zXFrA4-^RSx7i3eF$OO zr1w>D(}D`N%_rQ{b}(UU+d+gat@8+*TjmlrHP0bzY?@8DwQ&|qs$m9U-K*0H zYwM;FPNBLO+;9==p7guGdQVmfJ#Txy^)pR}-Pl z8woADfpC{qAIq;NCQ_nq)e$E2+PEk5(u6n>ru#L7$zqByOeP6~FeLPYfY9-MLbvD< zI<89yD}oht1R+fP35%vpXj&GbQ8ME;Bn%_2Z333@U?xU?@54$lyHm#hr@}9?@SSjb z_(`U=DU?rveDdX!C!bvTpSXOo<&!0!O!;KUCtW_lZi8R> z{Qpmj!{q({ufj}U?fo>4+o*AC6ri%l~us|KZpv^4R^k|Ie6tpDc6q{y(JOD%1Dp{y&s?tSnRR{{tT) zdF=gv$Wa41%KQJomgLd<|BM;0l+#D;|3muEW%|DM{~^zVGLIOw{}1V(lIf%O{~^5~ z)AzOi4|y(vI~hjr|3mW0a94xe{|7t@N-6LE10O7T^!`7j%P||m9_Wbue@JICeP8?k zjOiPp2K(Cohb-TK+Q|KX!26-Z{ks1TWiFRx%Kd-fGbE4R|A+KLW%|3_|A+jt{{y-I z&sbuY8kiJQ#?`!`b@;oN<$o+p{+5f@l{eMW8{U7Yl{eLL)q;i?C{||hGs|KE~#|7#E@0swdVmgMLE-OjhM@Xc^*xDoFCetuYkz^Y`8o; zBRoDl4DR<&hqVy4P=u)e&B2D?N5SK8$N&1^j^O6t8i@Gs3swZ@1gAi}fBCNeAP5o= z?f*Of1^+pS^?%gAAMW_S&A;Bi%Fp>d5a)je-0y!VMESS*HNNHTf*AizaKHc4-eVBq z|2gkd-c1nSzs9@Ry9n<7KN+I?5B8>b4W0+F{cpNk-HmY9{}b*b?w8!V-P_#jA+A5? z_PER4Ga#z}P@AU73d;R51|0w5RF~gbS zG>8_F6o%tLT>qP5E8ihDif8#Y@q~Cp+$Zi5w~Ff^vVXPc7Uzp4;#hGA$fh1j0i}Ra zKq;UUPzwA7C=lOU4xi4V9a`ZAZ6R^0s2xI_ENbr~4wKpf;=tGD6IaKpRmZed$F8+h z#dWn*$9s(t6V_Z6(>B(+cT-jD+F0>z)iH2?YE0W$acm>jrBm9$q(gO#+Wv}5t6uAt zYt-_-)-mJK$}87Yo9Y$$>XrTK9fGQ;!x1rUBjVVq;@ifGX&W<+ttxh{dQH1}4ZJ#z zZFKBf+?FH-ti|it<(qqP?V55_uYgyrl8=aK8xhA=72h^`O*<|#9396->3a)ai`Tc~ znpMTIRj-T(`zwyEIySC4rmZ@T?cKz#Rj+kd$FWt%u8kG1R=uWO9lKT?ueRS})T-j% zs^iuE - + diff --git a/tests/level_1_7/test_one_avg_daily_expenses.py b/tests/level_1_7/test_one_avg_daily_expenses.py index a8ecde6b..24a0a54a 100644 --- a/tests/level_1_7/test_one_avg_daily_expenses.py +++ b/tests/level_1_7/test_one_avg_daily_expenses.py @@ -46,5 +46,5 @@ ), ] ) -def test__calculate_average_daily_expenses(expenses, expected_result): +def test__calculate_average_daily_expenses(expenses:list[Expense], expected_result:decimal.Decimal)->bool: assert calculate_average_daily_expenses(expenses) == expected_result diff --git a/tests/level_1_7/test_three_is_subscription.py b/tests/level_1_7/test_three_is_subscription.py index 90a0a584..721aa2ab 100644 --- a/tests/level_1_7/test_three_is_subscription.py +++ b/tests/level_1_7/test_three_is_subscription.py @@ -33,27 +33,35 @@ def test__is_subscription(expense, history, expected_result): assert is_subscription(expense, history) == expected_result +def test__is_subscription_if_expense_occurs_multiple_times(expense, history): + assert is_subscription(expense, history) == True + + +@pytest.mark.xfail(reason='Incorrect work of function') +def test__is_subscription_if_expense_occurs_in_same_month(expense, history): + expense_updated = Expense( + amount=100, + currency='RUB', + card='1234', + spent_in='Megafon', + spent_at=datetime(2023, 3, 15, 0, 0), + category='ONLINE_SUBSCRIPTIONS' + ) + assert is_subscription(expense_updated, history) == False + +def test__is_subscription_if_expense_occurs_less_than_3_times(expense:list[Expense], history:list[list[Expense]])->bool: + expense_updated = Expense( + amount=100, + currency='RUB', + card='1234', + spent_in='Megafon', + spent_at=datetime(2023, 1, 1, 0, 0), + category='ONLINE_SUBSCRIPTIONS' + ) + history_updated = [ + expense, + Expense(amount=100, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 2, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), + ] + assert is_subscription(expense_updated, history_updated) == False - - - - - - - - - - - - - - - - - - - - - -# def test__is_subscription(expense, history) \ No newline at end of file From a653fb407923583ca7f67c6d3381971f31adaa71 Mon Sep 17 00:00:00 2001 From: Beloded1 Date: Fri, 16 Jun 2023 12:58:30 +0400 Subject: [PATCH 11/11] Fix many tests --- .coverage | Bin 61440 -> 61440 bytes .gitignore | 2 + conftest.py | 36 ++--- coverage.xml | 14 +- requirements.txt | 3 +- tests/level_1/test_five_title.py | 17 ++- tests/level_1/test_four_bank_parser.py | 1 + tests/level_1/test_one_gender.py | 25 ++-- tests/level_1/test_three_url_builder.py | 19 +-- tests/level_1/test_two_date_parser.py | 24 ++-- tests/level_1_5/test_five_replace_word.py | 12 +- tests/level_1_5/test_four_sentiment.py | 60 ++++---- tests/level_1_5/test_three_first.py | 22 ++- tests/level_1_7/test_four_fraud.py | 130 ++---------------- .../level_1_7/test_one_avg_daily_expenses.py | 79 +++++------ tests/level_1_7/test_three_is_subscription.py | 84 ++++------- .../level_1_7/test_two_expense_categorizer.py | 42 ++++-- 17 files changed, 253 insertions(+), 317 deletions(-) diff --git a/.coverage b/.coverage index 82735a4ad5be9513b94eb242aa249251e7f191f0..47958ae61324381745ab07366fd599eb4ead008e 100644 GIT binary patch delta 4357 zcmd7VYit}>6#(G5ubFdac4v2Edv|Ad?Ix*{I%%4uiR-v|xTyt|Kv5M{sT5Ta52>Ik z1R6ppp@fe2Do7O|l*(0vAU{G>MU{w9O9Dhyh0>~ODO89@d8n$26&%wPr!U&t2}_rA z_s(6$>)I+3Kk%>5XU@!?8P7R;JT}3`CfH;A1RJH#pYcw-MDE<{e$w6Le#{+lH@X9E zue-$cL_@qK{w7`)zZK7kC&lC9l=!|lD!w7^7x#+Kh`Yp2@lml^tP}kr5}{yxmS5%< z_@DR-{3-rZ{zLwQ@u8C=Wj4w-u{CTNE3$w&^j-QI{R@4OKL5}|+hS0of=EINQ4Q3s z3Cp0i8x|U%ZZXUwM+|d$P}>Z{EU2x9*#f97hP`;P&4!c6n+^Mr!-lm!P@9l3esVPe zHDtooi=b{wSOqm`coDhLFhXuHtl()kCY%DbK4AsaI>RaCTEhr=gJF3Z)EdK51hKl_ zxTgeawc&IRs8xpDO;7`dxe(NKhBbUXD-%wFT9FX%u0LTfsA~NNxjs%Gc`sH&msfvOntZcve7!}U}dDM^8Qs-%OmfHzTW z9nKf7fa);}@vqe_V*R(z>wD`;!dUMTLtSsd5U}37p^qix40VlR!WmH6gjjCIa0VF| z>YMNluizD=p%-IqV9Y&Fc}Pj}6qIX%6z@W4$~D1;q^g3@B_&_ndk^o5vC(l?#fPvGjCrG=>q zS!W$p$Xe_2G`YdL6p=O7JtcCz^>hzeZQb1@tE_V&8L+OE$#reVlVoN4ml|2ob}#9- z4s+yM>ugAtTZ=4NW{t1$QfogT*H}xR^jU)>z1AL(nl=tNT5vs5wFh`NsaQ8$68V@U zF^7|~CXuwzB&8$+82xNgP|4aBDw9n04S2YK@PX zSYyeK^{jN7*3fj`w-(_1D=8sIorVd=G{=PVPn$!Tb2TX^*L1EVVQgn-);hZ6%(Pu{ z-m@-8&b!u8*?Gsh6gmH}t~Q*vtuK|Fw*q%(>zxnFCFf0hpj39=ur8LI*W0c-m#uq> z&a`z`==|LpoBQ-nGPVD|=4Qv7jBRe(aCT{b*yhIkex1Kqb7M|f=gezvJka{!8aB5a zcDJ^Yu({FewL6;|E=eC(_Xl_G2<9!w3-|JP3_L+#`u9&yra1> zewU6f+T55lq?2Svb7Q<}?i52l}na!ECndO;c z#t+^P-VUaMmx5mhPX|8>P6sD~hl2-$!@>UG?qGMYBiJ4c1_MEFfZqcCRsVJWg8xVV zm;TTFAN!~L@A=>Hm4BbV7oL>d|Ac>sf1AI>U+?$(Wk2IP@*VlAd|CcRJ_C=ycjY;G z8omuwJUUVx7yA5$iBZwpnKjWUF;=jcl==tdY&ueKm5kb*+yK8^;v? ztstB1f$Bvv)OMBJWPPzp2Cbti*=Svf$cDD3$c@&u)YhN}PCK4nIrPSneC-x06|&wY zeb{km^B3B0IwzXVPp>HPf3u_DJ2_`XNsmT7(ULFK4_;APbIz8~p5QTFGPUQ;*<a|UB-c+Od4=BzGpYNuIf zkLlc9l5#$9UrEN^{M98rFvI_>A2AKnJ4%$=W77LgdhE?vQBpfidRDFV`&T#JTGCnr_d(oPmXLejZOaBckGZuLO delta 4040 zcmd7UTWB0r7zgk49P|`{f5m6shMEanjA`&DiRo6?knzXL2-`O)~o!y!s;)8wq^_#P^ zXLj=c&bM(AZ=A$0ldX6ZUohcs{Ty9>legBp+&j-Z-COMqdkejy$LSyRXZkh$l72+r zqi@g&x`RGPpQew}4fJ+;9le@fOwXbx(-m|vtzfPBbj!nHn+7M@+3S?1!73U^oRl z-f#f8+^{yl)N#NVzPVavYS@&k(@ZT(S!HUe;WY4A!!mG*VFf<6IORU3hEi6TI>vAx zaFJmdc(h@u&eWh`Uzx>fp>asB{p0~4N1@A-`%Td$esZ5C4`Jo{ zRx!xUvgBSvkz>g{hElNP?zAdda+e|OF}c%l7PfGQA%mOUu6Yp(DD#usz#Ikey|tYl2TL%SHlV0l& z+l^`^RJ9jsQ>fB*4VByOM66=KNvpH=WqBmUaCEJ zwqb<_D_Ys+W8|=QcebJaRjb~eZMg8hzA#_5Va;~EhIeHf>QCx=cebH^kFL*`Z61%2 zOQ276XB$3y3iK?UZQuyprj>25ey2fqwxO>7ScC3t^D%r-*XPYPEZPfOm@nI~WG8G# zXB)T;ZaHtZKfY4nXIXvRpInbu=ZDAD0SQNdI4r&wUx`n|`{E5TA$Eu@Vv~4StQYIVT5*{; zN1Q4~_);+>O1#EHPDD;P{2<@YX89L!^WNS%(dDl64TGmDYtkI?+0N@MnjE>=01P9FMj3u^G>O zwpKIK!CYOYk{JT#8Wb|qM0CV(pwAb0rO{l|!I2YzS>MqFA~a%uiR@wjPY(E){euHO z+gWr&NKd4{Kj2$!!fq$q0JDv>-H~H>_RI*^F&%VF1erVlB&E&{| gAlrvB4P=2^=$sCmZ^mESJvhF({>sFq-|ck&1jnBCO#lD@ diff --git a/.gitignore b/.gitignore index 033df5fb..f98852cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .venv __pycache__ +.coverage +coverage.xml \ No newline at end of file diff --git a/conftest.py b/conftest.py index a21a7338..641eb01f 100644 --- a/conftest.py +++ b/conftest.py @@ -1,22 +1,22 @@ -import pytest -from functions.level_1_7.models import Expense +from functions.level_1_7.models import Expense, Currency, BankCard, ExpenseCategory +import decimal +import datetime from datetime import datetime -@pytest.fixture -def expense(): + +def make_expenses( + amount: str = "100", + currency = Currency.RUB, + card = BankCard(last_digits="1234", owner="Alexandr"), + spent_in = "Online Store", + spent_at = datetime(2023, 1, 1, 0, 0, 0), + category: ExpenseCategory | None = None +) -> Expense: return Expense( - amount=100, - currency='RUB', - card='1234', - spent_in='Megafon', - spent_at=datetime(2023, 6, 1, 0, 0), - category='ONLINE_SUBSCRIPTIONS' + amount=decimal.Decimal(amount), + currency=currency, + card=card, + spent_in=spent_in, + spent_at=spent_at, + category=category ) - -@pytest.fixture -def history(expense): - return [ - expense, - Expense(amount=100, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 2, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - Expense(amount=100, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 3, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - ] diff --git a/coverage.xml b/coverage.xml index 6aeea652..d875dc18 100644 --- a/coverage.xml +++ b/coverage.xml @@ -1,5 +1,5 @@ - + @@ -8,7 +8,7 @@ C:\Users\Beloded\projects\testing_exercises\functions\level_1_7 - + @@ -69,7 +69,7 @@ - + @@ -82,11 +82,11 @@ - - + + - - + + diff --git a/requirements.txt b/requirements.txt index 1b6e276a..d7570493 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ pytest==7.2.1 pytest-cov==4.1.0 pytest-testdox -mypy==1.3.0 \ No newline at end of file +mypy==1.3.0 +freezegun==1.2.2 \ No newline at end of file diff --git a/tests/level_1/test_five_title.py b/tests/level_1/test_five_title.py index cf263f6c..0fcfe715 100644 --- a/tests/level_1/test_five_title.py +++ b/tests/level_1/test_five_title.py @@ -1,18 +1,31 @@ from functions.level_1.five_title import change_copy_item import pytest + def test__change_copy_item__add_copy(): assert change_copy_item('My Item') == 'Copy of My Item' + def test__change_copy_item__increase_number_of_copy(): assert change_copy_item('Copy of My Item (2)') == 'Copy of My Item (3)' -def test__change_copy_item__behavior_for_long_title(): - assert change_copy_item('Very long title with many words', max_main_item_title_length=10) == 'Very long title with many words' + +@pytest.mark.parametrize( + 'tittle, max_main_item_title_length, expected_result', + [ + ('Very long title with many words', 10, 'Very long title with many words'), + ('Very very very very long title with many words', 20, 'Very very very very long title with many words'), + ('Supep super super very very very very long title with many words', 30, 'Supep super super very very very very long title with many words'), + ] +) +def test__change_copy_item__behavior_for_long_title(tittle, max_main_item_title_length, expected_result): + assert change_copy_item(tittle, max_main_item_title_length) == expected_result + def test__change_copy_item__for_basic_case_with_text(): assert change_copy_item("Copy of My Item") == "Copy of My Item (2)" + @pytest.mark.parametrize( 'title, max_main_item_title_length, expected_result', [ diff --git a/tests/level_1/test_four_bank_parser.py b/tests/level_1/test_four_bank_parser.py index 655bf06e..d65b10f6 100644 --- a/tests/level_1/test_four_bank_parser.py +++ b/tests/level_1/test_four_bank_parser.py @@ -2,6 +2,7 @@ import datetime import decimal + def test__parse_ineco_expense__succes(): sms = SmsMessage( text="100.00 CARD1234, authcode1234 01.01.23 11:30 Alfa", diff --git a/tests/level_1/test_one_gender.py b/tests/level_1/test_one_gender.py index 5039b0df..37074484 100644 --- a/tests/level_1/test_one_gender.py +++ b/tests/level_1/test_one_gender.py @@ -2,18 +2,25 @@ import pytest -def test__genderalize__is_male(): - assert genderalize('говорил', 'говорила', 'male') == 'говорил' +@pytest.mark.parametrize( + 'verb_male, verb_female, gender, expected_result', + [ + ('говорил', 'говорила', 'male', 'говорил'), + ('кричал', 'кричала', 'male', 'кричал'), + ('кукорекал', 'кукорекала', 'male', 'кукорекал'), + ] +) +def test__genderalize__is_male(verb_male, verb_female, gender, expected_result): + assert genderalize(verb_male, verb_female, gender) == expected_result -def test__genderalize__is_not_male(): - assert genderalize('говорил', 'говорила', 'any str, except "male"') == 'говорила' @pytest.mark.parametrize( - 'verb_male, verb_female, gender, expected_result', + 'verb_male, verb_female, gender, expected_result', [ - ('говорил', 'говорила', 'male', 'говорил'), - ('говорил', 'говорила', 'any str, except "male', 'говорила'), + ('говорил', 'говорила', 'female', 'говорила'), + ('кричал', 'кричала', 'transgender', 'кричала'), + ('кукорекал', 'кукорекала', 'any str, except "male"', 'кукорекала'), ] ) -def test__genderalize(verb_male, verb_female, gender, expected_result): - assert genderalize(verb_male, verb_female, gender) == expected_result \ No newline at end of file +def test__genderalize__where_gender_is_not_male(verb_male, verb_female, gender, expected_result): + assert genderalize(verb_male, verb_female, gender) == expected_result diff --git a/tests/level_1/test_three_url_builder.py b/tests/level_1/test_three_url_builder.py index 31c4fb4f..7fa6fb88 100644 --- a/tests/level_1/test_three_url_builder.py +++ b/tests/level_1/test_three_url_builder.py @@ -3,21 +3,16 @@ def test__build_url__with_relative_url(): - result = build_url("example.com", "path/to/resource") - expected_result = "example.com/path/to/resource" - assert result == expected_result + assert build_url("example.com", "path/to/resource") == "example.com/path/to/resource" def test__build_url__with_relative_url_and_get_params(): - result = build_url("example.com", "path/to/resource", {"param1": "value1", "param2": "value2"}) - expected_result = "example.com/path/to/resource?param1=value1¶m2=value2" - assert result == expected_result + assert build_url("example.com", "path/to/resource", {"param1": "value1", "param2": "value2"}) == "example.com/path/to/resource?param1=value1¶m2=value2" def test__build_url__with_relative_url_and_empty_get_params(): - result = build_url("example.com", "path", {}) - expected_result = "example.com/path" - assert result == expected_result + assert build_url("example.com", "path", {}) == "example.com/path" + @pytest.mark.parametrize( 'host_name, relative_url, get_params, expected_result', @@ -25,7 +20,13 @@ def test__build_url__with_relative_url_and_empty_get_params(): ('example.com', 'path/to/resource', None, 'example.com/path/to/resource'), ('example.com', 'path/to/resource', {"param1": "value1", "param2": "value2"}, 'example.com/path/to/resource?param1=value1¶m2=value2'), ('example.com', 'path', {}, 'example.com/path'), + ], + ids=[ + 'build_url__with_relative_url', + 'build_url__with_relative_url_and_get_params', + 'build_url__with_relative_url_and_empty_get_params', ] + ) def test__build_url(host_name, relative_url, get_params, expected_result): assert build_url(host_name, relative_url, get_params) == expected_result diff --git a/tests/level_1/test_two_date_parser.py b/tests/level_1/test_two_date_parser.py index 209995d1..23f37b17 100644 --- a/tests/level_1/test_two_date_parser.py +++ b/tests/level_1/test_two_date_parser.py @@ -1,22 +1,22 @@ from functions.level_1.two_date_parser import compose_datetime_from +import datetime, pytest +from freezegun import freeze_time -import datetime, pytest +@freeze_time("2023-06-01 12:00:00") +def test__compose_datetime__from_today(): + result = compose_datetime_from("today", "10:30") + expected_result = datetime.datetime(2023, 6, 1, 10, 30) + assert result == expected_result -@pytest.mark.parametrize( - 'date_str, time_str, expected_result', - [ - ("today", "10:30", datetime.datetime.now().replace(hour=10, minute=30, second=0, microsecond=0)), - ("tomorrow", "14:45", (datetime.datetime.now() + datetime.timedelta(days=1)).replace(hour=14, minute=45, second=0, microsecond=0)), - ] -) -def test__compose_datetime__from(date_str, time_str, expected_result): - result = compose_datetime_from(date_str, time_str) +@freeze_time("2023-06-01 12:00:00") +def test__compose_datetime__from_tomorrow(): + result = compose_datetime_from("tomorrow", "14:45") + expected_result = datetime.datetime(2023, 6, 2, 14, 45) assert result == expected_result -def test__compose_datetime__wrong_time_format(): +def test__compose_datetime__wrong_time_format(): with pytest.raises(ValueError): compose_datetime_from("today", "10-30") - diff --git a/tests/level_1_5/test_five_replace_word.py b/tests/level_1_5/test_five_replace_word.py index baeff30d..3933726c 100644 --- a/tests/level_1_5/test_five_replace_word.py +++ b/tests/level_1_5/test_five_replace_word.py @@ -5,8 +5,16 @@ def test__replace_word__starts_with_case_irrelevant(): assert replace_word('the big black car', 'big', 'Cool') == 'the Cool black car' -def test__replace_word__unchanged_when_replace_word_not_found_in_text(): - assert replace_word('the big black car', 'red', 'small') == 'the big black car' +@pytest.mark.parametrize( + 'text, replace_from, replace_to, expected_result', + [ + ('the big black car', 'small', 'Cool', 'the big black car'), + ('the big black car', 'white', 'small', 'the big black car'), + ('the BIG black car', 'STRONG', 'cool', 'the BIG black car'), + ] +) +def test__replace_word__unchanged_when_replace_word_not_found_in_text(text, replace_from, replace_to, expected_result): + assert replace_word(text, replace_from, replace_to) == expected_result @pytest.mark.parametrize( diff --git a/tests/level_1_5/test_four_sentiment.py b/tests/level_1_5/test_four_sentiment.py index 93dcc3a5..1d660c6f 100644 --- a/tests/level_1_5/test_four_sentiment.py +++ b/tests/level_1_5/test_four_sentiment.py @@ -1,43 +1,45 @@ from functions.level_1_5.four_sentiment import check_tweet_sentiment import pytest +@pytest.mark.parametrize( + 'text, good_words, bad_words, expected_result', + [ + ('This text with only good words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], 'GOOD'), + ('This text with only perfect words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], 'GOOD'), + ('This text with only best words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], 'GOOD'), + ] +) +def test__check_tweet_sentiment__return_good_when_only_good_words_found(text, good_words, bad_words, expected_result): + assert check_tweet_sentiment(text, good_words, bad_words) == expected_result -def test__check_tweet_sentiment__return_good_when_only_good_words_found(): - text = 'This text with only good words' - good_words = ['good', 'best', 'perfect'] - bad_words = ['bad', 'scary', 'terrible'] - assert check_tweet_sentiment(text, good_words, bad_words) == 'GOOD' - - -def test__check_tweet_sentiment__return_bad_when_only_bad_words_found(): - text = 'This text with only bad words' - good_words = ['good', 'best', 'perfect'] - bad_words = ['bad', 'scary', 'terrible'] - assert check_tweet_sentiment(text, good_words, bad_words) == 'BAD' - - -def test__check_tweet_sentiment__return_none_when_equal_good_and_bad_words_found(): - text = 'This text with good and bad words' - good_words = ['good', 'best', 'perfect'] - bad_words = ['bad', 'scary', 'terrible'] - assert check_tweet_sentiment(text, good_words, bad_words) == None -def test__check_tweet_sentiment__return_none_when_no_good_and_bad_words_found(): - text = 'This text without needed words' - good_words = ['good', 'best', 'perfect'] - bad_words = ['bad', 'scary', 'terrible'] - assert check_tweet_sentiment(text, good_words, bad_words) == None +@pytest.mark.parametrize( + 'text, good_words, bad_words, expected_result', + [ + ('This text with only bad words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], 'BAD'), + ('This text with only scary words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], 'BAD'), + ('This text with only terrible words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], 'BAD'), + ] +) +def test__check_tweet_sentiment__return_bad_when_only_bad_words_found(text, good_words, bad_words, expected_result): + assert check_tweet_sentiment(text, good_words, bad_words) == expected_result @pytest.mark.parametrize( 'text, good_words, bad_words, expected_result', [ - ('This text with only good words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], 'GOOD'), - ('This text with only bad words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], 'BAD'), ('This text with good and bad words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], None), - ('This text without needed words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], None), + ('This text with good best and bad scary words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], None), + ('This text with good best perfect and bad scary terrible words', ['good', 'best', 'perfect'], ['bad', 'scary', 'terrible'], None), ] ) -def test__check_tweet_sentiment(text, good_words, bad_words, expected_result): - assert check_tweet_sentiment(text, good_words, bad_words) == expected_result \ No newline at end of file +def test__check_tweet_sentiment__return_none_when_equal_good_and_bad_words_found(text, good_words, bad_words, expected_result): + assert check_tweet_sentiment(text, good_words, bad_words) == expected_result + + +def test__check_tweet_sentiment__return_none_when_no_good_and_bad_words_found(): + text = 'This text without needed words' + good_words = ['good', 'best', 'perfect'] + bad_words = ['bad', 'scary', 'terrible'] + assert check_tweet_sentiment(text, good_words, bad_words) == None \ No newline at end of file diff --git a/tests/level_1_5/test_three_first.py b/tests/level_1_5/test_three_first.py index 70ca1197..3b343fe7 100644 --- a/tests/level_1_5/test_three_first.py +++ b/tests/level_1_5/test_three_first.py @@ -2,8 +2,21 @@ import pytest -def test__first__return_first_item_if_items_is_not_empty(): - assert first([5, 7, 1, 15]) == 5 +@pytest.mark.parametrize( + 'items, default, expected_result', + [ + ([5, 7, 1, 15], None, 5), + ([1, 2, 4, 1], None, 1), + ([7, 14, 1, 28], None, 7), + ([1, 1, 1, 1], None, 1), + ([1, 0, 0, 0], None, 1), + ([0, 0, 0, 0], None, 0), + ([-10, 0, 0, 0], None, -10), + ([-10, -20, -50, -100], None, -10), + ] +) +def test__first__return_first_item_if_items_is_not_empty(items, default, expected_result): + assert first(items, default) == expected_result def test__first__raise_error_if_empty_items_and_default_are_not_set(): @@ -24,6 +37,11 @@ def test__first__return_default_if_empty_items_found_and_default_is_int(): ([5, 7, 1, 15], None, 5), ([], None, None), ([], 0, 0), + ], + ids=[ + 'return_first_item_if_items_is_not_empty', + 'return_none_if_empty_items_found_and_default_is_non', + 'return_default_if_empty_items_found_and_default_is_int' ] ) def test__first(items, default, expected_result): diff --git a/tests/level_1_7/test_four_fraud.py b/tests/level_1_7/test_four_fraud.py index 2fe928f1..e92e725b 100644 --- a/tests/level_1_7/test_four_fraud.py +++ b/tests/level_1_7/test_four_fraud.py @@ -1,36 +1,11 @@ from functions.level_1_7.four_fraud import find_fraud_expenses -from functions.level_1_7.models import Expense, BankCard, ExpenseCategory, Currency -from decimal import Decimal -from datetime import datetime -import pytest +from conftest import make_expenses -def test__find_fraud_expenses__if_get_more_than_max_amount(): +def test__find_fraud_expenses__get_no_fraud_expenses_if_have_amount_more_than_max_amount(): history = [ - Expense( - amount=Decimal('5000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - Expense( - amount=Decimal('5001.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - Expense( - amount=Decimal('6001.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - + make_expenses(amount='5000.00'), + make_expenses(amount='5001.00'), + make_expenses(amount='6001.00'), ] expected_fraud_transactions = [] @@ -39,100 +14,23 @@ def test__find_fraud_expenses__if_get_more_than_max_amount(): assert fraud_transactions == expected_fraud_transactions -def test__find_fraud_expenses__if_get_less_than_min_chain_length(): +def test__find_fraud_expenses__get_no_fraud_expenses_if_have_len_amount_less_than_min_chain_length(): history = [ - Expense( - amount=Decimal('1000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - Expense( - amount=Decimal('2000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), + make_expenses(amount='1000.00'), + make_expenses(amount='2001.00'), ] - fraud_transactions = find_fraud_expenses(history) assert fraud_transactions == [] -@pytest.mark.xfail(reason='Incorrect work of function') # Думаю функция реализована неправильно. Но может я не разобрался просто. + def test__find_fraud_expenses__if_get_multiple_fraud_chains(): history = [ - Expense( - amount=Decimal('1000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - Expense( - amount=Decimal('2000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - Expense( - amount=Decimal('3000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - Expense( - amount=Decimal('4000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - ] - - expected_fraud_transactions = [ - Expense( - amount=Decimal('1000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - Expense( - amount=Decimal('2000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - Expense( - amount=Decimal('3000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), - Expense( - amount=Decimal('4000.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='The best drinking bar', - spent_at=datetime(2023, 6, 4, 23, 0, 0), - category=ExpenseCategory.BAR_RESTAURANT, - ), + make_expenses(amount='1000.00'), + make_expenses(amount='1000.00'), + make_expenses(amount='1000.00'), + make_expenses(amount='1000.00'), ] + expected_fraud_transactions = history fraud_transactions = find_fraud_expenses(history) assert fraud_transactions == expected_fraud_transactions diff --git a/tests/level_1_7/test_one_avg_daily_expenses.py b/tests/level_1_7/test_one_avg_daily_expenses.py index 24a0a54a..a4312948 100644 --- a/tests/level_1_7/test_one_avg_daily_expenses.py +++ b/tests/level_1_7/test_one_avg_daily_expenses.py @@ -1,50 +1,45 @@ import decimal from datetime import datetime -import pytest -from functions.level_1_7.models import Expense, BankCard, Currency from functions.level_1_7.one_avg_daily_expenses import calculate_average_daily_expenses +from conftest import make_expenses -@pytest.mark.parametrize( - 'expenses, expected_result', - [ - ( - [ - Expense( - amount=decimal.Decimal('100.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='Funny Shop', + +def test__calculate_average_daily_expenses_if_expenses_occurs_in_different_days(): + expenses = [ + make_expenses( + amount='100.00', + spent_at=datetime(2023, 6, 1, 12, 0, 0, 0), + ), + make_expenses( + amount='200.00', + spent_at=datetime(2023, 6, 1, 13, 0, 0, 0), + ), + make_expenses( + amount='300.00', + spent_at=datetime(2023, 6, 2, 14, 0, 0, 0), + ), + make_expenses( + amount='400.00', + spent_at=datetime(2023, 6, 2, 15, 0, 0, 0), + ), + ] + + expected_result = decimal.Decimal('500.00') + assert calculate_average_daily_expenses(expenses) == expected_result + + +def test__calculate_average_daily_expenses_if_one_expense_occurs(): + expenses = [ + make_expenses( + amount='100.00', spent_at=datetime(2023, 6, 1, 12, 0, 0, 0), - category=None - ), - Expense( - amount=decimal.Decimal('200.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='Funny Shop', - spent_at=datetime(2023, 6, 1, 13, 0, 0, 0), - category=None - ), - Expense( - amount=decimal.Decimal('300.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='Funny Shop', - spent_at=datetime(2023, 6, 2, 14, 0, 0, 0), - category=None - ), - Expense( - amount=decimal.Decimal('400.00'), - currency=Currency.RUB, - card=BankCard(last_digits='1234', owner='Alexandr'), - spent_in='Funny Shop', - spent_at=datetime(2023, 6, 2, 15, 0, 0, 0), - category=None ), - ], - decimal.Decimal('500.00') - ), ] -) -def test__calculate_average_daily_expenses(expenses:list[Expense], expected_result:decimal.Decimal)->bool: + expected_result = decimal.Decimal('100.00') assert calculate_average_daily_expenses(expenses) == expected_result + + +# def test__calculate_average_daily_expenses_with_empty_list(): # This test doesn't work, because raisestatistics.StatisticsError: mean requires at least one data point +# expenses = [] +# expected_result = decimal.Decimal('0.00') +# assert calculate_average_daily_expenses(expenses) == expected_result \ No newline at end of file diff --git a/tests/level_1_7/test_three_is_subscription.py b/tests/level_1_7/test_three_is_subscription.py index 721aa2ab..6d1efe58 100644 --- a/tests/level_1_7/test_three_is_subscription.py +++ b/tests/level_1_7/test_three_is_subscription.py @@ -1,67 +1,41 @@ from functions.level_1_7.three_is_subscription import is_subscription -from functions.level_1_7.models import Expense -import pytest from datetime import datetime +from conftest import make_expenses -@pytest.mark.parametrize( - "expense, history, expected_result", - [ - ( - Expense(amount=100, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 6, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - [ - Expense(amount=100, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 1, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - Expense(amount=200, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 2, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - Expense(amount=300, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 3, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - Expense(amount=400, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 4, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - Expense(amount=500, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 5, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - ], - True - ), - ( - Expense(amount=500, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 6, 5, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - [ - Expense(amount=500, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 1, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - Expense(amount=500, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 2, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), - Expense(amount=500, currency='RUB', card='1234', spent_in='Cofeshop', spent_at=datetime(2023, 3, 1, 0, 0), category='BAR_RESTAURANT'), - ], - False - ), +def test__is_subscription__no_subscription_when_expense_occurs_in_same_month(): + expense = make_expenses(spent_in='Megafon', spent_at=datetime(2023, 1, 2, 0, 0)) + history = [ + make_expenses(spent_in='Megafon', spent_at=datetime(2023, 1, 1, 0, 0)) ] -) -def test__is_subscription(expense, history, expected_result): - assert is_subscription(expense, history) == expected_result + assert is_subscription(expense, history) == False -def test__is_subscription_if_expense_occurs_multiple_times(expense, history): - assert is_subscription(expense, history) == True - +def test__is_subscription__when_successful_subscription_with_three_months_and_one_expense_in_each_month(): + expense = make_expenses(spent_in='Megafon', spent_at=datetime(2023, 6, 1, 0, 0)) + history = [ + make_expenses(spent_in='Megafon', spent_at=datetime(2023, 1, 1, 0, 0)), + make_expenses(spent_in='Megafon', spent_at=datetime(2023, 2, 1, 0, 0)), + make_expenses(spent_in='Megafon', spent_at=datetime(2023, 3, 1, 0, 0)), + ] + assert is_subscription(expense, history) == True -@pytest.mark.xfail(reason='Incorrect work of function') -def test__is_subscription_if_expense_occurs_in_same_month(expense, history): - expense_updated = Expense( - amount=100, - currency='RUB', - card='1234', - spent_in='Megafon', - spent_at=datetime(2023, 3, 15, 0, 0), - category='ONLINE_SUBSCRIPTIONS' - ) - assert is_subscription(expense_updated, history) == False -def test__is_subscription_if_expense_occurs_less_than_3_times(expense:list[Expense], history:list[list[Expense]])->bool: - expense_updated = Expense( - amount=100, - currency='RUB', - card='1234', - spent_in='Megafon', - spent_at=datetime(2023, 1, 1, 0, 0), - category='ONLINE_SUBSCRIPTIONS' - ) - history_updated = [ - expense, - Expense(amount=100, currency='RUB', card='1234', spent_in='Megafon', spent_at=datetime(2023, 2, 1, 0, 0), category='ONLINE_SUBSCRIPTIONS'), +def test__is_subscription__when_no_subscription_with_two_months_and_one_expense_in_each_month(): + expense = make_expenses(spent_in='Megafon', spent_at=datetime(2023, 6, 1, 0, 0)) + history = [ + make_expenses(spent_in='Megafon', spent_at=datetime(2023, 1, 1, 0, 0)), + make_expenses(spent_in='Megafon', spent_at=datetime(2023, 2, 1, 0, 0)), ] + assert is_subscription(expense, history) == False - assert is_subscription(expense_updated, history_updated) == False +def test__is_subscription__when_no_subscription_with_three_months_and_few_expenses_in_some_month(): + expense = make_expenses(spent_in='Megafon', spent_at=datetime(2023, 3, 2, 0, 0)) + history = [ + make_expenses(spent_in='Megafon', spent_at=datetime(2023, 1, 1, 0, 0)), + make_expenses(spent_in='Megafon', spent_at=datetime(2023, 2, 1, 0, 0)), + make_expenses(spent_in='Megafon', spent_at=datetime(2023, 2, 2, 0, 0)), + make_expenses(spent_in='Megafon', spent_at=datetime(2023, 3, 1, 0, 0)), + ] + assert is_subscription(expense, history) == False \ No newline at end of file diff --git a/tests/level_1_7/test_two_expense_categorizer.py b/tests/level_1_7/test_two_expense_categorizer.py index 8cfc9779..b80db2fb 100644 --- a/tests/level_1_7/test_two_expense_categorizer.py +++ b/tests/level_1_7/test_two_expense_categorizer.py @@ -1,26 +1,42 @@ from functions.level_1_7.two_expense_categorizer import guess_expense_category -from functions.level_1_7.models import Expense, ExpenseCategory +from functions.level_1_7.models import ExpenseCategory import pytest -from datetime import datetime +from conftest import make_expenses + @pytest.mark.parametrize( 'expense, ExpenseCategory', [ - (Expense(amount=10000, currency='RUB', card='1234', spent_in='Bastard place', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + (make_expenses(spent_in='Bastard place'), ExpenseCategory.BAR_RESTAURANT), - (Expense(amount=1000, currency='RUB', card='1234', spent_in='clean house', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + (make_expenses(spent_in='nice clean house'), ExpenseCategory.SUPERMARKET), - (Expense(amount=10, currency='USD', card='1234', spent_in='Netflix', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + (make_expenses(spent_in='Netflix USA'), ExpenseCategory.ONLINE_SUBSCRIPTIONS), - (Expense(amount=3000, currency='RUB', card='1234', spent_in='Wonder pharm', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + (make_expenses(spent_in='Wonder pharm'), ExpenseCategory.MEDICINE_PHARMACY), - (Expense(amount=2000, currency='RUB', card='1234', spent_in='kino park', spent_at=datetime(2023, 6, 1, 0, 0), category=None), - ExpenseCategory.THEATRES_MOVIES_CULTURE), - (Expense(amount=2000, currency='RUB', card='1234', spent_in='www.taxi.yandex.ru', spent_at=datetime(2023, 6, 1, 0, 0), category=None), + ] +) +def test__guess_expense_category_if_spent_in_contains_trigger_words(expense, ExpenseCategory): + assert guess_expense_category(expense) == ExpenseCategory + + +@pytest.mark.parametrize( + 'expense, ExpenseCategory', + [ + (make_expenses(spent_in='Bastard'), + ExpenseCategory.BAR_RESTAURANT), + (make_expenses(spent_in='pharm'), + ExpenseCategory.MEDICINE_PHARMACY), + (make_expenses(spent_in='www.taxi.yandex.ru'), ExpenseCategory.TRANSPORT), - (Expense(amount=5000, currency='RUB', card='1234', spent_in='Y Ashota', spent_at=datetime(2023, 6, 1, 0, 0), category=None), - None), + ] ) -def test__guess_expense_category(expense:Expense, ExpenseCategory:ExpenseCategory | None)->ExpenseCategory | None: - assert guess_expense_category(expense) == ExpenseCategory \ No newline at end of file +def test__guess_expense_category_if_spent_in_is_trigger_word(expense, ExpenseCategory): + assert guess_expense_category(expense) == ExpenseCategory + + +def test__guess_expense_category_if_spent_in_does_not_have_trigger_words(): + expense = make_expenses(spent_in='Y Ashota') + assert guess_expense_category(expense) == None \ No newline at end of file