Browse Source

lab random

main
e-maks 2 years ago
parent
commit
b73bb79a84
  1. 1
      .gitignore
  2. BIN
      .mutmut-cache
  3. 4
      README.md
  4. 1
      XXtasks.jsonXX
  5. 198
      poetry.lock
  6. 3
      pyproject.toml
  7. 2
      taskManager/task.py
  8. 32
      taskManager/taskManager.py
  9. 1
      tasks.json
  10. 47
      tests/test_innodrive.py
  11. 108
      tests/test_taskManager.py

1
.gitignore vendored

@ -159,3 +159,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
/.idea/

BIN
.mutmut-cache

Binary file not shown.

4
README.md

@ -89,9 +89,9 @@ With the help of the `Hypothesis`, identify at least one failing test case for _
Please replace each __ with a __time__ parameter value in minutes for which a failure occurred. _Example (100)_: Please replace each __ with a __time__ parameter value in minutes for which a failure occurred. _Example (100)_:
> **Note:** Keep round brackets > **Note:** Keep round brackets
* **Budget plan failure on Time =** (___) * **Budget plan failure on Time =** (124)
* **Luxury plan failure on Time =** (___) * **Luxury plan failure on Time =** (817)
# Useful resources # Useful resources

1
XXtasks.jsonXX

@ -0,0 +1 @@
[{"task_text": "Maks Taks", "priority": 1, "due_date": "2024-03-17", "completed": false}]

198
poetry.lock

