Skip to main content

在差异上运行覆盖率和 linting 报告

项目描述

自动查找需要测试覆盖的差异行。还可以找到存在违规的差异行(根据 pycodestyle、pyflakes、flake8 或 pylint 等工具)。这在代码审查期间用作代码质量指标。

概述

差异覆盖率是测试覆盖的新行或修改行的百分比。这为代码审查提供了一个清晰且可实现的标准:如果您触及一行代码,则应覆盖该行。代码覆盖率是每个开发人员的责任!

diff-cover命令行工具将XML 覆盖率报告与git diff的输出进行比较。然后它报告差异中行的覆盖率信息。

目前,diff-cover要求:

  • 您正在使用git进行版本控制。

  • 您的测试运行程序会生成 Cobertura、Clover 或 JaCoCo XML 格式的覆盖率报告。

支持的 XML 覆盖率报告可以使用许多覆盖率工具生成,包括:

diff-cover设计为可扩展的。如果您有兴趣添加对其他版本控制系统或覆盖率报告格式的支持,请参阅下文以获取有关如何贡献的信息!

安装

要安装最新版本:

pip install diff_cover

要安装开发版本:

git clone https://github.com/Bachmann1234/diff-cover.git
cd diff-cover
python setup.py install

入门

  1. 将当前工作目录设置为git存储库。

  2. 在覆盖范围内运行您的测试套件并生成 [Cobertura、Clover 或 JaCoCo] XML 报告。例如,使用pytest-cov

pytest --cov --cov-report=xml

这将在当前工作目录中创建一个coverage.xml文件。

注意:如果您使用不同的覆盖率生成器,则需要使用不同的命令来生成覆盖率 XML 报告。

  1. 运行diff-cover

diff-cover coverage.xml

这会将当前的git分支与origin/main进行比较,并将差异覆盖率报告打印到控制台。

您还可以生成报告的 HTML、JSON 或 Markdown 版本:

diff-cover coverage.xml --html-report report.html
diff-cover coverage.xml --json-report report.json
diff-cover coverage.xml --markdown-report report.md

多个 XML 覆盖率报告

如果一个人有来自多个测试套件的多个 xml 报告,您可以通过运行diff-cover并将多个覆盖率报告作为参数来获得组合覆盖率报告(如果一行被任何 xml 报告覆盖,则将其计为已覆盖). 您可以指定任意数量的覆盖率报告:

diff-cover coverage1.xml coverage2.xml

质量覆盖

您也可以通过运行diff-quality来使用 diff-cover 查看有关 diff 的质量报告 。

diff-quality --violations=<tool>

其中工具是要使用的质量检查器。目前支持 pycodestylepyflakesflake8pylintcheckstylecheckstylexml,但可以(并且应该!)支持更多的检查器。 请参阅“为新的质量检查器添加diff-quality支持”部分。

注意:没有办法从diff-quality运行findbugs ,因为它在生成的 java 字节码上运行,应该集成到构建框架中。

diff-cover一样,可以使用 HTML、JSON 或 Markdown 报告生成

diff-quality --violations=<tool> --html-report report.html
diff-quality --violations=<tool> --json-report report.json
diff-quality --violations=<tool> --markdown-report report.md

如果您已经使用pycodestylepyflakesflake8pylintcheckstylecheckstylexmlfindbugs生成报告,则可以将报告传递给diff-quality。这比让diff-quality重新运行 pycodestylepyflakesflake8pylintcheckstylecheckstylexml更有效。

# For pylint < 1.0
pylint -f parseable > pylint_report.txt

# For pylint >= 1.0
pylint --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" > pylint_report.txt

# Use the generated pylint report when running diff-quality
diff-quality --violations=pylint pylint_report.txt

# Use a generated pycodestyle report when running diff-quality.
pycodestyle > pycodestyle_report.txt
diff-quality --violations=pycodestyle pycodestyle_report.txt

请注意,您必须使用-f可解析选项为低于 1.0 的 pylint 版本 生成pylint报告,为 >= 1.0 的版本生成--msg-template选项。

diff-quality还将接受多个pycodestyle pyflakes flake8pylint报告:

diff-quality --violations=pylint report_1.txt report_2.txt

如果您需要传递其他选项,您可以使用选项标志

diff-quality --violations=pycodestyle --options="--exclude='*/migrations*' --statistics" pycodestyle_report.txt

比较分支

默认情况下,diff-cover将当前分支与origin/main进行比较。要指定不同的比较分支:

diff-cover coverage.xml --compare-branch=origin/release

失败

如果报告质量/覆盖率百分比低于某个阈值,要让diff-coverdiff-quality返回非零状态代码,请指定 fail-under 参数

diff-cover coverage.xml --fail-under=80
diff-quality --violations=pycodestyle --fail-under=80

如果覆盖率或质量分数低于 80%,上述将返回非零状态。

排除/包含路径

diff-coverdiff-quality都可以显式排除路径,而仅diff-quality支持包含(自 5.1.0 起)。

exclude 选项与fnmatch一起使用,与glob一起使用。这两个选项都可以使用多个值。包含选项应该用双引号括起来,以防止 shell 通配符。它们也应该相对于当前的 git 目录。

diff-cover coverage.xml --exclude setup.py
diff-quality --violations=pycodestyle --exclude setup.py

