Files
wehub-resource-sync 2cab53bc94
Test Vector Database Adaptors / Test MCP Vector DB Tools (push) Has been cancelled
Tests / Code Quality (Ruff & Mypy) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (macos-latest, 3.11) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (macos-latest, 3.12) (push) Has been cancelled
Tests / Tests (push) Has been cancelled
Docker Publish / Build and Push Docker Images (map[description:Skill Seekers CLI - Convert documentation to AI skills dockerfile:Dockerfile name:skill-seekers]) (push) Has been cancelled
Docker Publish / Build and Push Docker Images (map[description:Skill Seekers MCP Server - 25 tools for AI assistants dockerfile:Dockerfile.mcp name:skill-seekers-mcp]) (push) Has been cancelled
Docker Publish / Test Docker Images (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.10) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.11) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.12) (push) Has been cancelled
Tests / Serial / Integration / E2E Tests (push) Has been cancelled
Tests / MCP Server Tests (push) Has been cancelled
Test Vector Database Adaptors / Test chroma Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test faiss Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test qdrant Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test weaviate Adaptor (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:46:28 +08:00

16 KiB
Raw Permalink Blame History

代码质量标准

版本: 3.6.0 最后更新: 2026-02-18 状态: 生产就绪


概述

Skill Seekers 通过自动化 lint 检查、全面的测试和持续集成来保持高代码质量。本文档概述了用于确保可靠性和可维护性的质量标准、工具和流程。

质量支柱:

  1. Lint 检查 - 使用 Ruff 进行自动化代码风格和错误检测
  2. 测试 - 全面的测试覆盖(1,880+ 测试)
  3. 类型安全 - 类型提示与验证
  4. 安全 - 使用 Bandit 进行安全扫描
  5. CI/CD - 每次提交的自动化验证

使用 Ruff 进行 Lint 检查

什么是 Ruff

Ruff 是一个用 Rust 编写的极速 Python linter,集成了多个工具的功能:

  • Flake8(风格检查)
  • isort(导入排序)
  • Black(代码格式化)
  • pyupgradePython 版本升级)
  • 以及 100+ 其他 lint 规则

为什么选择 Ruff

  • 比传统 linter 快 10-100 倍
  • 🔧 大多数问题可自动修复
  • 📦 一个工具替代 10+ 个传统工具
  • 🎯 全面的规则覆盖

安装

# Using uv (recommended)
uv pip install ruff

# Using pip
pip install ruff

# Development installation
pip install -e ".[dev]"  # Includes ruff

运行 Ruff

检查问题

# Check all Python files
ruff check .

# Check specific directory
ruff check src/

# Check specific file
ruff check src/skill_seekers/cli/doc_scraper.py

# Check with auto-fix
ruff check --fix .

格式化代码

# Check formatting (dry run)
ruff format --check .

# Apply formatting
ruff format .

# Format specific file
ruff format src/skill_seekers/cli/doc_scraper.py

配置

Ruff 配置位于 pyproject.toml

[tool.ruff]
line-length = 100
target-version = "py310"

[tool.ruff.lint]
select = [
    "E",    # pycodestyle errors
    "W",    # pycodestyle warnings
    "F",    # pyflakes
    "I",    # isort
    "B",    # flake8-bugbear
    "SIM",  # flake8-simplify
    "UP",   # pyupgrade
]

ignore = [
    "E501",  # Line too long (handled by formatter)
]

