mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2025-03-09 12:50:23 -05:00
Merge 13d72c5762
into 05c8023a27
This commit is contained in:
commit
74e0bb80b0
7 changed files with 249 additions and 1 deletions
28
.coveragerc
Normal file
28
.coveragerc
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[coverage:run]
|
||||||
|
source = yt_dlp, devscripts
|
||||||
|
omit =
|
||||||
|
*/extractor/lazy_extractors.py
|
||||||
|
*/__pycache__/*
|
||||||
|
*/test/*
|
||||||
|
*/yt_dlp/compat/_deprecated.py
|
||||||
|
*/yt_dlp/compat/_legacy.py
|
||||||
|
data_file = .coverage
|
||||||
|
|
||||||
|
[coverage:report]
|
||||||
|
exclude_lines =
|
||||||
|
pragma: no cover
|
||||||
|
def __repr__
|
||||||
|
raise NotImplementedError
|
||||||
|
if __name__ == .__main__.:
|
||||||
|
pass
|
||||||
|
raise ImportError
|
||||||
|
except ImportError:
|
||||||
|
warnings\.warn
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
|
[coverage:html]
|
||||||
|
directory = .coverage-reports/html
|
||||||
|
title = yt-dlp Coverage Report
|
||||||
|
|
||||||
|
[coverage:xml]
|
||||||
|
output = .coverage-reports/coverage.xml
|
66
.github/workflows/coverage.yml
vendored
Normal file
66
.github/workflows/coverage.yml
vendored
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
name: Code Coverage
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
coverage:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
cache: pip
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -e ".[dev]"
|
||||||
|
pip install pytest-cov
|
||||||
|
|
||||||
|
- name: Run coverage tests in parallel
|
||||||
|
run: |
|
||||||
|
# Create a simple script to run coverage tests in parallel
|
||||||
|
cat > run_parallel_coverage.py << 'EOF'
|
||||||
|
import concurrent.futures
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def run_coverage(args):
|
||||||
|
test_path, module_path = args
|
||||||
|
cmd = ['python', '-m', 'devscripts.run_coverage', test_path, module_path]
|
||||||
|
return subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
|
coverage_tests = [
|
||||||
|
('test/test_utils.py', 'yt_dlp.utils'),
|
||||||
|
('test/test_YoutubeDL.py', 'yt_dlp.YoutubeDL'),
|
||||||
|
('test/devscripts', 'devscripts')
|
||||||
|
]
|
||||||
|
|
||||||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
|
||||||
|
futures = [executor.submit(run_coverage, test) for test in coverage_tests]
|
||||||
|
for future in concurrent.futures.as_completed(futures):
|
||||||
|
try:
|
||||||
|
future.result()
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error running coverage: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Run the script
|
||||||
|
python run_parallel_coverage.py
|
||||||
|
|
||||||
|
- name: Archive coverage results
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-report
|
||||||
|
path: |
|
||||||
|
.coverage-reports/html/
|
||||||
|
.coverage-reports/coverage.xml
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -127,3 +127,6 @@ yt-dlp.zip
|
||||||
# Plugins
|
# Plugins
|
||||||
ytdlp_plugins/
|
ytdlp_plugins/
|
||||||
yt-dlp-plugins
|
yt-dlp-plugins
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
/.coverage-reports/
|
||||||
|
|
5
devscripts/cov-combine
Executable file
5
devscripts/cov-combine
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# This script is a helper for the Hatch test coverage command
|
||||||
|
# It's called by `hatch test --cover`
|
||||||
|
|
||||||
|
coverage combine "$@"
|
105
devscripts/run_coverage.py
Executable file
105
devscripts/run_coverage.py
Executable file
|
@ -0,0 +1,105 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Script to run coverage tests for yt-dlp
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# python -m devscripts.run_coverage [test_path] [module_path] [additional pytest args]
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# python -m devscripts.run_coverage # Test everything
|
||||||
|
# python -m devscripts.run_coverage test/devscripts # Test devscripts
|
||||||
|
# python -m devscripts.run_coverage test/test_utils.py yt_dlp.utils # Test specific module
|
||||||
|
# python -m devscripts.run_coverage test/test_utils.py "yt_dlp.utils,yt_dlp.YoutubeDL" # Test multiple modules
|
||||||
|
# python -m devscripts.run_coverage test -v # With verbosity
|
||||||
|
#
|
||||||
|
# Using hatch:
|
||||||
|
# hatch run hatch-test:run-cov [args] # Same arguments as above
|
||||||
|
# hatch test --cover # Run all tests with coverage
|
||||||
|
#
|
||||||
|
# Important:
|
||||||
|
# - Always run this script from the project root directory
|
||||||
|
# - Test paths are relative to the project root
|
||||||
|
# - Module paths use Python import syntax (with dots)
|
||||||
|
# - Coverage reports are generated in .coverage-reports/
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
script_dir = Path(__file__).parent
|
||||||
|
repo_root = script_dir.parent
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = sys.argv[1:]
|
||||||
|
|
||||||
|
if not args:
|
||||||
|
# Default to running all tests
|
||||||
|
test_path = 'test'
|
||||||
|
module_path = 'yt_dlp,devscripts'
|
||||||
|
elif len(args) == 1:
|
||||||
|
test_path = args[0]
|
||||||
|
# Try to guess the module path from the test path
|
||||||
|
if test_path.startswith('test/devscripts'):
|
||||||
|
module_path = 'devscripts'
|
||||||
|
elif test_path.startswith('test/'):
|
||||||
|
module_path = 'yt_dlp'
|
||||||
|
else:
|
||||||
|
module_path = 'yt_dlp,devscripts'
|
||||||
|
else:
|
||||||
|
test_path = args[0]
|
||||||
|
module_path = args[1]
|
||||||
|
|
||||||
|
# Initialize coverage reports directory
|
||||||
|
cov_dir = repo_root / '.coverage-reports'
|
||||||
|
cov_dir.mkdir(exist_ok=True)
|
||||||
|
html_dir = cov_dir / 'html'
|
||||||
|
html_dir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# Run pytest with coverage
|
||||||
|
cmd = [
|
||||||
|
'python', '-m', 'pytest',
|
||||||
|
f'--cov={module_path}',
|
||||||
|
'--cov-config=.coveragerc',
|
||||||
|
'--cov-report=term-missing',
|
||||||
|
test_path,
|
||||||
|
]
|
||||||
|
|
||||||
|
if len(args) > 2:
|
||||||
|
cmd.extend(args[2:])
|
||||||
|
|
||||||
|
print(f'Running coverage on {test_path} for module(s) {module_path}')
|
||||||
|
print(f'Command: {" ".join(cmd)}')
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
|
# Generate reports after the test run in parallel
|
||||||
|
import concurrent.futures
|
||||||
|
|
||||||
|
def generate_html_report():
|
||||||
|
return subprocess.run([
|
||||||
|
'python', '-m', 'coverage', 'html',
|
||||||
|
], check=True)
|
||||||
|
|
||||||
|
def generate_xml_report():
|
||||||
|
return subprocess.run([
|
||||||
|
'python', '-m', 'coverage', 'xml',
|
||||||
|
], check=True)
|
||||||
|
|
||||||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
|
||||||
|
html_future = executor.submit(generate_html_report)
|
||||||
|
xml_future = executor.submit(generate_xml_report)
|
||||||
|
# Wait for both tasks to complete
|
||||||
|
concurrent.futures.wait([html_future, xml_future])
|
||||||
|
|
||||||
|
print(f'\nCoverage reports saved to {cov_dir.as_posix()}')
|
||||||
|
print(f'HTML report: open {cov_dir.as_posix()}/html/index.html')
|
||||||
|
return result.returncode
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f'Error running coverage: {e}')
|
||||||
|
return e.returncode
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
|
@ -81,6 +81,7 @@ static-analysis = [
|
||||||
test = [
|
test = [
|
||||||
"pytest~=8.1",
|
"pytest~=8.1",
|
||||||
"pytest-rerunfailures~=14.0",
|
"pytest-rerunfailures~=14.0",
|
||||||
|
"pytest-cov~=6.0",
|
||||||
]
|
]
|
||||||
pyinstaller = [
|
pyinstaller = [
|
||||||
"pyinstaller>=6.11.1", # Windows temp cleanup fixed in 6.11.1
|
"pyinstaller>=6.11.1", # Windows temp cleanup fixed in 6.11.1
|
||||||
|
@ -161,11 +162,12 @@ features = ["test"]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pytest-randomly~=3.15",
|
"pytest-randomly~=3.15",
|
||||||
"pytest-xdist[psutil]~=3.5",
|
"pytest-xdist[psutil]~=3.5",
|
||||||
|
"pytest-cov~=6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.hatch.envs.hatch-test.scripts]
|
[tool.hatch.envs.hatch-test.scripts]
|
||||||
run = "python -m devscripts.run_tests {args}"
|
run = "python -m devscripts.run_tests {args}"
|
||||||
run-cov = "echo Code coverage not implemented && exit 1"
|
run-cov = "python -m devscripts.run_coverage {args}"
|
||||||
|
|
||||||
[[tool.hatch.envs.hatch-test.matrix]]
|
[[tool.hatch.envs.hatch-test.matrix]]
|
||||||
python = [
|
python = [
|
||||||
|
|
39
test/README.md
Normal file
39
test/README.md
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# yt-dlp Tests
|
||||||
|
|
||||||
|
This directory contains tests for the yt-dlp codebase.
|
||||||
|
|
||||||
|
## Running Tests
|
||||||
|
|
||||||
|
### Using hatch (requires `pip install hatch`)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run tests for a specific test file
|
||||||
|
hatch run hatch-test:run test/test_utils.py
|
||||||
|
|
||||||
|
# Run a specific test class or method
|
||||||
|
hatch run hatch-test:run test/test_utils.py::TestUtil
|
||||||
|
hatch run hatch-test:run test/test_utils.py::TestUtil::test_url_basename
|
||||||
|
|
||||||
|
# Run with verbosity
|
||||||
|
hatch run hatch-test:run -- test/test_utils.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using pytest directly
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run a specific test file
|
||||||
|
python -m pytest test/test_utils.py
|
||||||
|
|
||||||
|
# Run a specific test class or method
|
||||||
|
python -m pytest test/test_utils.py::TestUtil
|
||||||
|
python -m pytest test/test_utils.py::TestUtil::test_url_basename
|
||||||
|
|
||||||
|
# Run with verbosity
|
||||||
|
python -m pytest -v test/test_utils.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important:** Always run tests from the project root directory, not from a subdirectory.
|
||||||
|
|
||||||
|
## Code Coverage
|
||||||
|
|
||||||
|
For information on running tests with code coverage, see the documentation in `.coverage-reports/README.md`.
|
Loading…
Reference in a new issue