mirror of https://github.com/yt-dlp/yt-dlp
Merge 262ff0817d
into 74e90dd9b8
commit
b1ba94eb1c
@ -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
|
@ -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())
|
@ -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 New Issue