可视化用于颤振测试(或颤振驱动程序)的点击/手势

fzy*_*cjy 8 dart flutter flutter-test

使用flutter_driver/ 时flutter_test,我们通过做类似的事情来模拟用户行为await tap()。但是,我想查看在 emulator 屏幕上点击的位置。是否可以?谢谢!

cre*_*not 11

我对此的想法(因为 Flutter 驱动程序和小部件测试不使用真正的点击)是在 Flutter 级别记录点击,即使用 Flutter 命中测试。

我将向您展示一个小部件,您可以将其包装在其中以可视化捕获 所有点击。我为此编写了一个完整的小部件

示范

这是在默认模板演示应用程序周围包裹小部件时的结果:

执行

我们想要做的很简单:以我们的小部件(整个应用程序是我们的孩子)的大小对所有点击事件做出反应。 然而,它带来了一个小挑战:例如在对它们做出反应后不会它们通过。所以,如果我们使用,我们可以要么没有反应击中按钮在我们的应用程序的水龙头我们将不能够击中按钮(只能看到我们的指示)。
GestureDetectorTapGestureRecognizer

因此,我们需要使用我们自己的渲染对象来完成这项工作。当您熟悉时,这不是一项艰巨的任务 -RenderProxyBox只是我们需要的抽象:)

捕捉命中事件

通过覆盖hitTest,我们可以确保我们总是记录命中:

@override
bool hitTest(BoxHitTestResult result, {required Offset position}) {
  if (!size.contains(position)) return false;
  // We always want to add a hit test entry for ourselves as we want to react
  // to each and every hit event.
  result.add(BoxHitTestEntry(this, position));
  return hitTestChildren(result, position: position);
}
Run Code Online (Sandbox Code Playgroud)

现在,我们可以handleEvent用来记录命中事件并可视化它们:

@override
void handleEvent(PointerEvent event, covariant HitTestEntry entry) {
  // We do not want to interfere in the gesture arena, which is why we are not
  // using regular tap recognizers. Instead, we handle it ourselves and always
  // react to the hit events (ignoring the gesture arena).
  if (event is PointerDownEvent) {
    // Record the global position.
    recordTap(event.position);

    // Visualize local position.
    visualizeTap(event.localPosition);
  }
}
Run Code Online (Sandbox Code Playgroud)

可视化

我将为您提供详细信息(最后是完整代码):我决定AnimationController为每个记录的命中创建一个并将其与本地位置一起存储。

由于我们使用的是 a RenderProxyBox,我们可以markNeedsPaint在动画控制器触发时调用,然后为所有记录的点击绘制一个圆圈:

@override
void paint(PaintingContext context, Offset offset) {
  context.paintChild(child!, offset);

  final canvas = context.canvas;
  for (final tap in _recordedTaps) {
    drawTap(canvas, tap);
  }
}
Run Code Online (Sandbox Code Playgroud)

代码

当然,我浏览了实现的大部分内容,因为您可以通读它们:)
代码应该是直截了当的,因为我概述了我使用的概念。

您可以在此处找到完整的源代码

用法

用法很简单:

TapRecorder(
  child: YourApp(),
)
Run Code Online (Sandbox Code Playgroud)

即使在我的示例实现中,您也可以配置点击圆圈的颜色、大小、持续时间等:

/// These are the parameters for the visualization of the recorded taps.
const _tapRadius = 15.0,
    _tapDuration = Duration(milliseconds: 420),
    _tapColor = Colors.white,
    _shadowColor = Colors.black,
    _shadowElevation = 2.0;
Run Code Online (Sandbox Code Playgroud)

如果你愿意,你可以让它们成为小部件参数。

测试

我希望可视化部分不辜负您的期望。

如果你想超越这一点,我确保水龙头是全局存储的:

/// List of the taps recorded by [TapRecorder].
///
/// This is only a make-shift solution of course. This will only be viable
/// when using a single [TapRecorder] because it is saved as a top-level
/// variable.
@visibleForTesting
final recordedTaps = <Offset>[];
Run Code Online (Sandbox Code Playgroud)

您可以简单地访问测试中的列表来检查记录的点击:)

结束

我在实现这个过程中获得了很多乐趣,我希望它符合您的期望。
实现只是一个快速的转换,但是,我希望它可以为您提供将这个想法提升到一个良好水平所需的所有概念:)

  • 做得好!奖励已授予!我想知道通过颤振驱动程序仪表包装器将其嫁接起来有多难 (2认同)