[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = [
    "S101",  # Allow assert in tests
]

常见 Ruff 规则

SIM102:简化嵌套 If 语句

修改前:

if condition1:
    if condition2:
        do_something()

修改后:

if condition1 and condition2:
    do_something()

原因: 提高可读性,减少嵌套层级。

SIM117:合并多个 With 语句

修改前:

with open('file1.txt') as f1:
    with open('file2.txt') as f2:
        process(f1, f2)

修改后:

with open('file1.txt') as f1, open('file2.txt') as f2:
    process(f1, f2)

原因: 语法更简洁,资源管理更好。

B904:正确的异常链

修改前:

try:
    risky_operation()
except Exception:
    raise CustomError("Failed")

修改后:

try:
    risky_operation()
except Exception as e:
    raise CustomError("Failed") from e

原因: 保留错误上下文,便于调试。

SIM113:移除未使用的 Enumerate 计数器

修改前:

for i, item in enumerate(items):
    process(item)  # i is never used

修改后:

for item in items:
    process(item)

原因: 意图更清晰,移除未使用的变量。

B007:未使用的循环变量

修改前:

for item in items:
    total += 1  # item is never used

修改后:

for _ in items:
    total += 1

原因: 明确表示循环变量是有意不使用的。

ARG002:未使用的方法参数

修改前:

def process(self, data, unused_arg):
    return data.transform()  # unused_arg never used

修改后:

def process(self, data):
    return data.transform()

原因: 移除死代码,使函数签名更清晰。


近期代码质量改进

v3.6.0 修复(2026 年 1 月 18 日)

修复了代码库中全部 21 个 ruff lint 错误

规则 数量 受影响文件 影响
SIM102 7 config_extractor.py、pattern_recognizer.py3 处) 合并嵌套 if 语句
SIM117 9 test_example_extractor.py3 处)、unified_skill_builder.py 合并 with 语句
B904 1 pdf_scraper.py 添加异常链
SIM113 1 config_validator.py 移除未使用的 enumerate 计数器
B007 1 doc_scraper.py 将未使用的循环变量改为 _
ARG002 1 测试 fixture 移除未使用的测试参数
总计 21 12 个文件 零 lint 错误

结果: 代码库干净无 lint 错误,可维护性提升。

已更新的文件

  1. src/skill_seekers/cli/config_extractor.pySIM102 修复)
  2. src/skill_seekers/cli/config_validator.pySIM113 修复)
  3. src/skill_seekers/cli/doc_scraper.pyB007 修复)
  4. src/skill_seekers/cli/pattern_recognizer.py3 处 SIM102 修复)
  5. src/skill_seekers/cli/test_example_extractor.py3 处 SIM117 修复)
  6. src/skill_seekers/cli/unified_skill_builder.pySIM117 修复)
  7. src/skill_seekers/cli/pdf_scraper.pyB904 修复)
  8. 6 个测试文件(各类修复)

测试要求

测试覆盖标准

关键路径: 要求 100% 覆盖

  • 核心抓取逻辑
  • 平台适配器
  • MCP 工具实现
  • 配置验证

整体项目: 覆盖率目标 >80%

当前状态:

  • 1,880+ 测试通过
  • 代码覆盖率 >85%
  • 所有关键路径已覆盖
  • 已集成 CI/CD

运行测试

全部测试

# Run all tests
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=src/skill_seekers --cov-report=term --cov-report=html

# View HTML coverage report
open htmlcov/index.html

特定测试类别

# Unit tests only
pytest tests/test_*.py -v

# Integration tests
pytest tests/test_*_integration.py -v

# E2E tests
pytest tests/test_*_e2e.py -v

# MCP tests
pytest tests/test_mcp*.py -v

测试标记

# Slow tests (skip by default)
pytest tests/ -m "not slow"

# Run slow tests
pytest tests/ -m slow

# Async tests
pytest tests/ -m asyncio

