Add test pipeline step and a basic test
This commit is contained in:
10
.gitignore
vendored
10
.gitignore
vendored
@@ -1,3 +1,11 @@
|
|||||||
|
# Locally specific files
|
||||||
.env
|
.env
|
||||||
.idea/
|
.idea/
|
||||||
.idea/vcs.xml
|
|
||||||
|
# Cache
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Tests and Coverage
|
||||||
|
.pytest_cache/
|
||||||
|
.coverage*
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
stages:
|
stages:
|
||||||
- lint
|
- lint
|
||||||
|
- test
|
||||||
- build
|
- build
|
||||||
- deploy
|
- deploy
|
||||||
|
|
||||||
@@ -11,17 +12,24 @@ stages:
|
|||||||
|
|
||||||
.base:
|
.base:
|
||||||
image: python:3.11.2
|
image: python:3.11.2
|
||||||
|
only:
|
||||||
|
changes:
|
||||||
|
- "/poetry.lock"
|
||||||
|
- "/pyproject.toml"
|
||||||
|
- "/app/*"
|
||||||
|
|
||||||
|
.test:
|
||||||
|
extends: .base
|
||||||
|
stage: test
|
||||||
|
before_script:
|
||||||
|
- *install-deps
|
||||||
|
|
||||||
.lint:
|
.lint:
|
||||||
extends: .base
|
extends: .base
|
||||||
stage: lint
|
stage: lint
|
||||||
before_script:
|
before_script:
|
||||||
- *install-deps
|
- *install-deps
|
||||||
only:
|
|
||||||
changes:
|
|
||||||
- "/poetry.lock"
|
|
||||||
- "/pyproject.toml"
|
|
||||||
- "/app/*"
|
|
||||||
######################################
|
######################################
|
||||||
# #
|
# #
|
||||||
# LINT STEPS #
|
# LINT STEPS #
|
||||||
@@ -38,6 +46,18 @@ isort:
|
|||||||
script:
|
script:
|
||||||
- poetry run isort --check .
|
- poetry run isort --check .
|
||||||
|
|
||||||
|
######################################
|
||||||
|
# #
|
||||||
|
# TEST STEPS #
|
||||||
|
# #
|
||||||
|
######################################
|
||||||
|
|
||||||
|
test:
|
||||||
|
extends: .test
|
||||||
|
coverage: '/TOTAL.*\s+(\d+\%)/'
|
||||||
|
script:
|
||||||
|
- poetry run pytest --cov -v
|
||||||
|
|
||||||
######################################
|
######################################
|
||||||
# #
|
# #
|
||||||
# BUILD STEPS #
|
# BUILD STEPS #
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ RUN curl -sSL https://install.python-poetry.org | python3 -
|
|||||||
ENV PATH=/root/.local/bin:$PATH
|
ENV PATH=/root/.local/bin:$PATH
|
||||||
RUN poetry install
|
RUN poetry install
|
||||||
|
|
||||||
CMD ["poetry", "run", "python", "app/main.py"]
|
CMD ["poetry", "run", "python", "-m" , "app.main"]
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -2,7 +2,7 @@ import os
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from twitch_client import StreamInformation
|
from app.twitch_client import StreamInformation
|
||||||
|
|
||||||
|
|
||||||
class DiscordClient:
|
class DiscordClient:
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from discord_client import DiscordClient
|
from app.discord_client import DiscordClient
|
||||||
|
from app.twitch_client import StreamInformation, TwitchClient
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from requests import HTTPError
|
from requests import HTTPError
|
||||||
from twitch_client import StreamInformation, TwitchClient
|
|
||||||
|
|
||||||
|
|
||||||
class Main:
|
class Main:
|
||||||
|
|||||||
0
app/tests/__init__.py
Normal file
0
app/tests/__init__.py
Normal file
16
app/tests/conftest.py
Normal file
16
app/tests/conftest.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from collections import namedtuple
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_loggers():
|
||||||
|
with (
|
||||||
|
mock.patch("loguru.logger.info") as info_logger,
|
||||||
|
mock.patch("loguru.logger.error") as error_logger,
|
||||||
|
):
|
||||||
|
mocked_loggers = namedtuple(
|
||||||
|
"mocked_loggers", ["info_logger", "error_logger"]
|
||||||
|
)
|
||||||
|
yield mocked_loggers(info_logger, error_logger)
|
||||||
44
app/tests/test_discord_client.py
Normal file
44
app/tests/test_discord_client.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import os
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import requests_mock
|
||||||
|
from requests import HTTPError
|
||||||
|
|
||||||
|
from app.discord_client import DiscordClient
|
||||||
|
from app.twitch_client import StreamInformation
|
||||||
|
|
||||||
|
|
||||||
|
def test_require_webhook_url():
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
DiscordClient()
|
||||||
|
|
||||||
|
|
||||||
|
def test_send_information_to_discord_fails(mock_loggers):
|
||||||
|
stream = StreamInformation(
|
||||||
|
user_id="",
|
||||||
|
user_name="",
|
||||||
|
user_login="",
|
||||||
|
game_name="",
|
||||||
|
started_at="",
|
||||||
|
title="",
|
||||||
|
viewer_count=0,
|
||||||
|
_thumbnail_url=""
|
||||||
|
)
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch.dict(os.environ, {"DISCORD_WEBHOOK_URL": "https://test"}),
|
||||||
|
requests_mock.Mocker() as requests_mocker,
|
||||||
|
):
|
||||||
|
requests_mocker.post(url="https://test", status_code=400)
|
||||||
|
|
||||||
|
discord_client = DiscordClient()
|
||||||
|
with pytest.raises(HTTPError):
|
||||||
|
discord_client.send_information_to_discord(
|
||||||
|
stream=stream, profile_image=""
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(mock_loggers.info_logger.call_args_list) == 1
|
||||||
|
assert mock_loggers.info_logger.call_args.args[0] == (
|
||||||
|
"Sending a message with an embed to the webhook..."
|
||||||
|
)
|
||||||
138
poetry.lock
generated
138
poetry.lock
generated
@@ -1,3 +1,19 @@
|
|||||||
|
[[package]]
|
||||||
|
name = "attrs"
|
||||||
|
version = "22.2.0"
|
||||||
|
description = "Classes Without Boilerplate"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
cov = ["attrs", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"]
|
||||||
|
dev = ["attrs"]
|
||||||
|
docs = ["furo", "sphinx", "myst-parser", "zope.interface", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"]
|
||||||
|
tests = ["attrs", "zope.interface"]
|
||||||
|
tests-no-zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"]
|
||||||
|
tests_no_zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "black"
|
name = "black"
|
||||||
version = "23.1.0"
|
version = "23.1.0"
|
||||||
@@ -54,6 +70,17 @@ category = "main"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "coverage"
|
||||||
|
version = "7.2.1"
|
||||||
|
description = "Code coverage measurement for Python"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
toml = ["tomli"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.4"
|
version = "3.4"
|
||||||
@@ -62,6 +89,14 @@ category = "main"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iniconfig"
|
||||||
|
version = "2.0.0"
|
||||||
|
description = "brain-dead simple config-ini parsing"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "isort"
|
name = "isort"
|
||||||
version = "5.12.0"
|
version = "5.12.0"
|
||||||
@@ -127,6 +162,73 @@ python-versions = ">=3.7"
|
|||||||
docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)", "sphinx (>=6.1.3)"]
|
docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)", "sphinx (>=6.1.3)"]
|
||||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest (>=7.2.1)"]
|
test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest (>=7.2.1)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pluggy"
|
||||||
|
version = "1.0.0"
|
||||||
|
description = "plugin and hook calling mechanisms for python"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["pre-commit", "tox"]
|
||||||
|
testing = ["pytest", "pytest-benchmark"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest"
|
||||||
|
version = "7.2.2"
|
||||||
|
description = "pytest: simple powerful testing with Python"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
attrs = ">=19.2.0"
|
||||||
|
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
|
iniconfig = "*"
|
||||||
|
packaging = "*"
|
||||||
|
pluggy = ">=0.12,<2.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest-cov"
|
||||||
|
version = "4.0.0"
|
||||||
|
description = "Pytest plugin for measuring coverage."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
coverage = {version = ">=5.2.1", extras = ["toml"]}
|
||||||
|
pytest = ">=4.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest-cover"
|
||||||
|
version = "3.0.0"
|
||||||
|
description = "Pytest plugin for measuring coverage. Forked from `pytest-cov`."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
pytest-cov = ">=2.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest-coverage"
|
||||||
|
version = "0.0"
|
||||||
|
description = "Pytest plugin for measuring coverage. Forked from `pytest-cov`."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
pytest-cover = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "requests"
|
name = "requests"
|
||||||
version = "2.28.2"
|
version = "2.28.2"
|
||||||
@@ -145,6 +247,30 @@ urllib3 = ">=1.21.1,<1.27"
|
|||||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||||
use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]
|
use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "requests-mock"
|
||||||
|
version = "1.10.0"
|
||||||
|
description = "Mock out responses from the requests package"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
requests = ">=2.3,<3"
|
||||||
|
six = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
fixture = ["fixtures"]
|
||||||
|
test = ["fixtures", "mock", "purl", "pytest", "sphinx", "testrepository (>=0.0.18)", "testtools", "requests-futures"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "six"
|
||||||
|
version = "1.16.0"
|
||||||
|
description = "Python 2 and 3 compatibility utilities"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "urllib3"
|
name = "urllib3"
|
||||||
version = "1.26.14"
|
version = "1.26.14"
|
||||||
@@ -172,9 +298,10 @@ dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"]
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.11"
|
python-versions = "^3.11"
|
||||||
content-hash = "2cd384690a48bd802789a049147162c975c512098cc42b7716ba54b06f448092"
|
content-hash = "c88f613c25a933f82f5abb7053b249fe6bc13d021c655f1da432fca43c5d2fba"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
|
attrs = []
|
||||||
black = []
|
black = []
|
||||||
certifi = []
|
certifi = []
|
||||||
charset-normalizer = []
|
charset-normalizer = []
|
||||||
@@ -183,13 +310,22 @@ click = [
|
|||||||
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
||||||
]
|
]
|
||||||
colorama = []
|
colorama = []
|
||||||
|
coverage = []
|
||||||
idna = []
|
idna = []
|
||||||
|
iniconfig = []
|
||||||
isort = []
|
isort = []
|
||||||
loguru = []
|
loguru = []
|
||||||
mypy-extensions = []
|
mypy-extensions = []
|
||||||
packaging = []
|
packaging = []
|
||||||
pathspec = []
|
pathspec = []
|
||||||
platformdirs = []
|
platformdirs = []
|
||||||
|
pluggy = []
|
||||||
|
pytest = []
|
||||||
|
pytest-cov = []
|
||||||
|
pytest-cover = []
|
||||||
|
pytest-coverage = []
|
||||||
requests = []
|
requests = []
|
||||||
|
requests-mock = []
|
||||||
|
six = []
|
||||||
urllib3 = []
|
urllib3 = []
|
||||||
win32-setctime = []
|
win32-setctime = []
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ requests = "^2.28.2"
|
|||||||
loguru = "^0.6.0"
|
loguru = "^0.6.0"
|
||||||
black = "^23.1.0"
|
black = "^23.1.0"
|
||||||
isort = "^5.12.0"
|
isort = "^5.12.0"
|
||||||
|
pytest = "^7.2.2"
|
||||||
|
requests-mock = "^1.10.0"
|
||||||
|
pytest-coverage = "^0.0"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user