Test2::Transition - 升级到 Test2 时的过渡说明
这里记录了与 Test2 升级相关的注意事项和问题。升级会导致 Test::Builder 在后台委托给 Test2。这种过渡在大多数情况下是透明的,但有一些情况可能会导致问题。
以下是与新内部结构不兼容的场景列表。
几年前,曾有两项尝试升级/替换 Test::Builder。令人困惑的是,它们分别被称为 Test::Builder2 和 Test::Builder1.5。许多人在代码中添加了条件语句,以检查 Test::Builder 的版本号并相应地调整代码。
Test::Builder2/1.5 项目都已停止。现在,人们添加的条件代码已成为雷区。绝大多数被 Test2 损坏的模块都属于此类。
解决方法是删除所有与 Test::Builder1.5/2 相关的代码。要么使用传统的 Test::Builder API,要么直接使用 Test2。
一些测试模块会用自己的实例或子类替换 Test::Builder 单例实例。这通常是为了拦截或修改发生的結果。
Test::Builder 单例现在是 Test2 的一个简单的兼容性包装器。Test::Builder 单例不再是结果的中心位置。许多结果完全绕过 Test::Builder 单例,这会破坏和改变替换单例时预期的行为。
如果您只是想拦截所有结果,而不是让它们进入 TAP,您应该查看 Test2::API 文档,并了解如何将新的 hub 推送到 hub 堆栈中。临时替换 hub 现在是拦截结果的正确方法。
如果您的目标纯粹是监控事件,请使用 Test::More 导出的 Test2::Hub->listen()
方法来观察事件的触发。如果您希望在结果进入 TAP 之前修改结果,请查看 Test2::Hub->filter()
方法。
一些模块直接查看 Test::Builder 单例上的哈希键。这里的问题是 Test::Builder 单例不再保存任何重要信息。
修复方法是使用 Test2::API 中指定的 API 来查看或修改状态。
早期的一个更改,实际上是让 Test2 成为一个想法的更改,是对子测试注释缩进的更改。人们认为,将子测试注释缩进而不是与子测试保持一致,可读性会更高。
# subtest foo
ok 1 - blah
1..1
ok 1 - subtest foo
旧的样式缩进了注释
# subtest foo
ok 1 - blah
1..1
ok 1 - subtest foo
这会破坏对 TAP 输出进行字符串比较的测试。
my $indent = $INC{'Test2/API.pm'} ? '' : ' ';
is(
$subtest_output,
"${indent}# subtest foo",
"Got subtest note"
);
检查 $INC{'Test2/API.pm'}
是否已设置,如果已设置,则不应期望缩进。如果未设置,则使用旧的 Test::Builder,应期望缩进。
这是一个已知在升级过程中出现过问题的 cpan 模块列表。
这些模块仍然可以正常工作,但它们的测试套件不会通过。如果您已经安装了这些模块,则可以继续使用它们。如果您在升级 Test::Builder 后尝试安装它们,则需要强制安装或绕过损坏的测试。
此模块有一个测试似乎绕过了 Test::Builder 的错误。该错误似乎已由 Test2 修复,这意味着解决方法会导致失败。这很容易更新,但还没有人这样做。
已知在以下版本中出现问题:1.0.9 及更早版本
测试由于子测试缩进而中断。
已知在版本 0.07 中出现问题。显然在 0.06 中可以正常工作。已提交补丁以解决此问题。
这些是未出现问题但测试套件出现问题且已修复的模块。
旧版本工作正常,但存在一个轻微的测试名称行为问题,这会导致 Test2 出现故障。由于此问题,旧版本将不再安装。CPAN 上的最新版本可以正常安装。升级不是必需的,但建议进行升级。
修复版本:0.43
一些测试依赖于以微妙的方式修改 $!
和 $?
。已应用补丁以更正更改的内容。
模块本身工作正常,无需升级。
修复版本:0.45
一些测试很脆弱,需要在较晚阶段加载 base.pm。Test2 过早加载了 base.pm。测试已更新以修复此问题。
模块本身从未出现故障,您无需升级。
修复版本:0.12
一项测试绕过了现在已修复的规划错误。如果您安装了旧版本,则无需升级。如果您需要,新版本可以正常安装。
修复版本:0.2.5
一些测试很脆弱,但已修复。实际故障来自子测试注释缩进更改。
无需升级,旧版本工作正常。只有新版本才能安装。
修复版本:0.025
此问题是由规划方式的错误修复引起的。测试在错误修复后已更新。
修复版本:0.04
旧版本工作正常,但无法安装,因为 Test::Aggregate 位于依赖链中。无需升级。
修复版本:2.15
一项测试出现故障,因为它依赖于 Scalar::Util 未加载。Test2 加载了 Scalar::Util。测试已更新,在检查 Scalar::Util 的加载状态后加载 Test2。
如果您已安装,则无需升级。
修复版本:1.11
旧版本需要直接访问 Test::Builder 单例哈希元素。CPAN 上的最新版本在旧版 Test::Builder 上仍然会这样做,但在 Test2 上会转而使用 Test2::IPC。
修复版本:0.35
此模块通过覆盖单例上的方法,并直接访问单例上的哈希值来实现。一个新的版本已经发布,它使用 Test2 API 来实现相同的结果,并且更合理。
修复版本:0.07
此模块包含 Test::Builder2 条件语句。通过移除这些条件语句来修复此问题。
修复版本:1.1.4
此模块依赖于 Test::Builder->_try()
,这是一个私有方法,文档中说明了没有人应该使用它。通过使用不同的工具来修复此问题。
修复版本:0.012
0.14 版本依赖于 Test::Builder->history
,该属性在 Test::Builder 1.5 中可用。0.12 和 0.13 版本依赖于其他 Test::Builder 内部机制。
修复版本:0.15
通过应用一个包装 Test::Builder->_print_comment
的角色来实现。通过在 Test2 下运行时添加一个修改消息的事件过滤器来修复此问题。
修复版本:0.007
此发行版直接访问 Test::Builder 单例中的哈希键。它也从错误的角度处理问题,请考虑使用 Test2::Aggregate 来实现类似的功能,以及 Test2::Harness,它允许在 harness 级别进行模块预加载。
截至版本 0.373,仍然存在问题。
此模块直接使用 Test::Builder 单例中的哈希键。由于 Test2 的优势,此模块也已过时。使用来自 Test2::API 的 intercept()
来实现类似的结果。
截至版本 0.3.0,仍然存在问题。
此模块覆盖了 Test::Builder::subtest()
和 Test::Builder::done_testing()
。它还直接访问单例的哈希元素。它尚未修复。
替代方案:Test2::AsyncSubtest 和 Test2::Workflow(不稳定)。
截至版本 0.05,仍然存在问题。
参见 https://github.com/tokuhirom/Test-Pretty/issues/25
作者承认该模块很疯狂,他正在等待一个新的稳定版本(Test2)以一种合理的方式完全重写它。
截至版本 0.32,仍然存在问题。
此模块的测试直接访问 Test::Builder 哈希键。大多数(如果不是全部)这些哈希键都有公共 API 方法,可以用来代替它们,以避免这个问题。
在版本 0.052 中仍然存在。
它对 Test::Builder 进行猴子补丁,并在代码中称之为“黑魔法”。
截至版本 0.20,仍然存在。
它以多种方式修改了 Test::Builder 的内部机制。实现此模块目标的更好方法是编写自己的子测试函数。
截至版本 0.11,仍然存在。
修改 Test::Builder 的内部机制。
截至版本 0.02,仍然存在。
修改 Test::Builder 的内部机制。
截至版本 0.11,仍然存在。
use Test::Builder;
# A majority of tools out there do this:
# my $TB = Test::Builder->new;
# This works, but has always been wrong, forcing Test::Builder to implement
# subtests as a horrific hack. It also causes problems for tools that try
# to replace the singleton (also discouraged).
sub my_ok($;$) {
my ($bool, $name) = @_;
my $TB = Test::Builder->new;
$TB->ok($bool, $name);
}
sub my_diag($) {
my ($msg) = @_;
my $TB = Test::Builder->new;
$TB->diag($msg);
}
use Test2::API qw/context/;
sub my_ok($;$) {
my ($bool, $name) = @_;
my $ctx = context();
$ctx->ok($bool, $name);
$ctx->release;
}
sub my_diag($) {
my ($msg) = @_;
my $ctx = context();
$ctx->diag($msg);
$ctx->release;
}
上下文对象具有以下方法的 API 兼容实现
如果您正在寻找带有 is
、like
等的帮助器,请参阅 Test2::Suite。
use Test::More;
sub exclusive_ok {
my ($bool1, $bool2, $name) = @_;
# Ensure errors are reported 1 level higher
local $Test::Builder::Level = $Test::Builder::Level + 1;
$ok = $bool1 || $bool2;
$ok &&= !($bool1 && $bool2);
ok($ok, $name);
return $bool;
}
从这里到 ok
,再到 ok
调用的任何内容,链中的每个工具都需要递增 $Level
变量。当发生错误时,Test::Builder 将对由 $Level
确定的堆栈帧进行跟踪,并报告该文件+行作为发生错误的位置。如果您或您使用的任何其他工具忘记设置 $Level
,则错误将报告到错误的位置。
use Test::More;
sub exclusive_ok {
my ($bool1, $bool2, $name) = @_;
# Grab and store the context, even if you do not need to use it
# directly.
my $ctx = context();
$ok = $bool1 || $bool2;
$ok &&= !($bool1 && $bool2);
ok($ok, $name);
$ctx->release;
return $bool;
}
Test2 不使用 $Level
来执行回溯,而是使用上下文对象。在此示例中,您创建了一个上下文对象并将其存储。这将锁定上下文(错误报告比这里高一级),以便所有包装的工具都能找到它。您不需要使用上下文对象,但需要将其存储在变量中。子程序结束后,$ctx
变量将被销毁,这将允许未来的工具找到它们自己的上下文。
# Set the mode BEFORE anything loads Test::Builder
use open ':std', ':encoding(utf8)';
use Test::More;
或者
# Modify the filehandles
my $builder = Test::More->builder;
binmode $builder->output, ":encoding(utf8)";
binmode $builder->failure_output, ":encoding(utf8)";
binmode $builder->todo_output, ":encoding(utf8)";
use Test2::API qw/test2_stack/;
test2_stack->top->format->encoding('utf8');
虽然更好的方法是使用 Test2::Plugin::UTF8 插件,它是 Test2::Suite 的一部分。
以下人员都以某种方式为本文档做出了贡献,即使只是为了审阅。
Test2 的源代码库可以在 http://github.com/Test-More/test-more/ 找到。
版权所有 2020 Chad Granum <[email protected]>。
本程序是自由软件;您可以在 Perl 本身相同的条款下重新发布和/或修改它。
参见 https://perldotcom.perl5.cn/perl/misc/Artistic.html