测试类别

  1. 单元测试800+ 测试)

    • 单个函数测试
    • 隔离的组件测试
    • 模拟外部依赖
  2. 集成测试300+ 测试)

    • 多组件工作流
    • 端到端功能测试
    • 真实文件系统操作
  3. E2E 测试100+ 测试)

    • 完整用户工作流
    • CLI 命令测试
    • 平台集成测试
  4. MCP 测试63 个测试)

    • 全部 40 个 MCP 工具
    • 传输模式测试(stdio、HTTP
    • 错误处理验证

提交前的测试要求

根据 ~/.claude/CLAUDE.md 中的用户指令:

"never skip any test. always make sure all test pass"

这意味着:

  • 提交前全部 1,880+ 测试必须通过
  • 不跳过任何测试,即使它们很慢
  • 为新功能添加测试
  • 立即修复失败的测试
  • 保持或提升覆盖率

CI/CD 集成

GitHub Actions 工作流

Skill Seekers 使用 GitHub Actions 对每次提交和 PR 进行自动化质量检查。

工作流配置

# .github/workflows/ci.yml (excerpt)
name: CI

on:
  push:
    branches: [main, development]
  pull_request:
    branches: [main, development]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install ruff

      - name: Run Ruff Check
        run: ruff check .

      - name: Run Ruff Format Check
        run: ruff format --check .

  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
        python-version: ['3.10', '3.11', '3.12', '3.13']

    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install package
        run: pip install -e ".[all-llms,dev]"

      - name: Run tests
        run: pytest tests/ --cov=src/skill_seekers --cov-report=xml

      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage.xml

CI 检查

每次提交和 PR 必须通过:

  1. Ruff Lint 检查 - 零 lint 错误
  2. Ruff 格式检查 - 一致的代码风格
  3. Pytest - 全部 1,880+ 测试通过
  4. 覆盖率 - 代码覆盖率 >80%
  5. 多平台 - Ubuntu + macOS
  6. 多版本 - Python 3.10-3.13

状态: 所有检查通过


Pre-commit 钩子

设置

# Install pre-commit
pip install pre-commit

# Install hooks
pre-commit install

配置

创建 .pre-commit-config.yaml

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.7.0
    hooks:
      # Run ruff linter
      - id: ruff
        args: [--fix]
      # Run ruff formatter
      - id: ruff-format

  - repo: local
    hooks:
      # Run tests before commit
      - id: pytest
        name: pytest
        entry: pytest
        language: system
        pass_filenames: false
        always_run: true
        args: [tests/, -v]

使用

# Pre-commit hooks run automatically on git commit
git add .
git commit -m "Your message"
# → Runs ruff check, ruff format, pytest

# Run manually on all files
pre-commit run --all-files

# Skip hooks (emergency only!)
git commit -m "Emergency fix" --no-verify

最佳实践

代码组织

导入顺序

# 1. Standard library imports
import os
import sys
from pathlib import Path

# 2. Third-party imports
import anthropic
import requests
from fastapi import FastAPI

# 3. Local application imports
from skill_seekers.cli.doc_scraper import scrape_all
from skill_seekers.cli.adaptors import get_adaptor

工具: Ruff 通过 I 规则自动排序导入。

命名约定

# Constants: UPPER_SNAKE_CASE
MAX_PAGES = 500
DEFAULT_TIMEOUT = 30

# Classes: PascalCase
class DocumentationScraper:
    pass

# Functions/variables: snake_case
def scrape_all(base_url, config):
    pages_count = 0
    return pages_count

# Private: leading underscore
def _internal_helper():
    pass

文档

文档字符串

def scrape_all(base_url: str, config: dict) -> list[dict]:
    """Scrape documentation from a website using BFS traversal.

    Args:
        base_url: The root URL to start scraping from
        config: Configuration dict with selectors and patterns

    Returns:
        List of page dictionaries containing title, content, URL

    Raises:
        NetworkError: If connection fails
        InvalidConfigError: If config is malformed

    Example:
        >>> pages = scrape_all('https://docs.example.com', config)
        >>> len(pages)
        42
    """
    pass

类型提示

from typing import Optional, Union, Literal

def package_skill(
    skill_dir: str | Path,
    target: Literal['claude', 'gemini', 'openai', 'markdown'],
    output_path: Optional[str] = None
) -> str:
    """Package skill for target platform."""
    pass

错误处理

异常模式

# Good: Specific exceptions with context
try:
    result = risky_operation()
except NetworkError as e:
    raise ScrapingError(f"Failed to fetch {url}") from e

# Bad: Bare except
try:
    result = risky_operation()
except:  # ❌ Too broad, loses error info
    pass

日志记录

import logging

logger = logging.getLogger(__name__)

# Log at appropriate levels
logger.debug("Processing page: %s", url)
logger.info("Scraped %d pages", len(pages))
logger.warning("Rate limit approaching: %d requests", count)
logger.error("Failed to parse: %s", url, exc_info=True)

安全扫描

Bandit

Bandit 扫描 Python 代码中的安全漏洞。

安装

pip install bandit

运行 Bandit

# Scan all Python files
bandit -r src/

# Scan with config
bandit -r src/ -c pyproject.toml

# Generate JSON report
bandit -r src/ -f json -o bandit-report.json

常见安全问题

B404:导入 subprocess 模块

# Review: Ensure safe usage of subprocess
import subprocess

# ✅ Safe: Using subprocess with shell=False and list arguments
subprocess.run(['ls', '-l'], shell=False)

# ❌ UNSAFE: Using shell=True with user input (NEVER DO THIS)
# This is an example of what NOT to do - security vulnerability!
# subprocess.run(f'ls {user_input}', shell=True)

B605:通过 shell 启动进程

# ❌ UNSAFE: Shell injection risk (NEVER DO THIS)
# Example of security anti-pattern:
# import os
# os.system(f'rm {filename}')

# ✅ Safe: Use subprocess with list arguments
import subprocess
subprocess.run(['rm', filename], shell=False)

安全最佳实践:

  • 切勿对用户输入使用 shell=True
  • 始终验证和清理用户输入
  • 使用带列表参数的 subprocess 而不是 shell 命令
  • 避免动态构造命令

开发工作流

1. 开始工作前

# Pull latest changes
git checkout development
git pull origin development

# Create feature branch
git checkout -b feature/your-feature

# Install dependencies
pip install -e ".[all-llms,dev]"

2. 开发过程中

# Run linter frequently
ruff check src/skill_seekers/cli/your_file.py --fix

# Run relevant tests
pytest tests/test_your_feature.py -v

# Check formatting
ruff format src/skill_seekers/cli/your_file.py

3. 提交前

# Run all linting checks
ruff check .
ruff format --check .

# Run full test suite (REQUIRED)
pytest tests/ -v

# Check coverage
pytest tests/ --cov=src/skill_seekers --cov-report=term

# Verify all tests pass ✅

4. 提交更改

# Stage changes
git add .

# Commit (pre-commit hooks will run)
git commit -m "feat: Add your feature

- Detailed change 1
- Detailed change 2

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"

# Push to remote
git push origin feature/your-feature

5. 创建 Pull Request

# Create PR via GitHub CLI
gh pr create --title "Add your feature" --body "Description..."

# CI checks will run automatically:
# ✅ Ruff linting
# ✅ Ruff formatting
# ✅ Pytest (1,880+ tests)
# ✅ Coverage report
# ✅ Multi-platform (Ubuntu + macOS)
# ✅ Multi-version (Python 3.10-3.13)

质量指标

当前状态(v3.6.0

指标 数值 目标 状态
Lint 错误 0 0
测试数量 1200+ 1000+
测试通过率 100% 100%
代码覆盖率 >85% >80%
CI 通过率 100% >95%
Python 版本 3.10-3.13 3.10+
平台 Ubuntu、macOS 2+

历史改进

版本 Lint 错误 测试 覆盖率
v2.5.0 38 602 75%
v2.6.0 21 700+ 80%
v2.7.0 0 1200+ 85%+

进展: 所有质量指标持续改进。


故障排除

常见问题

1. 更新后出现 Lint 错误

# Update ruff
pip install --upgrade ruff

# Re-run checks
ruff check .

2. 本地测试失败

# Ensure package is installed
pip install -e ".[all-llms,dev]"

# Clear pytest cache
rm -rf .pytest_cache/
rm -rf **/__pycache__/

# Re-run tests
pytest tests/ -v

3. 覆盖率过低

# Generate detailed coverage report
pytest tests/ --cov=src/skill_seekers --cov-report=html

# Open report
open htmlcov/index.html

# Identify untested code (red lines)
# Add tests for uncovered lines

相关文档


版本: 3.6.0 最后更新: 2026-02-18 状态: 生产就绪