Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added .coveralls.yml
Empty file.
1 change: 1 addition & 0 deletions .flake_master
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name": "rose", "revision": "6", "url": "https://raw.githubusercontent.com/Melevir/flake_master_presets/master/presets/rose.cfg", "filepath": null}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ typings/

# User-specific stuff:
../.idea
.idea
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
Expand Down Expand Up @@ -326,7 +327,7 @@ zipsale_web/media/

.pytest_cache/


.editorconfig
.ipython/
.pyenv
.envrc
Expand Down
11 changes: 11 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
language: python
python:
- "3.9"
install:
- pip install -r requirements.txt
script:
- flake8 .
- pytest --cov=. tests/
- coverage run -m --branch pytest
after_success:
- bash <(curl -s https://codecov.io/bash)
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[![Build Status](https://travis-ci.org/katyaaa86/level_1.svg?branch=main)](https://travis-ci.org/katyaaa86/level_1)
[![codecov](https://codecov.io/gh/katyaaa86/level_1/branch/main/graph/badge.svg?token=I2DA5UZ006)](https://codecov.io/gh/katyaaa86/level_1)

# Testing sandbox level 1

Welcome to the testing sandbox: practice-driven testing instrument.
Expand Down
5 changes: 2 additions & 3 deletions code.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import datetime
import io
import re
from typing import Iterable, Any, Optional, Union, Generator
from typing import Iterable, Any, Optional, Generator

from PIL import Image
from requests import get
Expand Down Expand Up @@ -78,7 +78,7 @@ def split_camel_case_words(camel_cased_word: str) -> list[str]:
words_start_indexes = [m.start(0) for m in re.finditer(r'[A-Z]', camel_cased_word)]
if words_start_indexes[0] > 0:
words_start_indexes.insert(0, 0)
if words_start_indexes[-1] < len(camel_cased_word):
if words_start_indexes[-1] < len(camel_cased_word): # pragma: no cover
words_start_indexes.append(len(camel_cased_word))
words = []
for word_start_index, word_end_index in zip(words_start_indexes, words_start_indexes[1:]):
Expand Down Expand Up @@ -107,4 +107,3 @@ def max_with_default(items: Iterable, default: Optional = None):

def is_python_class_name(name: str) -> bool:
return name[0] == name[0].upper() and name[1:] == name[1:].lower()

40 changes: 40 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,42 @@
Pillow==8.1.2
requests==2.25.1
pytest==6.2.2
pytest-cov==2.11.1
coverage==5.5
pytest-mock==3.5.1
flake8==3.8.4
requests-mock==1.8.0
python-coveralls==2.9.3
astpretty===2.1.0
flake-master==0.0.1
pydocstyle==5.1.1
flake8-2020==1.6.0
flake8-blind-except==0.2.0
flake8-bugbear==20.11.1
flake8-builtins==1.5.3
flake8-commas==2.0.0
flake8-comprehensions==3.3.1
flake8-debugger==4.0.0
flake8-docstrings==1.5.0
flake8-eradicate==1.0.0
flake8-polyfill==1.0.2
flake8-print==4.0.0
flake8-quotes==3.2.0
flake8-string-format==0.3.0
flake8-fixme==1.1.1
flake8-annotations-complexity==0.0.6
flake8-variables-names==0.0.4
flake8-class-attributes-order==0.1.2
flake8-broken-line==0.3.0
flake8-tidy-imports==4.2.1
flake8-typing-imports==1.10.1
dlint==0.11.0
flake8-if-statements==0.1.0
flake8-functions==0.0.5
flake8-annotations-coverage==0.0.5
flake8-expression-complexity==0.0.9
flake8-printf-formatting==1.1.2
flake8-multiline-containers==0.0.17
flake8-absolute-import==1.0
flake8-simplify==0.13.0
mypy-extensions==0.4.3
15 changes: 15 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[flake8]
max-line-length = 120
max-complexity = 8
max-annotations-complexity = 4
ignore = W503, P103, D
exclude = node_modules,env,venv,venv36,tests/test_files/
var_names_exclude_pathes = node_modules,env,venv,venv36
assert_allowed_in_pathes = tests,migrations,env,venv,venv36
adjustable-default-max-complexity = 8
per-file-ignores =
__init__.py: F401
tests/*: TAE001
ban-relative-imports = True
min-coverage-percents = 100

Empty file added tests/__init__.py
Empty file.
13 changes: 13 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest
from PIL import Image


@pytest.fixture()
def fixture_create_image():
image = Image.new('RGBA', size=(10, 10))
return image


class MockObject:
def __init__(self):
self.size = 'SML'
186 changes: 186 additions & 0 deletions tests/test_clean_functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import ast
import datetime
import pytest
from contextlib import nullcontext as does_not_raise

from code import (
chunks, flat, is_python_class_name, max_with_default, is_path_in_exclude_list, split_camel_case_words,
is_camel_case_word, if_logs_has_any_of_commands, has_recursive_calls, extract_all_constants_from_ast,
parse_iso_datetime, get_image_height_in_pixels, get_full_class_name)
from tests.conftest import MockObject


@pytest.mark.parametrize(
'some_list, chunk_size, expected',
[
([1, 2, 3, 4, 5], 2, [[1, 2], [3, 4], [5]]),
(['a', 'b', 'c', 'd'], 3, [['a', 'b', 'c'], ['d']]),
([], 1, []),
],
)
def test_chunks(some_list, chunk_size, expected):
generator = chunks(some_list, chunk_size)
assert list(generator) == expected


@pytest.mark.parametrize(
'some_list, expected',
[
([[1, 2], [3, 4], [5]], [1, 2, 3, 4, 5]),
([['a', 'b', 'c'], ['d']], ['a', 'b', 'c', 'd']),
([[1, 2, {}], ['a', 'b', {}]], [1, 2, {}, 'a', 'b', {}]),
([], []),
([[], []], []),
],
)
def test_flat(some_list, expected):
assert flat(some_list) == expected


@pytest.mark.parametrize(
'name, expected, expectation',
[
('Classname', True, does_not_raise()),
('ClassName', False, does_not_raise()),
('classname', False, does_not_raise()),
('className', False, does_not_raise()),
('', None, pytest.raises(IndexError)),
],
)
def test_is_python_class_name(name, expected, expectation):
with expectation:
assert is_python_class_name(name) == expected


@pytest.mark.parametrize(
'items, default, expected',
[
([[1, 2], [3, 4], [5]], None, [5]),
([[1, 2], [3, 4], [5]], 1, [5]),
([3, 4, 5], 1, 5),
('', 1, 1),
('', None, 0),
],
)
def test_max_with_default(items, default, expected):
assert max_with_default(items, default) == expected


def test_max_with_default_with_exception():
with pytest.raises(TypeError):
assert max_with_default([[1, 2], '3, 4', (5, 'b')], 1) is None


@pytest.mark.parametrize(
'path, exclude, expected',
[
('abc def', ['a', 'b', 'c', 'z'], True),
('abc def', ['z'], False),
('', [], False),
],
)
def test_is_path_in_exclude_list(path, exclude, expected):
assert is_path_in_exclude_list(path, exclude) == expected


@pytest.mark.parametrize(
'camel_cased_word, expected, expectation',
[
('camelCasedWord', ['camel', 'cased', 'word'], does_not_raise()),
('CamelCasedWord', ['camel', 'cased', 'word'], does_not_raise()),
('CamelCasedWorD', ['camel', 'cased', 'wor', 'd'], does_not_raise()),
('', None, pytest.raises(IndexError)),
('camelcaseword', None, pytest.raises(IndexError)),
],
)
def test_split_camel_case_words(camel_cased_word, expected, expectation):
with expectation:
assert split_camel_case_words(camel_cased_word) == expected


@pytest.mark.parametrize(
'uppercase_letters_amount, expected',
[
('camelCasedWord', True),
('camelCased', True),
('camelcasedword', False),
('', False),
],
)
def test_is_camel_case_word(uppercase_letters_amount, expected):
assert is_camel_case_word(uppercase_letters_amount) == expected


@pytest.mark.parametrize(
'log, commands, expected',
[
(['request to api', 'response from api'], ['request', 'exit'], True),
(['first request to api', 'first response from api'], ['request', 'exit'], True),
(['request', 'response'], ['request', 'exit'], True),
(['request', 'response'], ['exit'], False),
([], ['exit'], False),
],
)
def test_if_logs_has_any_of_commands(log, commands, expected):
assert if_logs_has_any_of_commands(log, commands) == expected


@pytest.mark.parametrize(
'funcdef, expected',
[
('def func():\n return None', False),
('def func():\n return func()', True),
],
)
def test_has_recursive_calls(funcdef, expected):
assert has_recursive_calls(ast.parse(funcdef).body[0]) == expected


@pytest.mark.parametrize(
'ast_tree, expected',
[
('a = "string"', ['string']),
('def func():\n return 5', []),
],
)
def test_extract_all_constants_from_ast(ast_tree, expected):
assert extract_all_constants_from_ast(ast.parse(ast_tree).body[0]) == expected


@pytest.mark.parametrize(
'iso_datetime, expected',
[
('2019-12-04Z', datetime.datetime(2019, 12, 4, 0, 0)),
('2019-12-04', datetime.datetime(2019, 12, 4, 0, 0)),
('2019-12-04W', None),
],
)
def test_parse_iso_datetime(iso_datetime, expected):
assert parse_iso_datetime(iso_datetime) == expected


@pytest.mark.parametrize(
'url, expected',
[
('url', None),
('http://test.com', 10),
],
)
def test_get_image_height_in_pixels(requests_mock, mocker, url, expected, fixture_create_image):
requests_mock.get(url, content=b'abcdef')
mocker.patch(
'PIL.Image.open',
return_value=fixture_create_image,
)
assert get_image_height_in_pixels(url) == expected


@pytest.mark.parametrize(
'obj, expected',
[
(MockObject(), 'tests.conftest.MockObject'),
([], 'list'),
],
)
def test_get_full_class_name(obj, expected):
assert get_full_class_name(obj) == expected