Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests #9

Merged
merged 4 commits into from
Jul 6, 2023
Merged
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
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