在 mozperftest 中开发

架构概述

mozperftest 实现了一个 mach 命令,它是 runner.py 之上的一个轻量级包装器,它允许我们在无需通过 mach 调用即可运行该工具。命令参数在 argparser.py 中准备,然后提供给运行器。

运行器创建一个 MachEnvironment 实例(参见 environment.py)和一个 Metadata 实例(参见 metadata.py)。这两个对象在整个测试过程中共享,并用于在所有部分之间共享数据。

然后,运行器调用 MachEnvironment.run,该函数负责运行测试。MachEnvironment 实例运行一系列的**层**。

层是负责性能测试的单个方面的类。它们被组织成三个类别

  • **系统**:任何在系统上设置和拆除某些资源或服务的内容。现有的系统层:**android**、**proxy**

  • **测试**:负责运行测试以收集指标的层。现有的测试层:**browsertime** 和 **androidlog**

  • **指标**:所有将指标处理成可用指标的层。现有的系统层:**perfherder** 和 **console**

MachEnvironment 实例为每个类别收集一系列层并按顺序运行它们。

这种组织的目标是允许添加新的性能测试运行器,这些运行器将基于层的特定组合。为了避免混乱的代码,我们需要确保每一层都代表进程的单个方面,并且与其他层完全独立(除了通过通用环境共享数据之外)。

例如,我们可以使用 perftest 通过实现新的**测试**层来运行 C++ 基准测试。

层是一个从 mozperftest.layers.Layer 继承并实现一些方法和类变量的类。

方法和变量列表

  • name:层的名称(类变量,必填)

  • activated:布尔值,用于默认激活层(类变量,False)

  • user_exception:当发生异常时将触发 on_exception 钩子

  • arguments:包含参数的字典。每个参数都遵循 argparser 标准

  • run(self, medatata):调用以执行层

  • setup(self):当层即将执行时调用

  • teardown(self):当层退出时调用

示例

class EmailSender(Layer):
    """Sends an email with the results
    """
    name = "email"
    activated = False

    arguments = {
        "recipient": {
            "type": str,
            "default": "[email protected]",
            "help": "Recipient",
        },
    }

    def setup(self):
        self.server = smtplib.SMTP(smtp_server,port)

    def teardown(self):
        self.server.quit()

    def __call__(self, metadata):
        self.server.send_email(self.get_arg("recipient"), metadata.results())

然后可以将其添加到用于为每个类别创建层列表的顶级函数之一

  • **mozperftest.metrics.pick_metrics** 用于指标类别

  • **mozperftest.system.pick_system** 用于系统类别

  • **mozperftest.test.pick_browser** 用于测试类别

并且还在这些类别中的每个 get_layers 函数中添加。构建参数解析器时会调用 get_layers 函数。

在我们的示例中,添加 EmailSender 层将添加两个新选项

  • **–email** 用于激活层的标志

  • –email-recipient

重要层

mozperftest 可用于使用 **browsertime** 测试层针对浏览器运行性能测试。它利用了 browsertime.js 框架,并提供了与 Mozilla 的构建和 CI 系统的完全集成。

Browsertime 使用 selenium webdriver 客户端来驱动浏览器,并提供一些指标来衡量用户旅程期间的性能。

编码风格

对于编码风格,我们希望

  • 遵循 PEP 257 用于文档字符串

  • 尽可能避免复杂性

  • 使用现代 Python 3 代码(例如,使用 pathlib 而不是 os.path

  • 尽可能避免对 Mozilla 构建项目和框架的依赖(mozharness、mozbuild 等),或者确保它们被隔离并有文档记录

合并补丁

警告

每个补丁都必须有测试。任何没有测试的更改都将被拒绝。

在为 mozperftest 合并补丁之前,请确保运行 perftest-test

% ./mach perftest-test
=> black [OK]
=> flake8 [OK]
=> remove old coverage data [OK]
=> running tests [OK]
=> coverage
Name                                             Stmts   Miss  Cover   Missing
------------------------------------------------------------------------------------------
mozperftest/metrics/notebook/analyzer.py         29      20     31%    26-36, 39-42, 45-51
...
mozperftest/system/proxy.py                      37      0     100%
------------------------------------------------------------------------------------------
TOTAL                                            1614    240    85%

[OK]

该命令将运行 blackflake8,并确保测试覆盖率没有下降。

您可以使用 -s 选项绕过 flake8/black 以加快您的工作流程,但请确保进行完整的测试运行。您还可以传递单个测试模块的名称。