内容

名称

Test2::Transition - 升级到 Test2 时的过渡说明

描述

这里记录了与 Test2 升级相关的注意事项和问题。升级会导致 Test::Builder 在后台委托给 Test2。这种过渡在大多数情况下是透明的,但有一些情况可能会导致问题。

会造成问题的地方

以下是与新内部结构不兼容的场景列表。

Test::Builder1.5/2 条件语句

问题

几年前,曾有两项尝试升级/替换 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 单例实例。这通常是为了拦截或修改发生的結果。

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::DBIx::Class::Schema

此模块有一个测试似乎绕过了 Test::Builder 的错误。该错误似乎已由 Test2 修复,这意味着解决方法会导致失败。这很容易更新,但还没有人这样做。

已知在以下版本中出现问题:1.0.9 及更早版本

Device::Chip

测试由于子测试缩进而中断。

已知在版本 0.07 中出现问题。显然在 0.06 中可以正常工作。已提交补丁以解决此问题。

建议升级

这些是未出现问题但测试套件出现问题且已修复的模块。

Test::Exception

旧版本工作正常,但存在一个轻微的测试名称行为问题,这会导致 Test2 出现故障。由于此问题,旧版本将不再安装。CPAN 上的最新版本可以正常安装。升级不是必需的,但建议进行升级。

修复版本:0.43

Data::Peek

一些测试依赖于以微妙的方式修改 $!$?。已应用补丁以更正更改的内容。

模块本身工作正常,无需升级。

修复版本:0.45

circular::require

一些测试很脆弱,需要在较晚阶段加载 base.pm。Test2 过早加载了 base.pm。测试已更新以修复此问题。

模块本身从未出现故障,您无需升级。

修复版本:0.12

Test::Module::Used

一项测试绕过了现在已修复的规划错误。如果您安装了旧版本,则无需升级。如果您需要,新版本可以正常安装。

修复版本:0.2.5

Test::Moose::More

一些测试很脆弱,但已修复。实际故障来自子测试注释缩进更改。

无需升级,旧版本工作正常。只有新版本才能安装。

修复版本:0.025

Test::FITesque

此问题是由规划方式的错误修复引起的。测试在错误修复后已更新。

修复版本:0.04

Test::Kit

旧版本工作正常,但无法安装,因为 Test::Aggregate 位于依赖链中。无需升级。

修复版本:2.15

autouse

一项测试出现故障,因为它依赖于 Scalar::Util 未加载。Test2 加载了 Scalar::Util。测试已更新,在检查 Scalar::Util 的加载状态后加载 Test2。

如果您已安装,则无需升级。

修复版本:1.11

需要升级

Test::SharedFork

旧版本需要直接访问 Test::Builder 单例哈希元素。CPAN 上的最新版本在旧版 Test::Builder 上仍然会这样做,但在 Test2 上会转而使用 Test2::IPC

修复版本:0.35

Test::Builder::Clutch

此模块通过覆盖单例上的方法,并直接访问单例上的哈希值来实现。一个新的版本已经发布,它使用 Test2 API 来实现相同的结果,并且更合理。

修复版本:0.07

Test::Dist::VersionSync

此模块包含 Test::Builder2 条件语句。通过移除这些条件语句来修复此问题。

修复版本:1.1.4

Test::Modern

此模块依赖于 Test::Builder->_try(),这是一个私有方法,文档中说明了没有人应该使用它。通过使用不同的工具来修复此问题。

修复版本:0.012

Test::UseAllModules

0.14 版本依赖于 Test::Builder->history,该属性在 Test::Builder 1.5 中可用。0.12 和 0.13 版本依赖于其他 Test::Builder 内部机制。

修复版本:0.15

Test::More::Prefix

通过应用一个包装 Test::Builder->_print_comment 的角色来实现。通过在 Test2 下运行时添加一个修改消息的事件过滤器来修复此问题。

修复版本:0.007

仍然存在问题

Test::Aggregate

此发行版直接访问 Test::Builder 单例中的哈希键。它也从错误的角度处理问题,请考虑使用 Test2::Aggregate 来实现类似的功能,以及 Test2::Harness,它允许在 harness 级别进行模块预加载。

截至版本 0.373,仍然存在问题。

Test::Wrapper

此模块直接使用 Test::Builder 单例中的哈希键。由于 Test2 的优势,此模块也已过时。使用来自 Test2::APIintercept() 来实现类似的结果。

截至版本 0.3.0,仍然存在问题。

Test::ParallelSubtest

此模块覆盖了 Test::Builder::subtest()Test::Builder::done_testing()。它还直接访问单例的哈希元素。它尚未修复。

替代方案:Test2::AsyncSubtestTest2::Workflow(不稳定)。

截至版本 0.05,仍然存在问题。

Test::Pretty

参见 https://github.com/tokuhirom/Test-Pretty/issues/25

作者承认该模块很疯狂,他正在等待一个新的稳定版本(Test2)以一种合理的方式完全重写它。

截至版本 0.32,仍然存在问题。

Net::BitTorrent

此模块的测试直接访问 Test::Builder 哈希键。大多数(如果不是全部)这些哈希键都有公共 API 方法,可以用来代替它们,以避免这个问题。

在版本 0.052 中仍然存在。

Test::Group

它对 Test::Builder 进行猴子补丁,并在代码中称之为“黑魔法”。

截至版本 0.20,仍然存在。

Test::Flatten

它以多种方式修改了 Test::Builder 的内部机制。实现此模块目标的更好方法是编写自己的子测试函数。

截至版本 0.11,仍然存在。

Log::Dispatch::Config::TestLog

修改 Test::Builder 的内部机制。

截至版本 0.02,仍然存在。

Test::Able

修改 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);
}

TEST2

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 兼容实现

ok($bool, $name)
diag(@messages)
note(@messages)
subtest($name, $code)

如果您正在寻找带有 islike 等的帮助器,请参阅 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,则错误将报告到错误的位置。

TEST2

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 变量将被销毁,这将允许未来的工具找到它们自己的上下文。

使用 UTF8

LEGACY

# 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)";

TEST2

use Test2::API qw/test2_stack/;

test2_stack->top->format->encoding('utf8');

虽然更好的方法是使用 Test2::Plugin::UTF8 插件,它是 Test2::Suite 的一部分。

作者、贡献者和审阅者

以下人员都以某种方式为本文档做出了贡献,即使只是为了审阅。

Chad Granum (EXODIST) <[email protected]>

来源

Test2 的源代码库可以在 http://github.com/Test-More/test-more/ 找到。

维护者

Chad Granum <[email protected]>

版权

版权所有 2020 Chad Granum <[email protected]>。

本程序是自由软件;您可以在 Perl 本身相同的条款下重新发布和/或修改它。

参见 https://perldotcom.perl5.cn/perl/misc/Artistic.html