roave/infection-static-analysis-plugin

基于突变测试的静态分析 - 根据静态分析防止逃逸突变无效


README

此插件旨在在 infection/infection 测试运行的基础上执行静态分析,以发现 逃逸突变 是否是有效的突变,或者它们是否不遵守您程序的类型签名。如果突变会导致类型错误,则将其“杀死”。

TL;DR

  • 这将提高您的突变分数,因为导致类型错误的突变会被杀死。
  • 这非常不正规,实际上替换了 vendor/bin/infection。请首先阅读下面的 稳定性 部分。
  • 目前,这比单独运行 infection 慢得多。未来有想法和建议来改进这一点。

使用方法

此工具当前的设计要求您运行 vendor/bin/roave-infection-static-analysis-plugin 而不是运行 vendor/bin/infection

composer require --dev roave/infection-static-analysis-plugin

vendor/bin/roave-infection-static-analysis-plugin

配置

roave-infection-static-analysis-plugin 二进制文件接受所有 infection 标志和参数,以及一个额外的 --psalm-config 参数。

使用 --psalm-config,您可以在分析生成的突变时指定要使用的 psalm 配置文件。

vendor/bin/roave-infection-static-analysis-plugin --psalm-config config/psalm.xml

背景

如果您来自具有 AoT 编译器的静态类型语言,您可能会对此项目的范围感到困惑,但在 PHP 生态系统中,生成不尊重类型系统的可运行代码非常容易,突变测试工具也一直在做这件事。

例如以下片段

/**
 * @template T
 * @param array<T> $values
 * @return list<T>
 */
function makeAList(array $values): array
{
    return array_values($values);
}

给定以下有效测试

function test_makes_a_list(): void
{
    $list = makeAList(['a' => 'b', 'c' => 'd']);
 
    assert(count($list) === 2);
    assert(in_array('b', $list, true));
    assert(in_array('d', $list, true));
}

由于我们没有以更精确的方式验证输出,突变测试框架将生成以下突变

/**
 * @template T
 * @param array<T> $values
 * @return list<T>
 */
function makeAList(array $values): array
{
-    return array_values($values);
+    return $values;
}

上面的代码是有效的 PHP,但根据我们的类型声明并不有效。虽然我们可以为这个写一个测试,但这种测试可能是多余的,因为现有的类型检查器可以检测到我们的实际返回值不再是一个 list<T>,而是一个 array<int|string, T> 的映射,这与我们声明的相冲突。

此插件检测此类突变,并防止它们让您编写不必要的测试,利用现有 PHP 类型检查器(如 phpstanpsalm)的全部功能。

稳定性

由于 infection/infection 尚未设计为支持插件,此工具使用一种非常激进的方法来自举,并依赖于底层运行器内部细节。

为了防止兼容性问题,因此始终固定到 infection/infection 的一个非常特定的版本,因此当您希望使用 infection/infection 的最新和最佳版本时,请耐心等待,因为我们可能仍在努力赶上它。

最终,我们将向 infection/infection 贡献补丁,以便有一个适当的方式来设计和使用插件,而无需进行肮脏的修改。

PHPStan?Psalm?我的最爱静态分析工具在哪里?

对于 1.0.x 的初始工作范围,我们提供 vimeo/psalm 支持,而其他静态分析器将在稍后的时间点加入。