Compare commits

..

5 Commits

Author SHA1 Message Date
bashonly
3de49061e3
Update CONTRIBUTING.md again 2023-12-25 17:26:48 +00:00
bashonly
9b5994e99d
Update CONTRIBUTING.md 2023-12-25 17:12:21 +00:00
Simon Sawicki
291171bfa9
Deprecate run_tests.bat and run_tests.sh 2023-12-25 18:06:28 +01:00
Simon Sawicki
b7ed507179
Migrate CI to run_tests.py
Also some internal changes to the test building
2023-12-25 17:54:41 +01:00
Simon Sawicki
e9ae695d95
Apply review 2023-12-25 14:41:28 +01:00
7 changed files with 67 additions and 82 deletions

View File

@ -18,18 +18,14 @@ jobs:
os: [ubuntu-latest] os: [ubuntu-latest]
# CPython 3.11 is in quick-test # CPython 3.11 is in quick-test
python-version: ['3.8', '3.9', '3.10', '3.12', pypy-3.8, pypy-3.10] python-version: ['3.8', '3.9', '3.10', '3.12', pypy-3.8, pypy-3.10]
run-tests-ext: [sh]
include: include:
# atleast one of each CPython/PyPy tests must be in windows # atleast one of each CPython/PyPy tests must be in windows
- os: windows-latest - os: windows-latest
python-version: '3.8' python-version: '3.8'
run-tests-ext: bat
- os: windows-latest - os: windows-latest
python-version: '3.12' python-version: '3.12'
run-tests-ext: bat
- os: windows-latest - os: windows-latest
python-version: pypy-3.9 python-version: pypy-3.9
run-tests-ext: bat
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
@ -42,4 +38,4 @@ jobs:
continue-on-error: False continue-on-error: False
run: | run: |
python3 -m yt_dlp -v || true # Print debug head python3 -m yt_dlp -v || true # Print debug head
./devscripts/run_tests.${{ matrix.run-tests-ext }} core python3 -Werror ./devscripts/run_tests.py core

View File

@ -18,7 +18,7 @@ jobs:
run: pip install pytest -r requirements.txt run: pip install pytest -r requirements.txt
- name: Run tests - name: Run tests
continue-on-error: true continue-on-error: true
run: ./devscripts/run_tests.sh download run: python3 -Werror ./devscripts/run_tests.py download
full: full:
name: Full Download Tests name: Full Download Tests
@ -29,15 +29,12 @@ jobs:
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
python-version: ['3.10', '3.11', '3.12', pypy-3.8, pypy-3.10] python-version: ['3.10', '3.11', '3.12', pypy-3.8, pypy-3.10]
run-tests-ext: [sh]
include: include:
# atleast one of each CPython/PyPy tests must be in windows # atleast one of each CPython/PyPy tests must be in windows
- os: windows-latest - os: windows-latest
python-version: '3.8' python-version: '3.8'
run-tests-ext: bat
- os: windows-latest - os: windows-latest
python-version: pypy-3.9 python-version: pypy-3.9
run-tests-ext: bat
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
@ -48,4 +45,4 @@ jobs:
run: pip install pytest -r requirements.txt run: pip install pytest -r requirements.txt
- name: Run tests - name: Run tests
continue-on-error: true continue-on-error: true
run: ./devscripts/run_tests.${{ matrix.run-tests-ext }} download run: python3 -Werror ./devscripts/run_tests.py download

View File

@ -19,7 +19,7 @@ jobs:
- name: Run tests - name: Run tests
run: | run: |
python3 -m yt_dlp -v || true python3 -m yt_dlp -v || true
./devscripts/run_tests.sh core python3 -Werror ./devscripts/run_tests.py core
flake8: flake8:
name: Linter name: Linter
if: "!contains(github.event.head_commit.message, 'ci skip all')" if: "!contains(github.event.head_commit.message, 'ci skip all')"

View File

