Rework pytest Integration into GitHub Actions (#3776)

This commit is contained in:
Bibo-Joshi 2023-06-26 19:48:38 +02:00 committed by GitHub
parent b0cff31fc1
commit 62a8cfc395
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 83 deletions

View file

@ -1,4 +1,4 @@
name: GitHub Actions name: Unit Tests
on: on:
pull_request: pull_request:
branches: branches:
@ -55,7 +55,7 @@ jobs:
TO_TEST="test_no_passport.py or test_datetime.py or test_defaults.py or test_jobqueue.py or test_applicationbuilder.py or test_ratelimiter.py or test_updater.py or test_callbackdatacache.py or test_request.py" TO_TEST="test_no_passport.py or test_datetime.py or test_defaults.py or test_jobqueue.py or test_applicationbuilder.py or test_ratelimiter.py or test_updater.py or test_callbackdatacache.py or test_request.py"
pytest -v --cov -k "${TO_TEST}" pytest -v --cov -k "${TO_TEST}"
# Rerun only failed tests (--lf), and don't run any tests if none failed (--lfnf=none) # Rerun only failed tests (--lf), and don't run any tests if none failed (--lfnf=none)
pytest -v --cov --cov-append -k "${TO_TEST}" --lf --lfnf=none pytest -v --cov --cov-append -k "${TO_TEST}" --lf --lfnf=none --junit-xml=.test_report_no_optionals.xml
# No tests were selected, convert returned status code to 0 # No tests were selected, convert returned status code to 0
opt_dep_status=$(( $? == 5 ? 0 : $? )) opt_dep_status=$(( $? == 5 ? 0 : $? ))
@ -66,7 +66,7 @@ jobs:
# worker. Increasing number of workers has little effect on test duration, but it seems # worker. Increasing number of workers has little effect on test duration, but it seems
# to increase flakyness, specially on python 3.7 with --dist=loadgroup. # to increase flakyness, specially on python 3.7 with --dist=loadgroup.
pytest -v --cov --cov-append -n auto --dist loadfile pytest -v --cov --cov-append -n auto --dist loadfile
pytest -v --cov --cov-append -n auto --dist loadfile --lf --lfnf=none pytest -v --cov --cov-append -n auto --dist loadfile --lf --lfnf=none --junit-xml=.test_report_optionals.xml
main_status=$(( $? == 5 ? 0 : $? )) main_status=$(( $? == 5 ? 0 : $? ))
# exit with non-zero status if any of the two pytest runs failed # exit with non-zero status if any of the two pytest runs failed
exit $(( ${opt_dep_status} || ${main_status} )) exit $(( ${opt_dep_status} || ${main_status} ))
@ -77,12 +77,22 @@ jobs:
TEST_BUILD: "true" TEST_BUILD: "true"
shell: bash --noprofile --norc {0} shell: bash --noprofile --norc {0}
- name: Test Summary
id: test_summary
uses: test-summary/action@v2.1
if: always() # always run, even if tests fail
with:
paths: |
.test_report_no_optionals.xml
.test_report_optionals.xml
- name: Submit coverage - name: Submit coverage
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v3
with: with:
env_vars: OS,PYTHON env_vars: OS,PYTHON
name: ${{ matrix.os }}-${{ matrix.python-version }} name: ${{ matrix.os }}-${{ matrix.python-version }}
fail_ci_if_error: true fail_ci_if_error: true
test_official: test_official:
name: test-official name: test-official
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
@ -105,8 +115,15 @@ jobs:
python -W ignore -m pip install -r requirements-dev.txt python -W ignore -m pip install -r requirements-dev.txt
- name: Compare to official api - name: Compare to official api
run: | run: |
pytest -v tests/test_official.py pytest -v tests/test_official.py --junit-xml=.test_report_official.xml
exit $? exit $?
env: env:
TEST_OFFICIAL: "true" TEST_OFFICIAL: "true"
shell: bash --noprofile --norc {0} shell: bash --noprofile --norc {0}
- name: Test Summary
id: test_summary
uses: test-summary/action@v2.1
if: always() # always run, even if tests fail
with:
paths: .test_report_official.xml

View file

@ -1,74 +0,0 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
import _pytest.config
import pytest
fold_plugins = {"_cov": "Coverage report", "flaky": "Flaky report"}
def terminal_summary_wrapper(original, plugin_name):
text = fold_plugins[plugin_name]
def pytest_terminal_summary(terminalreporter):
terminalreporter.write(f"##[group] {text}\n")
original(terminalreporter)
terminalreporter.write("##[endgroup]")
return pytest_terminal_summary
@pytest.mark.trylast()
def pytest_configure(config):
for hookimpl in config.pluginmanager.hook.pytest_terminal_summary._nonwrappers:
if hookimpl.plugin_name in fold_plugins:
hookimpl.function = terminal_summary_wrapper(hookimpl.function, hookimpl.plugin_name)
class PytestPluginHelpers:
terminal = None
previous_name = None
def _get_name(location):
if location[0].startswith("tests/"):
return location[0][6:]
return location[0]
@pytest.mark.trylast()
def pytest_itemcollected(item):
item._nodeid = item._nodeid.split("::", 1)[1]
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_protocol(item, nextitem):
# This is naughty but pytests' own plugins does something similar too, so who cares
if PytestPluginHelpers.terminal is None:
PytestPluginHelpers.terminal = _pytest.config.create_terminal_writer(item.config)
name = _get_name(item.location)
if PytestPluginHelpers.previous_name is None or PytestPluginHelpers.previous_name != name:
PytestPluginHelpers.previous_name = name
PytestPluginHelpers.terminal.write(f"\n##[group] {name}")
yield
if nextitem is None or _get_name(nextitem.location) != name:
PytestPluginHelpers.terminal.write("\n##[endgroup]")

View file

@ -39,7 +39,7 @@ from telegram.ext.filters import MessageFilter, UpdateFilter
from tests.auxil.build_messages import DATE from tests.auxil.build_messages import DATE
from tests.auxil.ci_bots import BOT_INFO_PROVIDER from tests.auxil.ci_bots import BOT_INFO_PROVIDER
from tests.auxil.constants import PRIVATE_KEY from tests.auxil.constants import PRIVATE_KEY
from tests.auxil.envvars import GITHUB_ACTION, TEST_WITH_OPT_DEPS from tests.auxil.envvars import TEST_WITH_OPT_DEPS
from tests.auxil.files import data_file from tests.auxil.files import data_file
from tests.auxil.networking import NonchalantHttpxRequest from tests.auxil.networking import NonchalantHttpxRequest
from tests.auxil.pytest_classes import PytestApplication, PytestBot, make_bot from tests.auxil.pytest_classes import PytestApplication, PytestBot, make_bot
@ -87,10 +87,6 @@ def pytest_collection_modifyitems(items: List[pytest.Item]):
parent.add_marker(pytest.mark.no_req) parent.add_marker(pytest.mark.no_req)
if GITHUB_ACTION:
pytest_plugins = ["tests.auxil.plugin_github_group"]
# Redefine the event_loop fixture to have a session scope. Otherwise `bot` fixture can't be # Redefine the event_loop fixture to have a session scope. Otherwise `bot` fixture can't be
# session. See https://github.com/pytest-dev/pytest-asyncio/issues/68 for more details. # session. See https://github.com/pytest-dev/pytest-asyncio/issues/68 for more details.
@pytest.fixture(scope="session") @pytest.fixture(scope="session")