diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f70cb1df --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +pycache/ +__pycache__/ \ No newline at end of file diff --git a/tests/level_1/conftest.py b/tests/level_1/conftest.py new file mode 100644 index 00000000..1fba7c49 --- /dev/null +++ b/tests/level_1/conftest.py @@ -0,0 +1,65 @@ +import pytest + +# ВОПРОС: то есть в этом тесте можно было обойтись совсем-совсем без фикстур? +# Они получились очень мелкими и многочисленными + +@pytest.fixture() +def host_name_1(): + return "host_name_8" + +@pytest.fixture() +def host_name_2(): + return "str" + +@pytest.fixture() +def relative_url(): + return "relative_url" + + +@pytest.fixture() +def get_params_mappings_k_and_v(): + return {'k': 'k_str', 'v': 'v_str'} + +@pytest.fixture() +def querypart_k_and_v(get_params_mappings_k_and_v): + return '?' + '&'.join([f'{k}={v}' for (k, v) in get_params_mappings_k_and_v.items()]) + +@pytest.fixture() +def url_k_and_v(host_name_2, relative_url, querypart_k_and_v): + return f'{host_name_2}/{relative_url}{querypart_k_and_v}' + +@pytest.fixture() +def get_params_mappings_k(): + return {'k': 'k_str'} + +@pytest.fixture() +def querypart_k(get_params_mappings_k): + return '?' + '&'.join([f'{k}={v}' for (k, v) in get_params_mappings_k.items()]) + +@pytest.fixture() +def url_k(host_name_1, relative_url, querypart_k): + return f'{host_name_1}/{relative_url}{querypart_k}' + + +@pytest.fixture() +def get_params_no_querypart(): + return {} + + +@pytest.fixture() +def get_params_none(): + return None + + +@pytest.fixture() +def get_params_attr_error(): + return [1,1] + +@pytest.fixture() +def querypart_no_querypart(get_params_no_querypart): + return '' + +@pytest.fixture() +def url_no_querypart(host_name_1, relative_url, querypart_no_querypart): + return f'{host_name_1}/{relative_url}{querypart_no_querypart}' + diff --git a/tests/level_1/test_five_title.py b/tests/level_1/test_five_title.py index fe767004..8f1c0ef5 100644 --- a/tests/level_1/test_five_title.py +++ b/tests/level_1/test_five_title.py @@ -1,5 +1,16 @@ from functions.level_1.five_title import change_copy_item +import pytest -def test_change_copy_item(): - pass +@pytest.mark.parametrize( + "title, max_main_item_title_length, expected_result", + [ + ('THIS IS TITLE', 100, 'Copy of THIS IS TITLE'), + ('THIS IS TITLE', 10, 'THIS IS TITLE'), + ('Copy of something(17)', 100, 'Copy of (18)'), + ('Copy of something (17)', 100, 'Copy of something (18)'), + ('Copy of something(1fvd7)', 100, 'Copy of something(1fvd7) (2)'), + ] +) +def test__change_copy_item__is_valid(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 df6c1b41..b446459b 100644 --- a/tests/level_1/test_four_bank_parser.py +++ b/tests/level_1/test_four_bank_parser.py @@ -1,5 +1,21 @@ from functions.level_1.four_bank_parser import BankCard, SmsMessage, Expense, parse_ineco_expense +import datetime +import decimal +from typing import NamedTuple def test_parse_ineco_expense(): - pass + text = "112.3 $, 40004234 13.05.23 17:23 Shop_name authcode jhtfj" + author = "Masha" + sent_at = datetime.datetime.now().time() + # Входное значение для функции + sms= SmsMessage(text, author, sent_at) + + bank_card1 = BankCard(last_digits='0123', owner= 'User1') + bank_card2 = BankCard(last_digits = '4234', owner = 'User2') + # Входное значение для функции + cards = [bank_card1, bank_card2] + + expense_result=Expense(amount = decimal.Decimal('112.3'), card = BankCard(last_digits ='4234', owner ='User2'), spent_in = 'Shop_name', spent_at = datetime.datetime(2023, 5, 13, 17, 23)) + assert parse_ineco_expense(sms, cards) == expense_result + diff --git a/tests/level_1/test_one_gender.py b/tests/level_1/test_one_gender.py index 31d0bc7f..6bfbf37f 100644 --- a/tests/level_1/test_one_gender.py +++ b/tests/level_1/test_one_gender.py @@ -1,5 +1,31 @@ from functions.level_1.one_gender import genderalize +import pytest -def test_genderalize(): - pass +@pytest.fixture +def verb_male(): + return "verb_male" + +@pytest.fixture +def verb_female(): + return "verb_female" + +@pytest.fixture +def random_symbols(): + return "4w5rgt" + +@pytest.mark.parametrize( + "verb_male, verb_female, gender, expected_result", + [ + (verb_male, random_symbols, "male", verb_male), + (verb_male, verb_female, "female", verb_female), + (verb_male, verb_female, random_symbols, verb_female), + ] +) +def test__genderalize__is_valid(verb_male, verb_female, gender, expected_result): + assert genderalize(verb_male, verb_female, gender) == expected_result + + +def test__genderalize_only_two_parameters_typeerror(): + with pytest.raises(TypeError): + genderalize(verb_male, verb_female) diff --git a/tests/level_1/test_three_url_builder.py b/tests/level_1/test_three_url_builder.py index bb7b54d2..a299cecc 100644 --- a/tests/level_1/test_three_url_builder.py +++ b/tests/level_1/test_three_url_builder.py @@ -1,5 +1,46 @@ from functions.level_1.three_url_builder import build_url +import pytest -def test_build_url(): - pass + + +@pytest.mark.parametrize( + "host_name, relative_url, get_params, expected_result", +[ + ('host_name_1', 'relative_url', 'get_params_none', 'url_no_querypart'), + ('host_name_2', 'relative_url', 'get_params_mappings_k_and_v', 'url_k_and_v'), + ('host_name_1', 'relative_url', 'get_params_mappings_k', 'url_k'), + ('host_name_1', 'relative_url', 'get_params_no_querypart', 'url_no_querypart'), +] +) +def test__build_url__is_valid(host_name, relative_url, get_params, expected_result, request): + host_name = request.getfixturevalue(host_name) + relative_url = request.getfixturevalue(relative_url) + get_params = request.getfixturevalue(get_params) + expected_result = request.getfixturevalue(expected_result) + assert build_url(host_name, relative_url, get_params) == expected_result + + +def test__build_url_only_host_name_typeerror(host_name_1): + with pytest.raises(TypeError): + build_url(host_name_1) + + +def test_build_url_only_get_params_typeerror(get_params_mappings_k): + with pytest.raises(TypeError): + build_url(get_params_mappings_k) + + +def test__build_url_value_error_no_parmeters(): + with pytest.raises(TypeError): + build_url() + +# Вопрос: убрать что ли нафиг этот тест, тк с такими данными результат - не тайпэррор( +def test__build_url_bad_key_in_get_params_typeerror(host_name_1, relative_url): + with pytest.raises(TypeError): + build_url(host_name_1, relative_url, {(1,1): None}) + + +def test__build_url_bad_key_in_get_params_attributeerror(host_name_1, relative_url, get_params_attr_error): + with pytest.raises(AttributeError): + build_url(host_name_1, relative_url, get_params_attr_error) \ No newline at end of file diff --git a/tests/level_1/test_two_date_parser.py b/tests/level_1/test_two_date_parser.py index b0247049..e246f340 100644 --- a/tests/level_1/test_two_date_parser.py +++ b/tests/level_1/test_two_date_parser.py @@ -1,5 +1,52 @@ from functions.level_1.two_date_parser import compose_datetime_from +import datetime +import pytest -def test_compose_datetime_from(): - pass +@pytest.fixture +def time_str(): + return "19:55" + +@pytest.fixture +def expected_result(time_str): + hour_str, minute_str = time_str.strip().split(":") + hour_str = int(hour_str) + minute_str = int(minute_str) + return datetime.datetime(datetime.date.today().year, + datetime.date.today().month, + datetime.date.today().day, + hour_str, minute_str) + + +@pytest.mark.parametrize( + "date_str, time_str, expected_result", + [ +# ("2023,12,15", time_str, expected_result), + ("tomorrow", "19:55", datetime.datetime(datetime.date.today().year, + datetime.date.today().month, + datetime.date.today().day+1, + 19,55)), + ("202yhbmj5", "19:33", datetime.datetime(datetime.date.today().year, + datetime.date.today().month, + datetime.date.today().day, + 19,33)), + ] +) +def test__compose_datetime_from__is_valid(date_str, time_str, expected_result): + assert compose_datetime_from(date_str, time_str) == expected_result + + +@pytest.mark.parametrize( + "date_str, time_str, expected_error, need_time_str", + [ + ("202yhbmj5", 14645, AttributeError, 1), + ("19:33", 0, TypeError, 0) + + ] +) +def test__compose_datetime_from__error(date_str, time_str, expected_error, need_time_str): + with pytest.raises(expected_error): + if need_time_str == 1: + compose_datetime_from(date_str, time_str) + else: + compose_datetime_from(date_str) diff --git a/tests/level_1_5/test_first.py b/tests/level_1_5/test_first.py new file mode 100644 index 00000000..7a4883e5 --- /dev/null +++ b/tests/level_1_5/test_first.py @@ -0,0 +1,50 @@ +from functions.level_1_5.three_first import first, NOT_SET +import pytest + + +@pytest.mark.parametrize( + "items, default, expected_result, items_need", + [ + ([1, 2, 3], None, 1, 1), + ([1, 2, 3], NOT_SET, 1, 1), + ([], 'default', 'default', 1), + ('', 'default', 'default', 1), + (None, 'default', 'default', 1), + (None, 1234, 1234, 1), + (None, None, None, 1 ), + (None, (5, 56), (5, 56), 1), + (0, 'default', 'd', 0), + (0, NOT_SET, 'N', 0) + ] +) +def test__first__is_valid(items, default, expected_result, items_need): + if items_need == 1: + assert first(items, default) is expected_result + else: + assert first(default) is expected_result + +@pytest.mark.parametrize( + "items, default, expected_error, items_need, default_need", + [ + ([], 0, AttributeError, 1, 0), + ([], NOT_SET, AttributeError, 1, 1), + (0, 0, TypeError, 0, 0), + ] +) +def test__first__errors(items, default, expected_error, items_need, default_need): + with pytest.raises(expected_error): + if items_need == 1: + if default_need == 1: + first(items, default) + else: + first(items) + else: + if default_need == 1: + pass + else: + first() + + +def test__first__items_is_empty_attributeerror(): + with pytest.raises(AttributeError): + first([], ) 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..d4e9c8ff --- /dev/null +++ b/tests/level_1_5/test_five_replace_word.py @@ -0,0 +1,34 @@ +from functions.level_1_5.five_replace_word import replace_word +import pytest + +@pytest.mark.parametrize( + "text, replace_from, replace_to, expected_result", + [ + ('one two three four', 'two', 'replace_to', 'one replace_to three four'), + ('one two three Two four', 'two', 'replace_to','one replace_to three replace_to four'), + ('one two three four', 'TWo', 'replace_to','one replace_to three four'), + ('one two three four', '1234', 'replace_to', 'one two three four'), + ('one two three four', '', 'replace_to', 'one two three four'), + ('one two three four', 'two', '', 'one three four'), + ] +) +def test__replace_word__is_valid(text, replace_from, replace_to, expected_result): + assert replace_word(text, replace_from, replace_to) == expected_result + + +@pytest.mark.parametrize( + "text, replace_from, replace_to, expected_error", + [ + ('one two three four', 'two', 123, TypeError), + ('one two three four', 2, '123', AttributeError), + (123314, 'two', '123', AttributeError), + ] +) +def test__replace_word__errors(text, replace_from, replace_to, expected_error): + with pytest.raises(expected_error): + replace_word(text, replace_from, replace_to) + + +def test__replace_word__not_enough_params_typeerror(): + with pytest.raises(TypeError): + replace_word('123', 'bsrbg') \ No newline at end of file diff --git a/tests/level_1_5/test_four_check_tweet_sentiment.py b/tests/level_1_5/test_four_check_tweet_sentiment.py new file mode 100644 index 00000000..6b898819 --- /dev/null +++ b/tests/level_1_5/test_four_check_tweet_sentiment.py @@ -0,0 +1,37 @@ +from functions.level_1_5.four_sentiment import check_tweet_sentiment +import pytest + + +@pytest.mark.parametrize( +"text, good_words, bad_words, expected_result", +[ + ('g1 b1 g2 b2 g3 b3 ', {'g1','g2'}, {'b1', 'b2'}, None), + ('g0 b0 g0 b0 g3 b3 ', {'g1','g2'}, {'b1', 'b2'}, None), + ('g1 b2 g0 b0 g3 b3 ', {'g1','g2'}, {'g1', 'g2'}, None), + ('g1 b2 g0 b0 g3 b3 g4 b4', {'g1','g2', 'g3'}, {'g1', 'g2'},'GOOD'), + ('1 2', '5 6 7 4', '2', 'BAD'), + ('g0 b0 g0 b0 g0 b3 g4 b4', {'g1','g2', 'g3'}, {'g1', 'g2'}, None), + ('g0 b0 g3 b3 g4 b4', {'g1','g2'}, {'g1', 'g2', 'g3'},'BAD'), + ('g0 b0 g3 b3 g4 b4', {''}, {'g1', 'g2', 'g3'}, 'BAD'), + ('g0 b0 g3 b3 g4 b4', {''}, {''}, None), + ('', {''}, {''}, None), + ('one two', 'one', 'two', None), +] +) + +def test__check_tweet_sentiment__is_valid(text, good_words, bad_words, expected_result): + assert check_tweet_sentiment(text, good_words, bad_words) is expected_result + + +@pytest.mark.parametrize( +"text, good_words, bad_words, expected_error", +[ + # ('', {''}, TypeError), + (123, '5 6 7 4', '2', AttributeError), +] +) + +def test__check_tweet_sentiment__errors(text, good_words, bad_words, expected_error): + with pytest.raises(expected_error): + check_tweet_sentiment(text, good_words, bad_words) + 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..6737fba3 --- /dev/null +++ b/tests/level_1_5/test_one_median.py @@ -0,0 +1,33 @@ +from functions.level_1_5.one_median import get_median_value +import pytest + + + +@pytest.mark.parametrize( + "items, expected_result", + [ + ('', None), + ([2, 1, 5], 5), + ([-2, -1, 5], 5), + ([2, 1, 3, 9, 10], 9), + ([2, 1, 1, 1, 3, 3, 2, 9, 9, 3, 9, 10], 9), + ([0.6, 99.4, 13.2], 13.2), + ] +) +def test__get_median__is_valid(items, expected_result): + assert get_median_value(items) is expected_result + +@pytest.mark.parametrize( + "items, expected_error, items_need", + [ + (0, TypeError, 0), + ([2, 1, 3, 9], IndexError, 1), + (1, TypeError, 1), + ] +) +def test__get_median_value__errors(items, expected_error, items_need): + with pytest.raises(expected_error): + if items_need == 1: + get_median_value(items) + else: + get_median_value() diff --git a/tests/level_1_5/test_solve_square_equation.py b/tests/level_1_5/test_solve_square_equation.py new file mode 100644 index 00000000..104c925c --- /dev/null +++ b/tests/level_1_5/test_solve_square_equation.py @@ -0,0 +1,41 @@ +from functions.level_1_5.two_square_equation import solve_square_equation +import pytest + + +@pytest.mark.parametrize( + "square_coefficient, linear_coefficient, const_coefficient, expected_results", + [ + (0, 0, 0, (None, None)), + (5, 2, 0, (-0.4, 0.0)), + (0, 2, 10,(-5.0, None)), + (0, 2, 0, (0.0, None)), + (4, 0, -16, (-2.0, 2.0)), + (5, 3, -26, (-2.6, 2.0)), + (1, 2, 5, (None, None)), + (1.1, 2.2, -5.5, (-3.449489742783178, 1.4494897427831779)), + ] + +) + +def test__solve_square_equation__is_valid(square_coefficient, linear_coefficient, const_coefficient, expected_results): + assert solve_square_equation(square_coefficient, linear_coefficient, const_coefficient) == expected_results + + +def test__solve_square_equation__not_enougt_params(): + with pytest.raises(TypeError): + solve_square_equation(0, 0) + + +def test__solve_square_equation__too_many_params(): + with pytest.raises(TypeError): + solve_square_equation(5, 2, 0, 9) + + +def test__solve_square_equation__params_are_string(): + with pytest.raises(TypeError): + solve_square_equation('a', 'b', 'c') + + +def test__solve_square_equation__params_are_lists(): + with pytest.raises(TypeError): + solve_square_equation([0], [0], [0]) diff --git a/tests/level_2/conftest.py b/tests/level_2/conftest.py new file mode 100644 index 00000000..62217acf --- /dev/null +++ b/tests/level_2/conftest.py @@ -0,0 +1,43 @@ +import pytest +from functions.level_2.two_students import Student + + +@pytest.fixture +def name(): + return("{ Something }") + +@pytest.fixture +def result1(name): + return name[2:len(name) - 2] + +@pytest.fixture +def name2(): + return("{ Something }") + +@pytest.fixture +def result2(): + return "Something" + +@pytest.fixture +def student1(): + return Student("Diana", "Ratnikova", "@winterlich_weiss") + +@pytest.fixture +def student2(): + return Student("Name", "Last Name", "@nickname") + +@pytest.fixture +def student3(): + return Student("wrtgshn", "athbgfs", "nickname") + +@pytest.fixture +def students(student1, student2, student3): + return [student1, student2, student3] + +@pytest.fixture +def telegram_username1(): + return "winterlich_weiss" + +@pytest.fixture +def telegram_username2(): + return "wshgfhnjtnhg" diff --git a/tests/level_2/test_generate_promocode.py b/tests/level_2/test_generate_promocode.py new file mode 100644 index 00000000..847fe837 --- /dev/null +++ b/tests/level_2/test_generate_promocode.py @@ -0,0 +1,2 @@ + +#Это оч интересная функция, ннада будет подумать, как тестировать)) \ No newline at end of file diff --git a/tests/level_2/test_get_student_by_tg_nickname.py b/tests/level_2/test_get_student_by_tg_nickname.py new file mode 100644 index 00000000..ca5354fe --- /dev/null +++ b/tests/level_2/test_get_student_by_tg_nickname.py @@ -0,0 +1,14 @@ +from functions.level_2.two_students import get_student_by_tg_nickname, Student +import pytest + + +def test__get_student_by_tg_nickname__is_ok_three_params(telegram_username1, students, student1): + assert get_student_by_tg_nickname(telegram_username1, students) is student1 + + +def test__get_student_by_tg_nickname__first_elem_of_list(telegram_username1, students): + assert get_student_by_tg_nickname(telegram_username1, students) is students[0] + + +def test__get_student_by_tg_nickname__is_None(telegram_username2, students): + assert get_student_by_tg_nickname(telegram_username2, students) is None \ No newline at end of file diff --git a/tests/level_2/test_one_brackets.py b/tests/level_2/test_one_brackets.py new file mode 100644 index 00000000..78fc68a8 --- /dev/null +++ b/tests/level_2/test_one_brackets.py @@ -0,0 +1,27 @@ +from functions.level_2.one_brackets import delete_remove_brackets_quotes +import pytest + + + +def test__delete_remove_brackets_quotes__function_in_return_of_result(name, result1): + assert delete_remove_brackets_quotes(name) == result1 + +def test__delete_remove_brackets_quotes__result2_is_string(name, result2): + assert delete_remove_brackets_quotes(name) == result2 + +# Вопрос: +# Похоже, мне нужны примеры грамотного использования фикстур в параметрайзах. +# Применила самый очевидный мне вариант в комментах ниже: +# Параметрайз здесь не видит файл конфтест. +# А если переношу фикстуры в текущий файл, жалуется, что name - это функция, +# над которой нельзя производить действия как со строкой + +#@pytest.mark.parametrize( +# "name, expected_result", +# [ +# (name, result1), +# (name, result2), +# ] +#) +#def test__delete_remove_brackets_quotes__is_valid(name, expected_result): +# assert delete_remove_brackets_quotes(name) == expected_result \ No newline at end of file