使用 robot.api 时不执行测试用例拆解,但在使用 pybot runner 时有效

test case teardown does not execute when using robot.api but does work when using pybot runner

背景

我正在试验 Robot Framework 的程序化 API,以便从活动数据集动态创建测试用例。

问题总结

在使用 robot.api 包中提供的实用程序库将我的测试转换为 运行 时,我 运行 遇到了 teardown 关键字似乎没有出现的问题因为测试用例被执行。如果我在 .robot 文件中使用关键字,这个 teardown 似乎会执行。

我的问题是:为什么我的测试用例拆解在使用 robot.api 而不是 pybot 时无法执行?

例子

我创建了以下示例来演示我遇到的问题。要 运行 它,您需要安装 Python robotframework 库 (pip install robotframework)。

在示例 运行s(下)中,您会看到控制台日志行 Test Case Teardown Ran 出现在 pybot 结果中,但不在 robot.api 结果中。对于行的格式,我提前表示歉意 - 这就是测试用例 运行ner 输出它们的方式,我不想修改输出并可能删除过程中的一些线索。

resource.robot

** Keywords **
TestSuite Setup
    Log To Console  TestSuite Setup Ran 

TestSuite Teardown
    Log To Console  TestSuite Teardown Ran 

TestCase Setup
    Log To Console  TestCase Setup Ran 

TestCase Teardown
    Log To Console  TestCase Teardown Ran 

suite.robot

** Settings **
Resource             resource.robot

Suite Setup     TestSuite Setup
Suite Teardown  TestSuite Teardown

** Test Cases **
Example test case
    [setup]     TestCase Setup
    [teardown]  TestCase Teardown
    Log To Console  Test ran 

suite.py

import robot.api as robot_api

suite = robot_api.TestSuite('Programmatic test suite')
suite.resource.imports.resource('resource.robot')
suite.keywords.create('TestSuite Setup', type='setup')
suite.keywords.create('TestSuite Teardown', type='teardown')

test = suite.tests.create('Example test case')
test.keywords.create('TestCase Setup', type='setup')
test.keywords.create('TestCase Teardown', type='teardown')
test.keywords.create('Log To Console', args=['Test ran'])
result = suite.run(output='output.xml')
robot_api.ResultWriter(result).write_results(
    log='log.html',
    report='report.html'
)

结果(使用 Pybot)

$ pybot suite.robot
==============================================================================
Suite                                                                         
==============================================================================
TestSuite Setup Ran
Example test case                                                     TestCase Setup Ran
.Test ran
.TestCase Teardown Ran
Example test case                                                     | PASS |
------------------------------------------------------------------------------
TestSuite Teardown Ran
Suite                                                                 | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
==============================================================================
Output:  /private/tmp/robot_problem/output.xml
Log:     /private/tmp/robot_problem/log.html
Report:  /private/tmp/robot_problem/report.html

结果(使用python-2.7)

$ python suite.py 
==============================================================================
Programmatic test suite                                                       
==============================================================================
TestSuite Setup Ran
Example test case                                                     TestCase Setup Ran
.Test ran
Example test case                                                     | PASS |
------------------------------------------------------------------------------
TestSuite Teardown Ran
Programmatic test suite                                               | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
==============================================================================
Output:  /private/tmp/robot_problem/output.xml

这对我来说听起来像是一个错误。或者也许是一个未记录的怪癖。安装关键字必须添加 FIRST 并且拆卸必须添加 LAST.

test = suite.tests.create('Example test case')
test.keywords.create('TestCase Setup', type='setup')
test.keywords.create('Log To Console', args=['Test ran'])
test.keywords.create('TestCase Teardown', type='teardown')
result = suite.run(output='output.xml')

我通过查看 robot/model/keyword.py 中的 class 关键字解决了这个问题:

@property
def setup(self):
    return self[0] if (self and self[0].type == 'setup') else None

@property
def teardown(self):
    return self[-1] if (self and self[-1].type == 'teardown') else None

结合类型检查注意 0 和 -1 的指标。