diff --git a/.gitlab/linter.yml b/.gitlab/linter.yml index 6b5ace6..f97c563 100644 --- a/.gitlab/linter.yml +++ b/.gitlab/linter.yml @@ -14,7 +14,7 @@ Pylint: allow_failure: true extends: .linter_template script: - - pylint --rcfile=pylintrc $PWD | tee ./pylint/pylint.log || pylint-exit $?; rm __init__.py + - pylint --rcfile=pylintrc $PWD | tee ./pylint/pylint.log after_script: - PYLINT_SCORE=$(sed -n 's/^Your code has been rated at \([-0-9.]*\)\/.*/\1/p' ./pylint/pylint.log) - echo $PYLINT_SCORE @@ -26,11 +26,6 @@ Pylint: paths: - ./pylint/ -Pylint Hard: - extends: .linter_template - script: - - pylint --rcfile=pylintrc $PWD --disable=missing-function-docstring,missing-class-docstring,useless-super-delegation,line-too-long,global-statement,arguments-differ,invalid-name - #Quality Control: # allow_failure: false # stage: Merge Request diff --git a/fixtures_browsers.py b/fixtures_browsers.py index 2103148..a100629 100644 --- a/fixtures_browsers.py +++ b/fixtures_browsers.py @@ -9,24 +9,28 @@ @pytest.fixture(scope='function') def browser_func(choose_driver): + """Browser that closes after each test function or method.""" yield choose_driver choose_driver.quit() @pytest.fixture(scope='class') def browser_class(choose_driver): + """Browser that closes after each test class.""" yield choose_driver choose_driver.quit() @pytest.fixture(scope='module') def browser_module(choose_driver): + """Browser that closes after each test module.""" yield choose_driver choose_driver.quit() @pytest.fixture(scope='session') def choose_driver(is_remote, t_browser): + """Remote or local browser selector fixture.""" if is_remote: return remote_driver(t_browser) return custom_driver(t_browser) diff --git a/fixtures_session.py b/fixtures_session.py index 00d71d9..67303b9 100644 --- a/fixtures_session.py +++ b/fixtures_session.py @@ -1,11 +1,12 @@ +# pylint: disable=missing-function-docstring import pytest -from src.main.session import MySession, HttpbinApiSessionLevelOne, HttpbinApiSessionLevelTwo +from src.main.session import ApiSession, HttpbinApiSessionLevelOne, HttpbinApiSessionLevelTwo @pytest.fixture(scope='session', autouse=True) -def api_session() -> MySession: - with MySession() as session: +def api_session() -> ApiSession: + with ApiSession() as session: yield session diff --git a/src/main/allure_helpers.py b/src/main/allure_helpers.py index d679d37..ef7c8dd 100644 --- a/src/main/allure_helpers.py +++ b/src/main/allure_helpers.py @@ -1,3 +1,4 @@ +# pylint: disable=missing-function-docstring,missing-class-docstring import json import logging from functools import wraps @@ -71,7 +72,7 @@ def wrapper(*args, **kwargs): attachment_type=allure.attachment_type.JSON, extension='json') - except ValueError as error: + except ValueError: logging.error('RESPONSE IN NOT JSON FORMAT') allure.attach( body=response.text.encode('utf8'), @@ -79,7 +80,6 @@ def wrapper(*args, **kwargs): f'{response.request.url}', attachment_type=allure.attachment_type.TEXT, extension='txt') - raise error return response return wrapper diff --git a/src/main/file.py b/src/main/file.py index 497ac41..ec9a9fb 100644 --- a/src/main/file.py +++ b/src/main/file.py @@ -6,7 +6,7 @@ def read_json(filename): """Read json and attach to allure as file.""" - with open(os.path.join(os.path.dirname(__file__), 'resources', filename)) as file: + with open(os.path.join(os.getcwd(), 'resources', filename)) as file: schema = json.loads(file.read()) allure.attach(body=json.dumps(schema, indent=2, ensure_ascii=False).encode('utf8'), name='Json schema', attachment_type=allure.attachment_type.JSON) diff --git a/src/main/session.py b/src/main/session.py index e541b83..6f60482 100644 --- a/src/main/session.py +++ b/src/main/session.py @@ -1,3 +1,4 @@ +# pylint: disable=arguments-differ import json import allure @@ -6,22 +7,18 @@ from src.main.allure_helpers import allure_request_logger -class MySession(Session): - def __init__(self): - super().__init__() +class ApiSession(Session): + """Requests api session which Log request/response to allure attachments and console.""" @allure_request_logger def request(self, method, url, **kwargs) -> Response: - """ Log request/response to allure and info""" - response = super().request(method=method, url=url, **kwargs) return response class HttpbinApiSessionLevelOne(Session): - def __init__(self, **kwargs): - super().__init__(**kwargs) + """Requests api session which has hardcoded base_url.""" def request(self, method, url, **kwargs) -> Response: url = f'https://httpbin.org{url}' @@ -30,8 +27,8 @@ def request(self, method, url, **kwargs) -> Response: class HttpbinApiSessionLevelTwo(Session): - def __init__(self, **kwargs): - super().__init__(**kwargs) + """Requests api session which has hardcoded base_url. + And logs request/response into allure attachments.""" def request(self, method, url, **kwargs) -> Response: url = f'https://httpbin.org{url}' @@ -40,19 +37,22 @@ def request(self, method, url, **kwargs) -> Response: try: allure.attach( body=url.encode('utf8'), - name=f'Request {response.status_code} {method} {url}', + name=f'Request {response.status_code} {response.request.method} ' + f'{response.request.url}', attachment_type=allure.attachment_type.TEXT, extension='txt') response.json() allure.attach( body=json.dumps(response.json(), indent=4, ensure_ascii=False).encode('utf8'), - name=f'Response {response.status_code} {response.request.method} {response.request.url}', + name=f'Response {response.status_code} {response.request.method} ' + f'{response.request.url}', attachment_type=allure.attachment_type.JSON, extension='json') except ValueError as error: allure.attach( body=response.text.encode('utf8'), - name=f'NOT JSON Response {response.status_code} {response.request.method} {response.request.url}', + name=f'NOT JSON Response {response.status_code} {response.request.method} ' + f'{response.request.url}', attachment_type=allure.attachment_type.TEXT, extension='txt') raise error diff --git a/src/test/moretv/__init__.py b/src/test/moretv/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/test/moretv/main_page/__init__.py b/src/test/moretv/main_page/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/test/old_ctc/__init__.py b/src/test/old_ctc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/test/old_ctc/tvprogram/__init__.py b/src/test/old_ctc/tvprogram/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/test/old_ctc/tvprogram/test_weeks_slider.py b/src/test/old_ctc/tvprogram/test_weeks_slider.py index a9289e2..ed61e5f 100644 --- a/src/test/old_ctc/tvprogram/test_weeks_slider.py +++ b/src/test/old_ctc/tvprogram/test_weeks_slider.py @@ -6,6 +6,7 @@ def test_current_week_is_active(browser_module): + """Assert that /programm page opens tv-program schedule on current week.""" logging.info('step1/2: start') browser_module.open('https://ctc.ru/programm') logging.info('step1/2: finish') @@ -15,18 +16,22 @@ def test_current_week_is_active(browser_module): def test_current_week_has_words_in_days(browser_module): + """Assert that /program page current week slider has week as weekdays names.""" logging.info('step1/2: start') browser_module.open('https://ctc.ru/programm') logging.info('step1/2: finish') logging.info('step2/2: start') - browser_module.all('.current_week .slider-item-day .m-desktop .day-week').should(have.exact_texts(*weekdays.in_words())) + browser_module.all('.current_week .slider-item-day .m-desktop .day-week')\ + .should(have.exact_texts(*weekdays.in_words())) logging.info('step2/2: finish') def test_today_is_active(browser_module): + """Assert that /programm page opens tv-schedule on today.""" logging.info('step1/2: start') browser_module.open('https://ctc.ru/programm') logging.info('step1/2: finish') logging.info('step2/2: start') - browser_module.element('.current_week .slider-item-day.current').should(have.exact_text('СЕГОДНЯ')) + browser_module.element('.current_week .slider-item-day.current')\ + .should(have.exact_text('СЕГОДНЯ')) logging.info('step2/2: finish') diff --git a/src/test/test_api.py b/src/test/test_api.py index e0cae96..dda4030 100644 --- a/src/test/test_api.py +++ b/src/test/test_api.py @@ -1,3 +1,4 @@ +# pylint: disable=missing-function-docstring import json import os @@ -28,7 +29,7 @@ def test_patch(self): with open(os.path.join(os.path.dirname(__file__), 'resources', 'patch.json')) as file: schema = json.loads(file.read()) - body = requests.get('https://httpbin.org/patch').json() + body = requests.patch('https://httpbin.org/patch').json() validictory.validate(body, schema, fail_fast=False) @@ -63,7 +64,7 @@ def test_patch(self): name='Json schema', attachment_type=allure.attachment_type.JSON) allure.attach(url, 'Requested API', allure.attachment_type.URI_LIST) - body = requests.get(url).json() + body = requests.patch(url).json() allure.attach(body=json.dumps(body, indent=2, ensure_ascii=False).encode('utf8'), name="Response", attachment_type=allure.attachment_type.JSON) @@ -131,14 +132,14 @@ def request(self, method, url): name="Response", attachment_type=allure.attachment_type.JSON) return body - def httpbin(self, method, url): + def http_bin(self, method, url): return self.request(method, f'https://httpbin.org{url}') @allure.title('GET "https://httpbin.org/get"') def test_get(self): schema = file.read_json('get.json') - body = self.httpbin('get', '/get') + body = self.http_bin('get', '/get') validictory.validate(body, schema, fail_fast=False) @@ -146,7 +147,7 @@ def test_get(self): def test_patch(self): schema = file.read_json('patch.json') - body = self.httpbin('patch', '/patch').json() + body = self.http_bin('patch', '/patch') validictory.validate(body, schema, fail_fast=False) diff --git a/src/test/test_assertions.py b/src/test/test_assertions.py index 3f2947a..a5806e0 100644 --- a/src/test/test_assertions.py +++ b/src/test/test_assertions.py @@ -1,3 +1,4 @@ +# pylint: disable=global-statement,missing-function-docstring import contextlib from pytest_voluptuous import S diff --git a/src/test/test_duplicates.py b/src/test/test_duplicates.py index 0c8347a..a6ae139 100644 --- a/src/test/test_duplicates.py +++ b/src/test/test_duplicates.py @@ -21,10 +21,13 @@ def test_list_of_dictionaries_does_not_duplicate_by_some_key_value(): """ + 1. create new dict with global keys by some key value which could repeat in list of dictionaries and append to this key a list of dictionaries, where this value figure 2. assert that dictionaries does not duplicate by some key's value + """ + new_some_view = defaultdict(list) for some in SOMETHING: @@ -42,6 +45,16 @@ def test_list_of_dictionaries_does_not_duplicate_by_some_key_value(): Random().randints(20, 0, 10), ]) def test_list_doesnt_have_duplicates(some_list): + """Parametrized test asserts there is no duplicate ints in list. + + Using next features: + 1. Random() function; + 2. Sorting set; + 3. Sorting list; + 4. List comprehension; + + """ + some_list.sort() logging.info(some_list) @@ -53,6 +66,14 @@ def test_list_doesnt_have_duplicates(some_list): def has_duplicates(list_of_values): + """Returns True if there are duplicates in list. + + Nothing special: + Simple cycle. + Uses any() method to check. + + """ + value_dict = defaultdict(int) for item in list_of_values: value_dict[item] += 1 @@ -60,6 +81,7 @@ def has_duplicates(list_of_values): def test_print_not_duplicated(): + """Test for method has_duplicates returns False.""" list_of_values = [2, -2] info(has_duplicates(list_of_values)) @@ -67,6 +89,7 @@ def test_print_not_duplicated(): def test_print_duplicated(): + """Test for method has_duplicates returns True.""" list_of_values = [2, 2] info(has_duplicates(list_of_values)) diff --git a/src/test/test_file_downloader.py b/src/test/test_file_downloader.py index 1655819..fde0638 100644 --- a/src/test/test_file_downloader.py +++ b/src/test/test_file_downloader.py @@ -7,6 +7,7 @@ def test_download_course(): + """Video downloader script for sites that store mp4 urls in html.""" course = 'selenium-webdriver-java-dlya-nachinayushchih' if not os.path.exists(course): os.makedirs(course) @@ -26,7 +27,8 @@ def test_download_course(): logging.info(f'start download {content_url}') with open(course + '/' + content_url.split('.net/')[1].replace('/', '.'), 'wb') as file: - for chunk in requests.get(url=content_url, stream=True).iter_content(chunk_size=1024 * 1024): + for chunk in requests.get(url=content_url, + stream=True).iter_content(chunk_size=1024 * 1024): if chunk: file.write(chunk) @@ -34,6 +36,7 @@ def test_download_course(): def test_leave_last_two_dots_part_of_filename(): + """File renaming script for list of files in directory.""" path = os.getcwd() + '/selenium-webdriver-java-dlya-nachinayushchih/' for _, filename in enumerate(os.listdir(path)): os.rename(