@ -140,9 +140,9 @@ To run yt-dlp as a developer, you don't need to build anything either. Simply ex
python -m yt_dlp python -m yt_dlp
To run all the available core tests use To run all the available core tests, use:
python devscript/run_tests.py python devscripts/run_tests.py
See item 6 of [new extractor tutorial](#adding-support-for-a-new-site) for how to run extractor specific test cases. See item 6 of [new extractor tutorial](#adding-support-for-a-new-site) for how to run extractor specific test cases.
@ -184,14 +184,19 @@ After you have ensured this site is distributing its content legally, you can fo
'url': 'https://yourextractor.com/watch/42', 'url': 'https://yourextractor.com/watch/42',
'md5': 'TODO: md5 sum of the first 10241 bytes of the video file (use --test)', 'md5': 'TODO: md5 sum of the first 10241 bytes of the video file (use --test)',
'info_dict': { 'info_dict': {
# For videos, only the 'id' and 'ext' fields are required to RUN the test:
'id': '42', 'id': '42',
'ext': 'mp4', 'ext': 'mp4',
'title': 'Video title goes here', # Then if the test run fails, it will output the missing/incorrect fields.
'thumbnail': r're:^https?://.*\.jpg$', # Properties can be added as:
# TODO more properties, either as: # * A value, e.g.:
# * A value # 'title': 'Video title goes here',
# * MD5 checksum; start the string with md5: # * MD5 checksum; start the string with 'md5:', e.g.:
# * A regular expression; start the string with re: # 'description': 'md5:098f6bcd4621d373cade4e832627b4f6',
# * A regular expression; start the string with 're:', e.g.:
# 'thumbnail': r're:^https?://.*\.jpg$',
# * A count of elements in a list; start the string with 'count:', e.g.:
# 'tags': 'count:10',
# * Any Python type, e.g. int or float # * Any Python type, e.g. int or float
} }
}] }]
@ -212,8 +217,8 @@ After you have ensured this site is distributing its content legally, you can fo
} }
``` ```
1. Add an import in [`yt_dlp/extractor/_extractors.py`](yt_dlp/extractor/_extractors.py). Note that the class name must end with `IE`. 1. Add an import in [`yt_dlp/extractor/_extractors.py`](yt_dlp/extractor/_extractors.py). Note that the class name must end with `IE`.
1. Run `python devscripts/run_tests.py YourExtractor` (note that `YourExtractor` doesn't end with `IE`). This *should fail* at first, but you can continually re-run it until you're done. If you decide to add more than one test, the tests will then be named `YourExtractor`, `YourExtractor_1`, `YourExtractor_2`, etc. Note that tests with `only_matching` key in test's dict are not counted in. You can also run all the tests in one go with `YourExtractor_all` 1. Run `python devscripts/run_tests.py YourExtractor`. This *may fail* at first, but you can continually re-run it until you're done. Upon failure, it will output the missing fields and/or correct values which you can copy. If you decide to add more than one test, the tests will then be named `YourExtractor`, `YourExtractor_1`, `YourExtractor_2`, etc. Note that tests with an `only_matching` key in the test's dict are not included in the count. You can also run all the tests in one go with `YourExtractor_all`
1. Make sure you have atleast one test for your extractor. Even if all videos covered by the extractor are expected to be inaccessible for automated testing, tests should still be added with a `skip` parameter indicating why the particular test is disabled from running. 1. Make sure you have at least one test for your extractor. Even if all videos covered by the extractor are expected to be inaccessible for automated testing, tests should still be added with a `skip` parameter indicating why the particular test is disabled from running.
1. Have a look at [`yt_dlp/extractor/common.py`](yt_dlp/extractor/common.py) for possible helper methods and a [detailed description of what your extractor should and may return](yt_dlp/extractor/common.py#L119-L440). Add tests and code for as many as you want. 1. Have a look at [`yt_dlp/extractor/common.py`](yt_dlp/extractor/common.py) for possible helper methods and a [detailed description of what your extractor should and may return](yt_dlp/extractor/common.py#L119-L440). Add tests and code for as many as you want.
1. Make sure your code follows [yt-dlp coding conventions](#yt-dlp-coding-conventions) and check the code with [flake8](https://flake8.pycqa.org/en/latest/index.html#quickstart): 1. Make sure your code follows [yt-dlp coding conventions](#yt-dlp-coding-conventions) and check the code with [flake8](https://flake8.pycqa.org/en/latest/index.html#quickstart):

View File

@ -1,17 +1,4 @@
@setlocal
@echo off @echo off
cd /d %~dp0..
if ["%~1"]==[""] ( >&2 echo run_tests.bat is deprecated. Please use `devscripts/run_tests.py` instead
set "test_set="test"" python -Werror %~dp0run_tests.py %~1
) else if ["%~1"]==["core"] (
set "test_set="-m not download""
) else if ["%~1"]==["download"] (
set "test_set="-m "download""
) else (
echo.Invalid test type "%~1". Use "core" ^| "download"
exit /b 1
)
set PYTHONWARNINGS=error
pytest %test_set%

View File

@ -6,63 +6,73 @@ import os
import re import re
import subprocess import subprocess
import sys import sys
import warnings
from pathlib import Path from pathlib import Path
IE_TEST_PATTERN = re.compile(r'IE(_all|_\d+)?$') fix_test_name = functools.partial(re.compile(r'IE(_all|_\d+)?$').sub, r'\1')
fix_test_name = functools.partial(IE_TEST_PATTERN.sub, r'\1')
def parse_args(): def parse_args():
parser = argparse.ArgumentParser(description='Run selected yt-dlp tests') parser = argparse.ArgumentParser(description='Run selected yt-dlp tests')
parser.add_argument( parser.add_argument(
'test', help='An extractor test, or one of "core" or "download"', nargs='*') 'test', help='a extractor tests, or one of "core" or "download"', nargs='*')
parser.add_argument( parser.add_argument(
'-k', help='Run a test matching the expression. Same as "pytest -k"', metavar='EXPRESSION') '-k', help='run a test matching EXPRESSION. Same as "pytest -k"', metavar='EXPRESSION')
return parser.parse_args() return parser.parse_args()
def run_tests(*tests, pattern=None): def run_tests(*tests, pattern=None):
unittest_supported = True werror = ('error', None, Warning, None, 0) in warnings.filters
arguments = [] run_core = 'core' in tests or (not pattern and not tests)
run_download = 'download' in tests
tests = list(map(fix_test_name, tests))
for test in tests: arguments = ['pytest', '--tb', 'short']
if test == 'core': if werror:
arguments += ['-m', 'not download'] arguments.append('-Werror')
unittest_supported = False if run_core:
elif test == 'download': arguments.extend(['-m', 'not download'])
arguments += ['-m', 'download'] elif run_download:
unittest_supported = False arguments.extend(['-m', 'download'])
else: elif pattern:
arguments.append(f'test/test_download.py::TestDownload::test_{fix_test_name(test)}') arguments.extend(['-k', pattern])
else:
arguments.extend(
f'test/test_download.py::TestDownload::test_{test}' for test in tests)
if pattern: print(f'Running {arguments}')
arguments += ['-k', pattern]
if not arguments:
arguments = ['-m', 'not download']
print(f'Running pytest with short traceback on {arguments}')
try: try:
subprocess.run(['pytest', '--tb', 'short'] + arguments) subprocess.run(arguments)
return return
except FileNotFoundError: except FileNotFoundError:
pass pass
if not unittest_supported: arguments = [sys.executable]
print('"pytest" needs to be installed to run the specified tests', file=sys.stderr) if werror:
arguments.append('-Werror')
arguments.extend(['-m', 'unittest'])
if run_core:
print('"pytest" needs to be installed to run core tests', file=sys.stderr)
return return
elif run_download:
arguments.append('test.test_download')
elif pattern:
arguments.extend(['-k', pattern])
else:
arguments.extend(
f'test.test_download.TestDownload.test_{test}' for test in tests)
arguments = [f'test.test_download.TestDownload.test_{fix_test_name(test)}' for test in tests] print(f'Running {arguments}')
if pattern: subprocess.run(arguments)
arguments += ['-k', pattern]
print(f'Running unittest with {arguments}')
subprocess.run([sys.executable, '-m', 'unittest'] + arguments)
if __name__ == '__main__': if __name__ == '__main__':
args = parse_args() try:
args = parse_args()
os.chdir(Path(__file__).parent.parent) os.chdir(Path(__file__).parent.parent)
run_tests(*args.test, pattern=args.k) run_tests(*args.test, pattern=args.k)
except KeyboardInterrupt:
pass

View File

@ -1,14 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/env sh
if [ -z "$1" ]; then >&2 echo 'run_tests.sh is deprecated. Please use `devscripts/run_tests.py` instead'
test_set='test' python3 -Werror devscripts/run_tests.py "$1"
elif [ "$1" = 'core' ]; then
test_set="-m not download"
elif [ "$1" = 'download' ]; then
test_set="-m download"
else
echo 'Invalid test type "'"$1"'". Use "core" | "download"'
exit 1
fi
python3 -bb -Werror -m pytest "$test_set"