lyyyuna 的小花园

动静中之动, by

RSS

Robot Framework 新版教程 - 解析器接口

发表于 2026-04

解析器接口

Robot Framework 支持外部解析器(Parser),可以处理自定义数据格式,甚至覆盖 Robot Framework 自身的解析器。

自定义解析器是 Robot Framework 6.1 中新增的功能。

启用解析器

解析器通过命令行的 --parser 选项启用,其语义与监听器完全相同。包括以名称或路径指定解析器、向解析器类传递参数等:

robot --parser MyParser tests.custom
robot --parser path/to/MyParser.py tests.custom
robot --parser Parser1:arg --parser Parser2:a1:a2 path/to/tests

解析器 API

解析器可以用模块或类的形式实现。本节说明它们必须包含哪些属性和方法。

EXTENSIONextension 属性

该属性指定解析器支持的一个或多个文件扩展名。EXTENSIONextension 两个名称都可以使用,如果两者同时存在,前者优先。属性的值可以是字符串,也可以是字符串序列。扩展名不区分大小写,可以带或不带前导点号。如果解析器以类的形式实现,可以将该属性设置为类属性或实例属性。

包含多个部分的扩展名也受支持,如 .example.ext.robot.zip

如果解析器支持 .robot 扩展名,它将替代标准解析器来解析这些文件。

parse 方法

必需的 parse 方法负责解析套件文件。对于每个具有解析器所支持扩展名的被解析文件,都会调用该方法。方法必须返回一个 TestSuite 对象。

在简单情况下,parse 可以只接受一个参数,即指向待解析文件的 pathlib.Path 对象。如果解析器需要获取在上级套件初始化文件中设置的 Test SetupTest TeardownTest TagsTest Timeout 的默认值,parse 方法必须接受两个参数。此时第二个参数是一个 TestDefaults 对象。

parse_init 方法

可选的 parse_init 方法负责解析套件初始化文件,即格式为 __init__.ext 的文件,其中 .ext 是解析器支持的扩展名。该方法必须返回一个 TestSuite 对象,代表整个目录。从子套件文件和子目录创建的套件将被添加到其子套件中。

parse_init 同样可以接受一个或两个参数,取决于它是否需要与测试相关的默认值。如果它接受默认值,可以修改传入的 TestDefaults 对象,修改结果在解析子套件文件时可见。

只有在解析器需要支持套件初始化文件时,才需要实现该方法。

可选基类

解析器不需要实现任何显式接口,但继承可选的 Parser 基类可能会有帮助。主要好处是基类提供了文档和类型提示,同时也充当了一个更正式的 API 规范。

示例

以模块形式实现的解析器

第一个示例展示了一个简单的以模块形式实现的解析器,它支持一个硬编码的扩展名。它只是创建一个虚拟套件,并不实际解析任何内容。

from robot.api import TestSuite


EXTENSION = '.example'


def parse(source):
    suite = TestSuite(name='Example', source=source)
    test = suite.tests.create(name='Test')
    test.body.create_keyword(name='Log', args=['Hello!'])
    return suite

以类形式实现的解析器

第二个解析器以类的形式实现,接受要使用的扩展名作为参数。解析器读取给定的源文件,并为其中的每一行创建一个虚拟测试。

from pathlib import Path
from robot.api import TestSuite


class ExampleParser:

    def __init__(self, extension: str):
        self.extension = extension

    def parse(self, source: Path) -> TestSuite:
        name = TestSuite.name_from_source(source, self.extension)
        suite = TestSuite(name, source=source)
        for line in source.read_text().splitlines():
            test = suite.tests.create(name=line)
            test.body.create_keyword(name='Log', args=['Hello!'])
        return suite

继承可选基类的解析器

这个解析器继承了可选的 Parser 基类。它支持解析套件初始化文件,使用了 TestDefaults,并注册了多个扩展名。

from pathlib import Path
from robot.api import TestSuite
from robot.api.interfaces import Parser, TestDefaults


class ExampleParser(Parser):
    extension = ('example', 'another')

    def parse(self, source: Path, defaults: TestDefaults) -> TestSuite:
        """创建一个套件,并将初始化文件中可能的默认值设置到测试中。"""
        suite = TestSuite(TestSuite.name_from_source(source), source=source)
        for line in source.read_text().splitlines():
            test = suite.tests.create(name=line, doc='Example')
            test.body.create_keyword(name='Log', args=['Hello!'])
            defaults.set_to(test)
        return suite

    def parse_init(self, source: Path, defaults: TestDefaults) -> TestSuite:
        """创建一个虚拟套件并设置一些默认值。

        该方法仅在存在具有受支持扩展名的初始化文件时才会被调用。
        """
        defaults.tags = ('tags', 'from init')
        defaults.setup = {'name': 'Log', 'args': ['Hello from init!']}
        return TestSuite(TestSuite.name_from_source(source.parent), doc='Example',
                         source=source, metadata={'Example': 'Value'})

解析器作为预处理器

最后一个示例解析器充当 Robot Framework 数据文件的预处理器,除了标准的 *** Test Cases *** 格式外,还支持 === Test Cases === 格式的 header。在这种用法中,使用 TestSuite.from_stringTestSuite.from_modelTestSuite.from_file_system 工厂方法来构造返回的套件会很方便。

from pathlib import Path
from robot.running import TestDefaults, TestSuite


class RobotPreprocessor:
    extension = '.robot'

    def parse(self, source: Path, defaults: TestDefaults) -> TestSuite:
        data = source.read_text()
        for header in 'Settings', 'Variables', 'Test Cases', 'Keywords':
            data = data.replace(f'=== {header} ===', f'*** {header} ***')
        suite = TestSuite.from_string(data, defaults=defaults)
        return suite.config(name=TestSuite.name_from_source(source), source=source)
lyyyuna 沪ICP备2025110782号-1