Add tests for BaseSession and TelegramAPIServer

This commit is contained in:
Alex Root Junior 2019-11-16 00:52:18 +02:00
parent c824b298c9
commit a24708d589
12 changed files with 159 additions and 9 deletions

View file

@ -2,7 +2,7 @@ import abc
import asyncio import asyncio
import datetime import datetime
import json import json
from typing import Any, Callable, Dict, List, Optional, TypeVar, Union from typing import Any, Callable, Optional, TypeVar, Union
from pydantic.dataclasses import dataclass from pydantic.dataclasses import dataclass
@ -76,13 +76,13 @@ class BaseSession(abc.ABC):
return self.json_dumps(self.clean_json(value)) return self.json_dumps(self.clean_json(value))
if isinstance(value, datetime.timedelta): if isinstance(value, datetime.timedelta):
now = datetime.datetime.now() now = datetime.datetime.now()
return int((now + value).timestamp()) return str(round((now + value).timestamp()))
if isinstance(value, datetime.datetime): if isinstance(value, datetime.datetime):
return round(value.timestamp()) return str(round(value.timestamp()))
else: else:
return str(value) return str(value)
def clean_json(self, value: Union[List, Dict]): def clean_json(self, value: Any):
if isinstance(value, list): if isinstance(value, list):
return [self.clean_json(v) for v in value if v is not None] return [self.clean_json(v) for v in value if v is not None]
elif isinstance(value, dict): elif isinstance(value, dict):

51
poetry.lock generated
View file

