pull/12565/merge
Wilson Bilkovich 2 days ago committed by GitHub
commit b1ba94eb1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -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

@ -0,0 +1,65 @@
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')
]
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

@ -127,3 +127,6 @@ yt-dlp.zip
# Plugins
ytdlp_plugins/
yt-dlp-plugins
# Coverage
/.coverage-reports/

@ -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 "$@"

@ -0,0 +1,103 @@
#!/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'
elif len(args) == 1:
test_path = args[0]
# Try to guess the module path from the test path
if test_path.startswith('test/'):
module_path = 'yt_dlp'
else:
module_path = 'yt_dlp'
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: {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())

@ -80,6 +80,7 @@ static-analysis = [
test = [
"pytest~=8.1",
"pytest-rerunfailures~=14.0",
"pytest-cov~=6.0",
]
pyinstaller = [
"pyinstaller>=6.11.1", # Windows temp cleanup fixed in 6.11.1
@ -160,11 +161,12 @@ features = ["test"]
dependencies = [
"pytest-randomly~=3.15",
"pytest-xdist[psutil]~=3.5",
"pytest-cov~=6.0",
]
[tool.hatch.envs.hatch-test.scripts]
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]]
python = [

@ -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…
Cancel
Save