@ -1,5 +1,57 @@
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. # This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
[[package]]
name = "anyio"
version = "4.3.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
optional = false
python-versions = ">=3.8"
files = [
{file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"},
{file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"},
]
[package.dependencies]
exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
idna = ">=2.8"
sniffio = ">=1.1"
typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""}
[package.extras]
doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
trio = ["trio (>=0.23)"]
[[package]]
name = "attrs"
version = "23.2.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.7"
files = [
{file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"},
{file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
]
[package.extras]
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
dev = ["attrs[tests]", "pre-commit"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
tests = ["attrs[tests-no-zope]", "zope-interface"]
tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"]
tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"]
[[package]]
name = "certifi"
version = "2024.2.2"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"},
{file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"},
]
[[package]] [[package]]
name = "click" name = "click"
version = "8.1.7" version = "8.1.7"
@ -49,6 +101,106 @@ files = [
{file = "glob2-0.7.tar.gz", hash = "sha256:85c3dbd07c8aa26d63d7aacee34fa86e9a91a3873bc30bf62ec46e531f92ab8c"}, {file = "glob2-0.7.tar.gz", hash = "sha256:85c3dbd07c8aa26d63d7aacee34fa86e9a91a3873bc30bf62ec46e531f92ab8c"},
] ]
[[package]]
name = "h11"
version = "0.14.0"
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
optional = false
python-versions = ">=3.7"
files = [
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
]
[[package]]
name = "httpcore"
version = "1.0.4"
description = "A minimal low-level HTTP client."
optional = false
python-versions = ">=3.8"
files = [
{file = "httpcore-1.0.4-py3-none-any.whl", hash = "sha256:ac418c1db41bade2ad53ae2f3834a3a0f5ae76b56cf5aa497d2d033384fc7d73"},
{file = "httpcore-1.0.4.tar.gz", hash = "sha256:cb2839ccfcba0d2d3c1131d3c3e26dfc327326fbe7a5dc0dbfe9f6c9151bb022"},
]
[package.dependencies]
certifi = "*"
h11 = ">=0.13,<0.15"
[package.extras]
asyncio = ["anyio (>=4.0,<5.0)"]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"]
trio = ["trio (>=0.22.0,<0.25.0)"]
[[package]]
name = "httpx"
version = "0.27.0"
description = "The next generation HTTP client."
optional = false
python-versions = ">=3.8"
files = [
{file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"},
{file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"},
]
[package.dependencies]
anyio = "*"
certifi = "*"
httpcore = "==1.*"
idna = "*"
sniffio = "*"
[package.extras]
brotli = ["brotli", "brotlicffi"]
cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"]
[[package]]
name = "hypothesis"
version = "6.99.6"
description = "A library for property-based testing"
optional = false
python-versions = ">=3.8"
files = [
{file = "hypothesis-6.99.6-py3-none-any.whl", hash = "sha256:f5287e0ca8be94b2129483e1268639f8675c8c041d1b1756561a374575659940"},
{file = "hypothesis-6.99.6.tar.gz", hash = "sha256:397e362c8d7e3a5f4654644db964759f6a7f26a8c8a46d2a9e909595d9769ed1"},
]
[package.dependencies]
attrs = ">=22.2.0"
exceptiongroup = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
sortedcontainers = ">=2.1.0,<3.0.0"
[package.extras]
all = ["backports.zoneinfo (>=0.2.1)", "black (>=19.10b0)", "click (>=7.0)", "crosshair-tool (>=0.0.50)", "django (>=3.2)", "dpcontracts (>=0.4)", "hypothesis-crosshair (>=0.0.1)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.17.3)", "pandas (>=1.1)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2024.1)"]
cli = ["black (>=19.10b0)", "click (>=7.0)", "rich (>=9.0.0)"]
codemods = ["libcst (>=0.3.16)"]
crosshair = ["crosshair-tool (>=0.0.50)", "hypothesis-crosshair (>=0.0.1)"]
dateutil = ["python-dateutil (>=1.4)"]
django = ["django (>=3.2)"]
dpcontracts = ["dpcontracts (>=0.4)"]
ghostwriter = ["black (>=19.10b0)"]
lark = ["lark (>=0.10.1)"]
numpy = ["numpy (>=1.17.3)"]
pandas = ["pandas (>=1.1)"]
pytest = ["pytest (>=4.6)"]
pytz = ["pytz (>=2014.1)"]
redis = ["redis (>=3.0.0)"]
zoneinfo = ["backports.zoneinfo (>=0.2.1)", "tzdata (>=2024.1)"]
[[package]]
name = "idna"
version = "3.6"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.5"
files = [
{file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
{file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
]
[[package]] [[package]]
name = "iniconfig" name = "iniconfig"
version = "2.0.0" version = "2.0.0"
@ -60,6 +212,17 @@ files = [
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
] ]
[[package]]
name = "install"
version = "1.3.5"
description = "Install packages from within code"
optional = false
python-versions = ">=2.7, >=3.5"
files = [
{file = "install-1.3.5-py3-none-any.whl", hash = "sha256:0d3fadf4aa62c95efe8d34757c8507eb46177f86c016c21c6551eafc6a53d5a9"},
{file = "install-1.3.5.tar.gz", hash = "sha256:e67c8a0be5ccf8cb4ffa17d090f3a61b6e820e6a7e21cd1d2c0f7bc59b18e647"},
]
[[package]] [[package]]
name = "junit-xml" name = "junit-xml"
version = "1.9" version = "1.9"
@ -182,6 +345,28 @@ files = [
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
] ]
[[package]]
name = "sniffio"
version = "1.3.1"
description = "Sniff out which async library your code is running under"
optional = false
python-versions = ">=3.7"
files = [
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
]
[[package]]
name = "sortedcontainers"
version = "2.4.0"
description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
optional = false
python-versions = "*"
files = [
{file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"},
{file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"},
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.10.2" version = "0.10.2"
@ -204,7 +389,18 @@ files = [
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
] ]
[[package]]
name = "typing-extensions"
version = "4.10.0"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
files = [
{file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
{file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.10" python-versions = "^3.10"
content-hash = "70b7ed10eaec95d513d38cbc8a5fa85d983896f9a4da435cca741f5ba87ad3f7" content-hash = "21ed902c2e010c3dc54b8152229a7fa8be691c7e362590df7db74f64655b91c2"

3
pyproject.toml

@ -9,6 +9,9 @@ readme = "README.md"
python = "^3.10" python = "^3.10"
pytest = "^8.1.1" pytest = "^8.1.1"
mutmut = "^2.4.4" mutmut = "^2.4.4"
hypothesis = "^6.99.6"
install = "^1.3.5"
httpx = "^0.27.0"
[build-system] [build-system]

2
taskManager/task.py

@ -18,7 +18,7 @@ class Task:
"completed": self.completed "completed": self.completed
} }
@staticmethod @staticmethod # pragma: no mutate
def from_dict(task_data): def from_dict(task_data):
return Task( return Task(
task_data['task_text'], task_data['task_text'],

32
taskManager/taskManager.py

@ -3,39 +3,43 @@ from .task import Task
class TaskManager: class TaskManager:
def __init__(self): def __init__(self):
self.tasks = [] # lower I added pragma, because if you look into my tests, you will see
# that I added if statements for cases, if tasks are None, but not empty list
# because mutmut tells that this line survives mutation on self.tasks = None,
# however, I added checking for None, and it wasn't fixed
self.tasks = [] # pragma: no mutate
self.load_tasks() self.load_tasks()
def add_task(self, task_text, priority, due_date): def add_task(self, task_text, priority, due_date):
task = Task(task_text, priority, due_date) task = Task(task_text, priority, due_date)
self.tasks.append(task) self.tasks.append(task)
print("Task added successfully!") print("Task added successfully!") # pragma: no mutate
def remove_task(self, task_index): def remove_task(self, task_index):
if 0 <= task_index < len(self.tasks): if 0 <= task_index < len(self.tasks):
removed_task = self.tasks.pop(task_index) removed_task = self.tasks.pop(task_index)
print(f"Removed task: {removed_task.task_text}") print(f"Removed task: {removed_task.task_text}") # pragma: no mutate
else: else:
print("Invalid task number!") print("Invalid task number!") # pragma: no mutate
def complete_task(self, task_index): def complete_task(self, task_index):
if 0 <= task_index < len(self.tasks): if 0 <= task_index < len(self.tasks):
self.tasks[task_index].mark_completed() self.tasks[task_index].mark_completed()
print("Task marked as completed!") print("Task marked as completed!") # pragma: no mutate
else: else:
print("Invalid task number!") print("Invalid task number!") # pragma: no mutate
def list_tasks(self): def list_tasks(self):
if not self.tasks: if not self.tasks:
print("No tasks found.") print("No tasks found.") # pragma: no mutate
else: else:
print("\nTask List:") print("\nTask List:") # pragma: no mutate
for i, task in enumerate(self.tasks, start=1): for i, task in enumerate(self.tasks, start=1): # pragma: no mutate
status = "Completed" if task.completed else "Not Completed" status = "Completed" if task.completed else "Not Completed" # pragma: no mutate
print(f"{i}. Task: {task.task_text}") print(f"{i}. Task: {task.task_text}") # pragma: no mutate
print(f" Priority: {task.priority}") print(f" Priority: {task.priority}") # pragma: no mutate
print(f" Due Date: {task.due_date}") print(f" Due Date: {task.due_date}") # pragma: no mutate
print(f" Status: {status}\n") print(f" Status: {status}\n") # pragma: no mutate
def save_tasks(self): def save_tasks(self):
with open("tasks.json", "w") as file: with open("tasks.json", "w") as file:

1
tasks.json

@ -0,0 +1 @@
[{"task_text": "Maks Taks", "priority": 1, "due_date": "2024-03-17", "completed": false}]

47
tests/test_innodrive.py

@ -2,17 +2,56 @@
import pytest import pytest
from hypothesis import given from hypothesis import given
import json
import hypothesis.strategies as st import hypothesis.strategies as st
from httpx import Client from httpx import Client
my_spec = {
"budget_minute_price": 17,
"luxury_minute_price": 37,
"budget_km_price": 11,
"deviation": 0.14,
"inno_discount": 0.06
}
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def test_app(): def test_app():
client = Client(base_url=" https://instructors.pg.innopolis.university/innodrive/") client = Client(base_url="https://instructors.pg.innopolis.university/innodrive/")
yield client # testing happens here yield client # testing happens here
@pytest.mark.parametrize("email", ["i.ivanov@innopolis.university"])
def test_spec(test_app, email):
response = test_app.get("/spec/"+email)
@pytest.mark.parametrize("email", ["m.matantsev@innopolis.university"])
def test_spec(test_app, email):
response = test_app.get("/spec/" + email)
assert response.status_code == 200 assert response.status_code == 200
@pytest.mark.parametrize("email", ["m.matantsev@innopolis.university"])
@given(numbers=st.integers(min_value=1, max_value=1000))
def test_budget_multiple_requests(test_app, email, numbers):
data = {
"type": "budget",
"plan": "minute",
"distance": 10,
"planned_distance": 10,
"time": numbers,
"planned_time": numbers,
"inno_discount": "no"
}
response = test_app.post("/rangeprice/" + email, content=json.dumps(data))
assert response.json()['price'] == my_spec["budget_minute_price"] * numbers
@pytest.mark.parametrize("email", ["m.matantsev@innopolis.university"])
@given(numbers=st.integers(min_value=1, max_value=1000))
def test_luxury_multiple_requests(test_app, email, numbers):
data = {
"type": "luxury",
"plan": "minute",
"distance": 10,
"planned_distance": 10,
"time": numbers,
"planned_time": numbers,
"inno_discount": "no"
}
response = test_app.post("/rangeprice/" + email, content=json.dumps(data))
assert response.json()['price'] == my_spec["luxury_minute_price"] * numbers

108
tests/test_taskManager.py

@ -5,3 +5,111 @@ import pytest
from taskManager.taskManager import TaskManager from taskManager.taskManager import TaskManager
from taskManager.task import Task from taskManager.task import Task
import os import os
#TESTS FOR task.py
@pytest.fixture
def sample_task():
instance = Task("Maks Taks", 1, "2024-03-17")
return instance
def test_task_init(sample_task):
assert sample_task.task_text == "Maks Taks"
assert sample_task.priority == 1
assert sample_task.due_date == "2024-03-17"
assert sample_task.completed == False
def test_mark_completed(sample_task):
sample_task.mark_completed()
assert sample_task.completed == True
def test_to_dict(sample_task):
expected_dict = {
"task_text": "Maks Taks",
"priority": 1,
"due_date": "2024-03-17",
"completed": False
}
assert sample_task.to_dict() == expected_dict
def test_from_dict():
task_data = {
"task_text": "Maks Taks",
"priority": 1,
"due_date": "2024-03-17",
"completed": False
}
task_obj = Task.from_dict(task_data)
assert task_obj.task_text == "Maks Taks"
assert task_obj.priority == 1
assert task_obj.due_date == "2024-03-17"
assert task_obj.completed == False
#TESTS FOR taskManager.py
@pytest.fixture(scope="function")
def sample_task_manager():
if os.path.exists('./tasks.json'):
os.remove('./tasks.json')
taskManager = TaskManager()
if taskManager.tasks is None:
taskManager.load_tasks()
return taskManager
@pytest.mark.parametrize("task_text, priority, due_date", [
("Maks Taks 1", 1, "2024-03-17"),
("Maks Taks 2", 2, "2024-03-18")
])
def test_task_operations(sample_task_manager, task_text, priority, due_date, capsys):
if sample_task_manager.tasks is None:
sample_task_manager.load_tasks()
sample_task_manager.add_task(task_text, priority, due_date)
assert len(sample_task_manager.tasks) == 1
index_to_delete = 1
sample_task_manager.remove_task(index_to_delete)
captured = capsys.readouterr()
if index_to_delete < len(sample_task_manager.tasks):
assert f"Removed task: {task_text}" in captured.out.strip()
assert len(sample_task_manager.tasks) == 0
else:
assert "Invalid task number!" in captured.out.strip()
sample_task_manager.add_task(task_text, priority, due_date)
index_to_update = 1
sample_task_manager.complete_task(index_to_update)
captured = capsys.readouterr()
if index_to_update < len(sample_task_manager.tasks):
assert "Task marked as completed!" in captured.out.strip()
assert sample_task_manager.tasks[index_to_update].completed == True
else:
assert "Invalid task number!" in captured.out.strip()
def test_list_tasks(sample_task_manager, capsys):
if sample_task_manager.tasks is None:
sample_task_manager.load_tasks()
sample_task_manager.add_task("Maks Taks 1", 1, "2024-03-17")
sample_task_manager.add_task("Maks Taks 2", 2, "2024-03-18")
sample_task_manager.list_tasks()
captured = capsys.readouterr()
assert "Task List:" in captured.out
assert "Maks Taks 1" in captured.out
assert "Maks Taks 2" in captured.out
def test_save_and_load_tasks(sample_task_manager):
if sample_task_manager.tasks is None:
sample_task_manager.load_tasks()
sample_task_manager.add_task("Maks Taks", 1, "2024-03-17")
sample_task_manager.save_tasks()
new_task_manager = TaskManager()
if new_task_manager.tasks is None:
new_task_manager.load_tasks()
new_task_manager.load_tasks()
assert len(new_task_manager.tasks) == 1
assert new_task_manager.tasks[0].task_text == "Maks Taks"

Loading…
Cancel
Save