@ -49,6 +49,14 @@ optional = false
python-versions = ">=3.5.3" python-versions = ">=3.5.3"
version = "3.0.1" version = "3.0.1"
[[package]]
category = "dev"
description = "Enhance the standard unittest package with features for testing asyncio libraries"
name = "asynctest"
optional = false
python-versions = ">=3.5"
version = "0.13.0"
[[package]] [[package]]
category = "main" category = "main"
description = "Atomic file writes." description = "Atomic file writes."
@ -109,7 +117,7 @@ version = "7.0"
[[package]] [[package]]
category = "main" category = "main"
description = "Cross-platform colored terminal text." description = "Cross-platform colored terminal text."
marker = "sys_platform == \"win32\"" marker = "python_version >= \"3.5\" and sys_platform == \"win32\" or sys_platform == \"win32\""
name = "colorama" name = "colorama"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
@ -164,7 +172,7 @@ version = "2.8"
[[package]] [[package]]
category = "main" category = "main"
description = "Read metadata from Python packages" description = "Read metadata from Python packages"
marker = "python_version < \"3.8\"" marker = "python_version >= \"3.5\" and python_version < \"3.8\" or python_version < \"3.8\""
name = "importlib-metadata" name = "importlib-metadata"
optional = false optional = false
python-versions = ">=2.7,!=3.0,!=3.1,!=3.2,!=3.3" python-versions = ">=2.7,!=3.0,!=3.1,!=3.2,!=3.3"
@ -457,6 +465,38 @@ version = "2.8.1"
coverage = ">=4.4" coverage = ">=4.4"
pytest = ">=3.6" pytest = ">=3.6"
[[package]]
category = "main"
description = "Thin-wrapper around the mock package for easier use with py.test"
name = "pytest-mock"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.11.2"
[package.dependencies]
pytest = ">=2.7"
[[package]]
category = "dev"
description = "Mypy static type checker plugin for Pytest"
name = "pytest-mypy"
optional = false
python-versions = "~=3.4"
version = "0.4.2"
[package.dependencies]
[[package.dependencies.mypy]]
python = ">=3.5,<3.8"
version = ">=0.500"
[[package.dependencies.mypy]]
python = ">=3.8"
version = ">=0.700"
[package.dependencies.pytest]
python = ">=3.5"
version = ">=2.8"
[[package]] [[package]]
category = "main" category = "main"
description = "World timezone definitions, modern and historical" description = "World timezone definitions, modern and historical"
@ -544,7 +584,7 @@ multidict = ">=4.0"
[[package]] [[package]]
category = "main" category = "main"
description = "Backport of pathlib-compatible object wrapper for zip files" description = "Backport of pathlib-compatible object wrapper for zip files"
marker = "python_version < \"3.8\"" marker = "python_version >= \"3.5\" and python_version < \"3.8\" or python_version < \"3.8\""
name = "zipp" name = "zipp"
optional = false optional = false
python-versions = ">=2.7" python-versions = ">=2.7"
@ -554,7 +594,7 @@ version = "0.6.0"
more-itertools = "*" more-itertools = "*"
[metadata] [metadata]
content-hash = "5252c850bdd8bc1c88cfb7aedc2ce27896fc06310a0ecf6674548702051cadcc" content-hash = "36e7679dedd3bcc50c24575b35da90a64bd33ef54d7862db94159dfc7ecaf28a"
python-versions = "^3.7" python-versions = "^3.7"
[metadata.hashes] [metadata.hashes]
@ -563,6 +603,7 @@ aiohttp = ["1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e", "
appdirs = ["9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", "d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"] appdirs = ["9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", "d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"]
aresponses = ["d1d6ef52b9a97142d106688cf9b112602ef3dc66f6368de8f91f47241d8cfc9c", "f62bcdd739612b6254dd552467b5897a81dcf785e4bb48463bf71e40df398580"] aresponses = ["d1d6ef52b9a97142d106688cf9b112602ef3dc66f6368de8f91f47241d8cfc9c", "f62bcdd739612b6254dd552467b5897a81dcf785e4bb48463bf71e40df398580"]
async-timeout = ["0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f", "4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"] async-timeout = ["0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f", "4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"]
asynctest = ["5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676", "c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"]
atomicwrites = ["03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", "75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"] atomicwrites = ["03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", "75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"]
attrs = ["08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", "f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"] attrs = ["08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", "f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"]
babel = ["af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab", "e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28"] babel = ["af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab", "e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28"]
@ -603,6 +644,8 @@ pyparsing = ["20f995ecd72f2a1f4bf6b072b63b22e2eb457836601e76d6e5dfcd75436acc1f",
pytest = ["15837d2880cb94821087bc07476892ea740696b20e90288fd6c19e44b435abdb", "b6cf7ad9064049ee486586b3a0ddd70dc5136c40e1147e7d286efd77ba66c5eb"] pytest = ["15837d2880cb94821087bc07476892ea740696b20e90288fd6c19e44b435abdb", "b6cf7ad9064049ee486586b3a0ddd70dc5136c40e1147e7d286efd77ba66c5eb"]
pytest-asyncio = ["9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf", "d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b"] pytest-asyncio = ["9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf", "d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b"]
pytest-cov = ["cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b", "cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626"] pytest-cov = ["cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b", "cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626"]
pytest-mock = ["b3514caac35fe3f05555923eabd9546abce11571cc2ddf7d8615959d04f2c89e", "ea502c3891599c26243a3a847ccf0b1d20556678c528f86c98e3cd6d40c5cf11"]
pytest-mypy = ["3b7b56912d55439d5f447cc609f91caac7f74f0f1c89f1379d04f06bac777c32", "5a5338cecff17f005b181546a13e282761754b481225df37f33d37f86ac5b304"]
pytz = ["1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", "b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"] pytz = ["1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", "b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"]
pyyaml = ["0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9", "01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4", "5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8", "5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696", "7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34", "7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9", "87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73", "9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299", "a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b", "b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae", "b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681", "bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41", "f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8"] pyyaml = ["0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9", "01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4", "5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8", "5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696", "7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34", "7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9", "87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73", "9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299", "a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b", "b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae", "b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681", "bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41", "f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8"]
six = ["1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", "30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"] six = ["1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", "30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"]

View file

@ -16,6 +16,7 @@ pydantic = "^1.1"
Babel = "^2.7" Babel = "^2.7"
pytest-cov = "^2.8" pytest-cov = "^2.8"
aiofiles = "^0.4.0" aiofiles = "^0.4.0"
pytest-mock = "^1.11"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
black = {version = "^18.3-alpha.0", allows-prereleases = true} black = {version = "^18.3-alpha.0", allows-prereleases = true}
@ -30,6 +31,8 @@ mkdocs = "^1.0"
mkdocs-material = "^4.4" mkdocs-material = "^4.4"
pygments = "^2.4" pygments = "^2.4"
pymdown-extensions = "^6.1" pymdown-extensions = "^6.1"
pytest-mypy = "^0.4.2"
asynctest = "^0.13.0"
[tool.black] [tool.black]
line-length = 99 line-length = 99

View file

View file

View file

View file

View file

@ -0,0 +1,11 @@
from aiogram.api.session.base import PRODUCTION
class TestAPIServer:
def test_method_url(self):
method_url = PRODUCTION.api_url(token="TOKEN", method="apiMethod")
assert method_url == "https://api.telegram.org/botTOKEN/apiMethod"
def test_file_url(self):
file_url = PRODUCTION.file_url(token="TOKEN", path="path")
assert file_url == "https://api.telegram.org/file/botTOKEN/path"

View file

@ -0,0 +1,89 @@
import datetime
from unittest.mock import patch
import pytest
from asynctest import CoroutineMock
from aiogram.api.session.base import BaseSession
from aiogram.utils.mixins import DataMixin
class TestBaseSession(DataMixin):
def setup(self):
self["__abstractmethods__"] = BaseSession.__abstractmethods__
BaseSession.__abstractmethods__ = set()
def teardown(self):
BaseSession.__abstractmethods__ = self["__abstractmethods__"]
def test_sync_close(self):
session = BaseSession()
with patch(
"aiogram.api.session.base.BaseSession.close", new=CoroutineMock()
) as mocked_close:
session.__del__()
mocked_close.assert_called_once_with()
@pytest.mark.asyncio
async def test_async_close(self):
session = BaseSession()
with patch(
"aiogram.api.session.base.BaseSession.close", new=CoroutineMock()
) as mocked_close:
session.__del__()
mocked_close.assert_called_once_with()
def test_prepare_value(self):
session = BaseSession()
now = datetime.datetime(
year=2019, month=11, day=15, hour=12, minute=42, second=15, microsecond=0
)
assert session.prepare_value("text") == "text"
assert session.prepare_value(["test"]) == '["test"]'
assert session.prepare_value({"test": "ok"}) == '{"test": "ok"}'
assert session.prepare_value(now) == "1573814535"
assert isinstance(session.prepare_value(datetime.timedelta(minutes=2)), str)
assert session.prepare_value(42) == "42"
def test_clean_json(self):
session = BaseSession()
cleaned_dict = session.clean_json({"key": "value", "null": None})
assert "key" in cleaned_dict
assert "null" not in cleaned_dict
cleaned_list = session.clean_json(["kaboom", 42, None])
assert len(cleaned_list) == 2
assert 42 in cleaned_list
assert None not in cleaned_list
assert cleaned_list[0] == "kaboom"
def test_clean_json_with_nested_json(self):
session = BaseSession()
cleaned = session.clean_json(
{
"key": "value",
"null": None,
"nested_list": ["kaboom", 42, None],
"nested_dict": {"key": "value", "null": None},
}
)
assert len(cleaned) == 3
assert "null" not in cleaned
assert isinstance(cleaned["nested_list"], list)
assert cleaned["nested_list"] == ["kaboom", 42]
assert isinstance(cleaned["nested_dict"], dict)
assert cleaned["nested_dict"] == {"key": "value"}
def test_clean_json_not_json(self):
session = BaseSession()
assert session.clean_json(42) == 42

View file

View file

@ -1,4 +1,5 @@
import pytest import pytest
from aiogram.utils.helper import Helper, HelperMode, Item, ListItem, OrderedHelper from aiogram.utils.helper import Helper, HelperMode, Item, ListItem, OrderedHelper

View file

@ -1,4 +1,5 @@
import pytest import pytest
from aiogram.utils.mixins import ContextInstanceMixin, DataMixin from aiogram.utils.mixins import ContextInstanceMixin, DataMixin
@ -47,5 +48,7 @@ class TestContextInstanceMixin:
def test_set_wrong_type(self): def test_set_wrong_type(self):
obj = ContextObject() obj = ContextObject()
with pytest.raises(TypeError, match=r"Value should be instance of 'ContextObject' not '.+'"): with pytest.raises(
TypeError, match=r"Value should be instance of 'ContextObject' not '.+'"
):
obj.set_current(42) obj.set_current(42)