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. 43
      tests/test_innodrive.py
  11. 108
      tests/test_taskManager.py

1
.gitignore vendored

@ -159,3 +159,4 @@ cython_debug/ @@ -159,3 +159,4 @@ cython_debug/
# 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.
#.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 _ @@ -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)_:
> **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

1
XXtasks.jsonXX

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

198
poetry.lock

@ -1,5 +1,57 @@ @@ -1,5 +1,57 @@
# 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]]
name = "click"
version = "8.1.7"
@ -49,6 +101,106 @@ files = [ @@ -49,6 +101,106 @@ files = [
{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]]
name = "iniconfig"
version = "2.0.0"
@ -60,6 +212,17 @@ files = [ @@ -60,6 +212,17 @@ files = [
{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]]
name = "junit-xml"
version = "1.9"
@ -182,6 +345,28 @@ files = [ @@ -182,6 +345,28 @@ files = [
{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]]
name = "toml"
version = "0.10.2"
@ -204,7 +389,18 @@ files = [ @@ -204,7 +389,18 @@ files = [
{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]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "70b7ed10eaec95d513d38cbc8a5fa85d983896f9a4da435cca741f5ba87ad3f7"
content-hash = "21ed902c2e010c3dc54b8152229a7fa8be691c7e362590df7db74f64655b91c2"

3
pyproject.toml

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

2
taskManager/task.py

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

32
taskManager/taskManager.py

@ -3,39 +3,43 @@ from .task import Task @@ -3,39 +3,43 @@ from .task import Task
class TaskManager:
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()
def add_task(self, task_text, priority, due_date):
task = Task(task_text, priority, due_date)
self.tasks.append(task)
print("Task added successfully!")
print("Task added successfully!") # pragma: no mutate
def remove_task(self, task_index):
if 0 <= task_index < len(self.tasks):
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:
print("Invalid task number!")
print("Invalid task number!") # pragma: no mutate
def complete_task(self, task_index):
if 0 <= task_index < len(self.tasks):
self.tasks[task_index].mark_completed()
print("Task marked as completed!")
print("Task marked as completed!") # pragma: no mutate
else:
print("Invalid task number!")
print("Invalid task number!") # pragma: no mutate
def list_tasks(self):
if not self.tasks:
print("No tasks found.")
print("No tasks found.") # pragma: no mutate
else:
print("\nTask List:")
for i, task in enumerate(self.tasks, start=1):
status = "Completed" if task.completed else "Not Completed"
print(f"{i}. Task: {task.task_text}")
print(f" Priority: {task.priority}")
print(f" Due Date: {task.due_date}")
print(f" Status: {status}\n")
print("\nTask List:") # pragma: no mutate
for i, task in enumerate(self.tasks, start=1): # pragma: no mutate
status = "Completed" if task.completed else "Not Completed" # pragma: no mutate
print(f"{i}. Task: {task.task_text}") # pragma: no mutate
print(f" Priority: {task.priority}") # pragma: no mutate
print(f" Due Date: {task.due_date}") # pragma: no mutate
print(f" Status: {status}\n") # pragma: no mutate
def save_tasks(self):
with open("tasks.json", "w") as file:

1
tasks.json

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

43
tests/test_innodrive.py

@ -2,17 +2,56 @@ @@ -2,17 +2,56 @@
import pytest
from hypothesis import given
import json
import hypothesis.strategies as st
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")
def test_app():
client = Client(base_url="https://instructors.pg.innopolis.university/innodrive/")
yield client # testing happens here
@pytest.mark.parametrize("email", ["i.ivanov@innopolis.university"])
@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
@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 @@ -5,3 +5,111 @@ import pytest
from taskManager.taskManager import TaskManager
from taskManager.task import Task
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