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

Tests #36

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
6 changes: 4 additions & 2 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
paths:
- ".github/workflows/lint.yaml"
- "locales/*.pot"
- "tests/**"
- "userbot/**"
- ".pre-commit-config.yaml"
- "dev-requirements.txt"
Expand All @@ -18,6 +19,7 @@ on:
paths:
- ".github/workflows/lint.yaml"
- "locales/*.pot"
- "tests/**"
- "userbot/**"
- ".pre-commit-config.yaml"
- "dev-requirements.txt"
Expand Down Expand Up @@ -56,5 +58,5 @@ jobs:

- name: Check code style
run: |
isort --check --diff userbot
black --check --diff userbot
isort --check --diff userbot tests
black --check --diff userbot tests
54 changes: 54 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Test code

on:
push:
branches:
- master
paths:
- ".github/workflows/test.yaml"
- "tests/**"
- "userbot/**"
- "dev-requirements.txt"
- "pyproject.toml"
- "requirements.txt"
pull_request:
branches:
- master
paths:
- ".github/workflows/test.yaml"
- "tests/**"
- "userbot/**"
- "dev-requirements.txt"
- "pyproject.toml"
- "requirements.txt"

permissions:
contents: read

env:
CI: "true"

jobs:
test:
name: Test code using pytest
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Install Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
cache: pip

- name: Install packages
run: pip install -r dev-requirements.txt -r requirements.txt

- name: Run tests
env:
ENV_FILE_CONTENT: ${{ secrets.TEST_ENV_FILE_CONTENT }}
run: |
echo "$ENV_FILE_CONTENT" >>"$GITHUB_ENV"
pytest
9 changes: 9 additions & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# i18n
Babel~=2.11.0

# Code style
black~=22.10.0
isort~=5.10.1
pre-commit~=2.20.0

# Tests
hypothesis~=6.56.4
pytest~=7.2.0
pytest-asyncio~=0.20.1
# TODO (2022-11-06): pytest-cov~=4.0.0
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ line_length = 100
py_version = '310' # (2022-10-28) isort 5.10.1 doesn't support 3.11
profile = 'black'
known_first_party = ['userbot']

[tool.pytest.ini_options]
testpaths = [
"tests",
]
Empty file added tests/__init__.py
Empty file.
103 changes: 103 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from __future__ import annotations

import asyncio
import json
import os
import random
from typing import AsyncIterable

import pytest
import pytest_asyncio
from pyrogram import Client
from pyrogram.types import TermsOfService, User

from userbot import __version__
from userbot.config import Config, RedisConfig
from userbot.utils import SecretStr


@pytest.fixture(scope="session")
def config() -> Config:
os.environ.setdefault("SESSION", "test")
# https://github.com/telegramdesktop/tdesktop/blob/a4b0443/Telegram/cmake/telegram_options.cmake#L15-L18
os.environ.setdefault("API_ID", "17349")
os.environ.setdefault("API_HASH", "344583e45741c457fe1862106095a5eb")

config = Config.from_env()

config.kwargs.setdefault("test_mode", SecretStr("1"))
config.kwargs.setdefault("in_memory", SecretStr("1"))
if config.kwargs.get("phone_number", None) is None:
try:
with open(config.data_location / ".test_phone.json") as f:
phone_number, phone_code = json.load(f)
except FileNotFoundError:
dc_n = str(random.randint(1, 3))
random_n = f"{random.randint(0, 9999):4d}"
# https://docs.pyrogram.org/topics/test-servers#test-numbers
phone_number = f"99966{dc_n}{random_n}"
phone_code = dc_n * 5
try:
with open(config.data_location / ".test_phone.json", "w") as f:
json.dump([phone_number, phone_code], f)
except OSError:
pass
config.kwargs["phone_number"] = SecretStr(phone_number)
config.kwargs["phone_code"] = SecretStr(phone_code)

return config


@pytest.fixture(scope="session")
def redis_config() -> RedisConfig:
os.environ.setdefault("REDIS_HOST", "localhost")
os.environ.setdefault("REDIS_DB", "2")
return RedisConfig.from_env()


@pytest.fixture(scope="session")
def event_loop() -> asyncio.AbstractEventLoop:
"""Overrides pytest default function scoped event loop"""
policy = asyncio.get_event_loop_policy()
loop = policy.new_event_loop()
yield loop
loop.close()


@pytest_asyncio.fixture(scope="session")
async def client(config: Config) -> AsyncIterable[Client]:
in_memory = config.kwargs.pop("in_memory") == "1"
app = Client(
name=config.session,
api_id=config.api_id,
api_hash=config.api_hash.value,
app_version=f"evgfilim1/userbot {__version__} TEST",
device_model="Linux",
test_mode=config.kwargs.pop("test_mode") == "1",
in_memory=in_memory,
workdir=str(config.data_location),
**config.kwargs,
)
# Make sure we are registered, register otherwise
is_authorized = await app.connect()
if not is_authorized:
phone_number = config.kwargs["phone_number"].value
code = await app.send_code(phone_number)
signed_in = await app.sign_in(
phone_number, code.phone_code_hash, config.kwargs["phone_code"].value
)
if not isinstance(signed_in, User):
await app.sign_up(
phone_number,
code.phone_code_hash,
f"Test {phone_number[-4:]}",
)
if isinstance(signed_in, TermsOfService):
await app.accept_terms_of_service(signed_in.id)
await app.disconnect()
await app.start()
yield app
if in_memory:
await app.log_out()
else:
await app.stop()
Empty file added tests/test_modules/__init__.py
Empty file.
Loading