diff-quality --violations=pycodestyle --include project/foo/**

对每个更改的文件执行以下操作:

  1. 检查是否指定了任何包含模式

  2. 如果是,请检查更改的文件是否是至少一个包含模式的一部分

  3. 检查文件是否属于任何排除模式

根据 git 中的文件状态忽略/包含

diff-coverdiff-quality都允许用户忽略和包含基于 git 状态的文件:staged、unstaged、untracked:

  • --ignore-staged:忽略所有暂存文件(默认包括它们)

  • --ignore-unstaged:忽略所有未暂存的文件(默认包括它们)

  • --include-untracked:包括所有未跟踪的文件(默认忽略它们)

静音模式

diff-coverdiff-quality都支持默认禁用的安静模式。可以使用-q / --quiet标志启用它:

diff-cover coverage.xml -q
diff-quality --violations=pycodestyle -q

如果启用,该工具将仅打印错误和失败,但不打印信息或警告消息。

配置文件

这两种工具都允许用户使用–config-file / -c在配置文件中指定选项:

diff-cover coverage.xml --config-file myconfig.toml
diff-quality --violations=pycodestyle --config-file myconfig.toml

目前,仅支持 TOML 文件。请注意,仅支持非强制性选项。如果在配置文件和命令行中指定了选项,则使用命令行的值。

TOML 配置

解析器只会对以.toml结尾的配置文件做出反应。要使用它,请安装带有额外要求toml的diff-cover

选项名称与命令行上的相同,但所有破折号都应为下划线。如果一个选项可以被指定多次,那么配置值应该被指定为一个列表。

[tool.diff_cover]
compare_branch = <s>"origin/feature"</s>
quiet = true

[tool.diff_quality]
compare_branch = <s>"origin/feature"</s>
ignore_staged = true

故障排除

问题diff-cover总是报告:“此 diff 中没有包含覆盖信息的行。”

解决方案diff-cover将覆盖率 XML 报告中的源文件与git diff中的源文件匹配。因此,文件的相对路径匹配很重要。如果您使用coverage.py 生成覆盖率 XML 报告,请确保 从同一工作目录运行diff-cover 。

问题GitDiffTool._execute()引发错误:

fatal: ambiguous argument 'origin/main...HEAD': unknown revision or path not in the working tree.

众所周知,在Travis CI中运行diff-cover时会发生这种情况

解决方案:在运行diff-cover之前获取远程主分支:

git fetch origin master:refs/remotes/origin/main

问题差异质量报告“diff_cover.violations_reporter.QualityReporterError:未找到配置文件,使用默认配置”

解决方案:您的项目需要一个pylintrc文件。提供这个文件(它可以是空的)并且diff-quality应该没有问题地运行。

问题差异质量报告“未安装质量工具”

解决方案diff-quality假设您已经安装了您希望针对您的 diff 运行的工具。如果您没有它,请使用您最喜欢的包管理器安装它。

问题diff-quality报告没有质量问题

解决方案:您可以使用类似diff-quality --violations foo *.py的模式。最后一个参数不用于指定文件,而是用于质量工具报告。删除它以解决问题

执照

此存储库中的代码在 Apache 2.0 许可下获得许可。有关详细信息,请参阅LICENSE.txt

如何贡献

贡献是非常受欢迎的。最简单的方法是 fork 这个 repo,然后从你的 fork 发出 pull request。

注意:diff-quality支持插件模型,因此可以集成新工具而无需更改此 repo。 请参阅“为新的质量检查器添加diff-quality支持”部分。

为发展做准备

这个项目是用诗歌管理的,可以用pip安装。 诗歌管理 python 虚拟环境并组织依赖项。它还打包了这个项目。

pip install poetry
poetry install

我还建议在之后运行此命令。这将使 git blame 忽略格式化整个代码库的提交。

git config blame.ignoreRevsFile .git-blame-ignore-revs

为新的质量检查器添加diff-quality支持

添加对新质量检查器的支持很简单。diff-quality支持使用流行的 Python 插件包的插件。

如果质量检查器已经作为 Python 包实现,那就太好了!如果没有, 请创建一个 Python 包 来托管插件实现。

在 Python 包的setup.py文件中,定义插件的入口点,例如

setup(
    ...
    entry_points={
        'diff_cover': [
            'sqlfluff = sqlfluff.diff_quality_plugin'
        ],
    },
    ...
)

笔记:

  • 入口点的字典键必须命名为diff_cover

  • 该值必须采用TOOL_NAME = YOUR_PACKAGE.PLUGIN_MODULE格式

安装包后,diff-quality使用此信息根据提供给diff-quality命令的--violations选项的工具名称查找工具包和模块 ,例如:

$ diff-quality --violations sqlfluff

插件实现将类似于下面的示例。这是一个基于工作插件实现的简化示例。

from diff_cover.hook import hookimpl as diff_cover_hookimpl
from diff_cover.violationsreporters.base import BaseViolationReporter, Violation

class SQLFluffViolationReporter(BaseViolationReporter):
    supported_extensions = ['sql']

    def __init__(self):
        super(SQLFluffViolationReporter, self).__init__('sqlfluff')

    def violations(self, src_path):
        return [
            Violation(violation.line_number, violation.description)
            for violation in get_linter().get_violations(src_path)
        ]

    def measured_lines(self, src_path):
        return None

    @staticmethod
    def installed():
        return True


@diff_cover_hookimpl
def diff_cover_report_quality():
    return SQLFluffViolationReporter()

重要笔记:

  • diff-quality正在寻找插件功能:

    • 位于setup.py入口点中列出的包的模块中。

    • 标有@diff_cover_hookimpl装饰器

    • 名为diff_cover_report_quality(这将它与diff_cover可能支持的任何其他插件类型区分开来。)

  • 该函数应返回具有以下属性和方法的对象:

    • 带有支持的文件扩展名列表的supported_extensions属性

    • 违规()函数,返回指定src_path的违规对象列表。有关此函数和其他可能的报告相关方法的更多详细信息,请参阅此处的BaseViolationReporter类 。

特别感谢

向 diff-cover Will Daly的原作者和 diff-quality Sarina Canelake的原作者大喊。

最初在edX的支持下创建。