Skip to content

Commit

Permalink
Add tests (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
da-maltsev authored Jul 6, 2023
1 parent 5662ff8 commit d286e4a
Show file tree
Hide file tree
Showing 17 changed files with 460 additions and 7 deletions.
39 changes: 38 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,46 @@ jobs:
. venv/bin/activate
make lint
build-docker-image:
test:
needs: build
runs-on: ubuntu-latest
services:
postgres:
image: postgres:13.9-alpine
env:
POSTGRES_HOST_AUTH_METHOD: trust
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

steps:
- uses: actions/checkout@v3

- uses: actions/setup-python@v4
id: setup-python
with:
python-version-file: '.python-version'

- uses: actions/cache@v3
with:
path: |
venv
key: ${{ runner.os }}-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/*requirements.txt') }}

- name: Run the tests
env:
DATABASE_URL: postgres://postgres@localhost:5432/postgres
run: |
. venv/bin/activate
make test
build-docker-image:
needs: test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,10 @@ lint:
fmt:
isort .

test:
pytest --dead-fixtures
pytest -x

dev:
watchmedo auto-restart --patterns '*.py' python bot.py

25 changes: 24 additions & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ emoji==1.7.0
eradicate==2.3.0
# via flake8-eradicate
exceptiongroup==1.1.2
# via anyio
# via
# anyio
# pytest
executing==1.2.0
# via stack-data
flake8==6.0.0
Expand Down Expand Up @@ -106,6 +108,8 @@ idna==3.4
# via
# anyio
# httpx
iniconfig==2.0.0
# via pytest
ipython==8.14.0
# via channel-discussion-antispam-bot (pyproject.toml)
isort==5.12.0
Expand All @@ -122,6 +126,8 @@ mypy==1.4.1
# via channel-discussion-antispam-bot (pyproject.toml)
mypy-extensions==1.0.0
# via mypy
packaging==23.1
# via pytest
parso==0.8.3
# via jedi
peewee==3.16.2
Expand All @@ -130,6 +136,8 @@ pexpect==4.8.0
# via ipython
pickleshare==0.7.5
# via ipython
pluggy==1.2.0
# via pytest
prompt-toolkit==3.0.39
# via ipython
psycopg2-binary==2.9.6
Expand All @@ -148,6 +156,20 @@ pyflakes==3.0.1
# via flake8
pygments==2.15.1
# via ipython
pytest==7.4.0
# via
# pytest-deadfixtures
# pytest-env
# pytest-mock
# pytest-randomly
pytest-deadfixtures==2.2.1
# via channel-discussion-antispam-bot (pyproject.toml)
pytest-env==0.8.2
# via channel-discussion-antispam-bot (pyproject.toml)
pytest-mock==3.11.1
# via channel-discussion-antispam-bot (pyproject.toml)
pytest-randomly==3.12.0
# via channel-discussion-antispam-bot (pyproject.toml)
python-dotenv==1.0.0
# via channel-discussion-antispam-bot (pyproject.toml)
python-telegram-bot[webhooks]==20.3
Expand All @@ -171,6 +193,7 @@ tomli==2.0.1
# via
# flake8-pyproject
# mypy
# pytest
tornado==6.3.2
# via python-telegram-bot
traitlets==5.9.0
Expand Down
4 changes: 1 addition & 3 deletions filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class HasNoValidPreviousMessages(MessageFilter):
def filter(self, message: Message) -> bool:
if not DB_ENABLED() or message.from_user is None:
return True

return self.has_no_valid_previous_messages(user_id=message.from_user.id, chat_id=message.chat_id)

@classmethod
Expand Down Expand Up @@ -61,8 +60,7 @@ def filter(self, message: Message) -> bool:
if message.text is None:
return False

entities_types = set([entity.type for entity in message.entities])
return len(entities_types.intersection({'url', 'text_link'})) != 0
return any(entity.type in ('url', 'text_link') for entity in message.entities)


class ContainsThreeOrMoreEmojies(MessageFilter):
Expand Down
10 changes: 8 additions & 2 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@ class LogEntry(pw.Model):
class Meta:
database = db
indexes = (
('chat_id', 'message_id'),
True,
(
('chat_id', 'message_id'),
True,
),
)


def create_tables():
db.create_tables([LogEntry])


def drop_tables():
db.drop_tables([LogEntry])
11 changes: 11 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ dev = [
"flake8-variables-names",
"flake8-walrus",
"flake8-pyproject",

"pytest-deadfixtures",
"pytest-mock",
"pytest-randomly",
"pytest-env",
]


Expand Down Expand Up @@ -75,3 +80,9 @@ exclude = [
line_length = 160
known_standard_library = ["typing"]
multi_line_output = 4

[tool.pytest.ini_options]
python_files = ["test*.py"]
env = [
"DATABASE_URL=postgres://postgres@localhost:5432/postgres"
]
Empty file added tests/__init__.py
Empty file.
25 changes: 25 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import pytest

from models import create_tables, db, drop_tables


@pytest.fixture(scope="session")
def test_db():
create_tables()

yield db

drop_tables()


@pytest.fixture(scope='function', autouse=True)
def _rollback_transactions(test_db):
test_db.begin()

yield

test_db.rollback()

@pytest.fixture
def mock_message(mocker):
return mocker.patch("telegram.Message", autospec=True).return_value
Empty file added tests/tests_filters/__init__.py
Empty file.
8 changes: 8 additions & 0 deletions tests/tests_filters/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from typing import Callable

import pytest


@pytest.fixture
def do_filter(filter_obj) -> Callable[[], bool]:
return lambda message: filter_obj.filter(message)
20 changes: 20 additions & 0 deletions tests/tests_filters/test_chat_message_only.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import pytest

from filters import ChatMessageOnly


@pytest.fixture(scope="session")
def filter_obj():
return ChatMessageOnly()


def test_false_if_forwarded(do_filter, mock_message):
mock_message.forward_from_message_id = "ordinary-id-yep"

assert do_filter(mock_message) is False


def test_true_if_not_forwarded(do_filter, mock_message):
mock_message.forward_from_message_id = None

assert do_filter(mock_message) is True
48 changes: 48 additions & 0 deletions tests/tests_filters/test_cointains_three_or_more_emojis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import pytest

from filters import ContainsThreeOrMoreEmojies


@pytest.fixture
def message(mock_message):
mock_message.text = None
return mock_message


@pytest.fixture(scope="session")
def filter_obj():
return ContainsThreeOrMoreEmojies()


def test_false_if_empty_message(do_filter, message):
assert do_filter(message) is False


@pytest.mark.parametrize(
"text",
[
"Shalom 👋🏾",
"Ou ui 👀🙃",
"No emojis actually",
"🐍",
" ",
]
)
def test_false_if_less_than_3_emojis(do_filter, message, text):
message.text = text

assert do_filter(message) is False


@pytest.mark.parametrize(
"text",
[
"Shalom 👋🏾👀🙃",
"😅😎🧑🏿‍🦱👨‍👨‍👧‍👧",
"😅😎🧑🏿‍🦱👨‍👨‍👧‍👧🐍 some text 👋🏾👀🙃",
]
)
def test_true_if_more_than_2_emojis(do_filter, message, text):
message.text = text

assert do_filter(message) is True
62 changes: 62 additions & 0 deletions tests/tests_filters/test_contains_link.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import pytest

from filters import ContainsLink


class FakeMessageEntity:
def __init__(self, type: str):
self.type = type


@pytest.fixture
def mock_message_entity(mocker):
return lambda type_str: FakeMessageEntity(type_str)


@pytest.fixture
def message(mock_message, mock_message_entity):
# To see all possible types look at telegram.MessageEntity Attributes
message.text = "I'm not empty inside"
code = mock_message_entity("code")
phone_number = mock_message_entity("phone_number")
mock_message.entities = [code, phone_number]
return mock_message


@pytest.fixture(scope="session")
def filter_obj():
return ContainsLink()


def test_false_if_no_links_message(do_filter, message):
assert do_filter(message) is False


@pytest.mark.parametrize(
"link_type",
[
"url",
"text_link",
]
)
def test_true_if_has_link(do_filter, message, mock_message_entity, link_type):
message_entity = mock_message_entity(link_type)
message.entities.append(message_entity)

assert do_filter(message) is True


@pytest.mark.parametrize(
"link_types",
[
["text_link", "url"],
["text_link", "text_link"],
["url", "url"],
]
)
def test_true_if_has_many_links(do_filter, message, mock_message_entity, link_types):
for link_type in link_types:
message_entity = mock_message_entity(link_type)
message.entities.append(message_entity)

assert do_filter(message) is True
46 changes: 46 additions & 0 deletions tests/tests_filters/test_contains_tg_contact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import pytest

from filters import ContainsTelegramContact


@pytest.fixture
def message(mock_message):
message.text = "Ordinary text"
return mock_message


@pytest.fixture(scope="session")
def filter_obj():
return ContainsTelegramContact()


def test_false_if_no_text_message(do_filter, message):
message.text = None
assert do_filter(message) is False


@pytest.mark.parametrize(
"text",
[
"Hello there!",
"OMG look at my email [email protected]",
"sobaka@sobaka",
]
)
def test_false_if_no_contact(do_filter, message, text):
message.text = text

assert do_filter(message) is False


@pytest.mark.parametrize(
"text",
[
"write me a message @bbqomg",
"@contact_me",
]
)
def test_true_if_contact(do_filter, message, text):
message.text = text

assert do_filter(message) is True
Loading

0 comments on commit d286e4a

Please sign in to comment.