接上一篇 day1 run.py

发现build test suit还挺复杂的, 先从官网API找到了一些资料,可以看出这是robotframework进行组织

测试案例实现的重要步骤, 将传入的testCase解析并生成suite对象, 等待调用

https://robot-framework.readthedocs.io/en/v3.1/autodoc/robot.running.html

(一)官网 API 说明部分

robot.running package

Implements the core test execution logic.

The main public entry points of this package are of the following two classes:

  • TestSuiteBuilder for creating executable test suites based on existing test case files and directories.
  • TestSuiteBuilder 根据已有的测试文件和目录生成可执行的测试suites
  • TestSuite for creating an executable test suite structure programmatically.
  • TestSuite 根据传入参数生成可执行的测试suite
  • 两者区别是TestSuiteBuilder根据传入robotFramework的测试文件定义进行解析,然后生成可执行测试 suite
  • 而TestSuite是需要我们制定各种参数,生成可执行的测试 suite, TestSuiteBuilder解析之后回去调用TestSuite

It is recommended to import both of these classes via the robot.api package like in the examples below. Also TestCase and Keyword classes used internally by the TestSuite class are part of the public API. In those rare cases where these classes are needed directly, they can be imported from this package.

Examples

First, let’s assume we have the following test suite in file activate_skynet.robot:

 *** Settings ***
Library OperatingSystem *** Test Cases ***
Should Activate Skynet
[Tags] smoke
[Setup] Set Environment Variable SKYNET activated
Environment Variable Should Be Set SKYNET

We can easily parse and create an executable test suite based on the above file using the TestSuiteBuilder class as follows:

 from robot.api import TestSuiteBuilder

 suite = TestSuiteBuilder().build('path/to/activate_skynet.robot')

That was easy. Let’s next generate the same test suite from scratch using the TestSuite class:

from robot.api import TestSuite

suite = TestSuite('Activate Skynet')
suite.resource.imports.library('OperatingSystem')
test = suite.tests.create('Should Activate Skynet', tags=['smoke'])
test.keywords.create('Set Environment Variable', args=['SKYNET', 'activated'], type='setup')
test.keywords.create('Environment Variable Should Be Set', args=['SKYNET'])

Not that complicated either, especially considering the flexibility. Notice that the suite created based on the file could also be edited further using the same API.

Now that we have a test suite ready, let’s execute it and verify that the returned Result object contains correct information:

result = suite.run(critical='smoke', output='skynet.xml')

assert result.return_code == 0
assert result.suite.name == 'Activate Skynet'
test = result.suite.tests[0]
assert test.name == 'Should Activate Skynet'
assert test.passed and test.critical
stats = result.suite.statistics
assert stats.critical.total == 1 and stats.critical.failed == 0

Running the suite generates a normal output XML file, unless it is disabled by using output=None. Generating log, report, and xUnit files based on the results is possible using the ResultWriter class:

from robot.api import ResultWriter

# Report and xUnit files can be generated based on the result object.
ResultWriter(result).write_results(report='skynet.html', log=None)
# Generating log files requires processing the earlier generated output XML.
ResultWriter('skynet.xml').write_results()

(二)代码阅读部分

day1 的代码段,

suite = TestSuiteBuilder(settings['SuiteNames'], settings['WarnOnSkipped']).build(*datasources)

/robot/running/builder.py
from .model import ForLoop, Keyword, ResourceFile, TestSuite

def build(self, *paths):
"""
:param paths: Paths to test data files or directories.
:return: :class:`~robot.running.model.TestSuite` instance.
"""
if not paths:
raise DataError('One or more source paths required.')
if len(paths) == 1:
return self._parse_and_build(paths[0])
root = TestSuite()
for path in paths:
root.suites.append(self._parse_and_build(path))
return root

主要功能在TestSuite() 的构建上, 生成TestSuite()实例

*1*root = TestSuite()

实例化之后 解析path传入的文件

root.suites继承自父类 robot.model.testsuite.py, suites 返回TestSuites

suites.append 即 TestSuites.append, 而TestSuites又继承自(ItemList)

所以调用TtemList.append

robot.model.testsuite.py

*2*root.suites.append(self._parse_and_build(path))
--->
    @setter
    def suites(self, suites):
    """Child suites as a :class:`~.TestSuites` object."""
    return TestSuites(self.__class__, self, suites)     class TestSuites(ItemList):
     __slots__ = []     def __init__(self, suite_class=TestSuite, parent=None, suites=None):
    ItemList.__init__(self, suite_class, {'parent': parent}, suites) #初始化父类
@py2to3
class ItemList(object):
__slots__ = ['_item_class', '_common_attrs', '_items'] def __init__(self, item_class, common_attrs=None, items=None):
self._item_class = item_class
self._common_attrs = common_attrs
self._items = ()
if items:
self.extend(items) def create(self, *args, **kwargs):
return self.append(self._item_class(*args, **kwargs)) def append(self, item):
self._check_type_and_set_attrs(item)
self._items += (item,)
return item

_build_suite
构建文件中的每个suite, 然后填入list中待执行, 详细见_build_suite这块代码解析
下面三个函数进行了suite的具体构建, setup/teardown/test, 每个suite的三元素进行了构建
_build_setup
(suite, data.setting_table.suite_setup)
_build_teardown(suite, data.setting_table.suite_teardown)
_build_test(suite, test_data, defaults)
*3*self._parse_and_build(path)

    def _parse_and_build(self, path):
    suite = self._build_suite(self._parse(path))
    suite.remove_empty_suites()
    return suite

from robot.parsing import TestData, ResourceFile as ResourceData    

def _parse(self, path):
try:
return TestData(source=abspath(path),
include_suites=self.include_suites,
warn_on_skipped=self.warn_on_skipped)
except DataError as err:
raise DataError("Parsing '%s' failed: %s" % (path, err.message))
    def _build_suite(self, data, parent_defaults=None):
     #根据传入的data进行 test suite 构建

defaults = TestDefaults(data.setting_table, parent_defaults)
suite = TestSuite(name=data.name, # 传入data.name ... 下同
source=data.source,
doc=unic(data.setting_table.doc),
metadata=
self._get_metadata(data.setting_table))
self._build_setup(suite, data.setting_table.suite_setup)
self._build_teardown(suite, data.setting_table.suite_teardown)
for test_data in data.testcase_table.tests:
self._build_test(suite, test_data, defaults)
for child in data.children:
suite.suites.append(self._build_suite(child, defaults))
ResourceFileBuilder().build(data, target=suite.resource)
return suite
 

running 中的 TestSuite 继承自 robot.model.TestSuite

class TestSuite(model.TestSuite):
"""Represents a single executable test suite. See the base class for documentation of attributes not documented here.
"""
__slots__ = ['resource']
test_class = TestCase #: Internal usage only.
keyword_class = Keyword #: Internal usage only. def __init__(self, name='', doc='', metadata=None, source=None):
model.TestSuite.__init__(self, name, doc, metadata, source)
#: :class:`ResourceFile` instance containing imports, variables and
#: keywords the suite owns. When data is parsed from the file system,
#: this data comes from the same test case file that creates the suite.
self.resource = ResourceFile(source=source)

脑瓜疼, 看不下去了, 休息一会儿 。。。 。。。

Robot Framework 源码阅读 day2 TestSuitBuilder的更多相关文章

  1. Robot Framework 源码阅读 day1 run.py

    robot里面run起来的接口主要有两类 run_cli def run_cli(arguments): """Command line execution entry ...

  2. Robot Framework 源码阅读 day1 __main__.py

    robot文件夹下的__main__.py函数 是使用module运行时的入口函数: import sys # Allows running as a script. __name__ check n ...

  3. Robot Framework 源码解析(1) - java入口点

    一直很好奇Robot Framework 是如何通过关键字驱动进行测试的,好奇它是如何支持那么多库的,好奇它是如何完成截图的.所以就打算研究一下它的源码. 这是官方给出的Robot framework ...

  4. Robot Framework源码解析(2) - 执行测试的入口点

    我们再来看 src/robot/run.py 的工作原理.摘录部分代码: from robot.conf import RobotSettings from robot.model import Mo ...

  5. Android源码阅读 – Zygote

    @Dlive 本文档: 使用的Android源码版本为:Android-4.4.3_r1 kitkat (源码下载: http://source.android.com/source/index.ht ...

  6. Spring源码阅读笔记

    前言 作为一个Java开发者,工作了几年后,越发觉力有点不从心了,技术的世界实在是太过于辽阔了,接触的东西越多,越感到前所未有的恐慌. 每天捣鼓这个捣鼓那个,结果回过头来,才发现这个也不通,那个也不精 ...

  7. jdk源码阅读笔记-LinkedHashMap

    Map是Java collection framework 中重要的组成部分,特别是HashMap是在我们在日常的开发的过程中使用的最多的一个集合.但是遗憾的是,存放在HashMap中元素都是无序的, ...

  8. Apollo源码阅读笔记(二)

    Apollo源码阅读笔记(二) 前面 分析了apollo配置设置到Spring的environment的过程,此文继续PropertySourcesProcessor.postProcessBeanF ...

  9. SpringMVC源码阅读系列汇总

    1.前言 1.1 导入 SpringMVC是基于Servlet和Spring框架设计的Web框架,做JavaWeb的同学应该都知道 本文基于Spring4.3.7源码分析,(不要被图片欺骗了,手动滑稽 ...

随机推荐

  1. Linux内核设计与实现 总结笔记(第九章)内核同步介绍

    在使用共享内存的应用程序中,程序员必须特别留意保护共享资源,防止共享资源并发访问. 一.临界区和竞争条件 1.1 临界区和竞争条件 所谓临界区就是访问和操作共享数据代码段.多个执行线程并发访问同一个资 ...

  2. php大文件下载+断点续传

    如果我们的网站提供文件下载的服务,那么通常我们都希望下载可以断点续传(Resumable Download),也就是说用户可以暂停下载,并在未来的某个时间从暂停处继续下载,而不必重新下载整个文件. 通 ...

  3. Codeforces 878A - Short Program(位运算)

    原题链接:http://codeforces.com/problemset/problem/878/A 题意:给出n个位运算操作, 化简这些操作, 使化简后的操作次数不多于5步. 思路:我们可以对二进 ...

  4. 【CF686D】Kay and Snowflake(树的重心)

    题意:给定一棵n个点的树,q次询问,每次询问以某个点为根的子树编号是多少 n,q<=3e5 思路:设sz[u]为以u为根子树的size,v为u的size最大的儿子 若sz[v]*2<sz[ ...

  5. Nginx动静分离-tomcat

    一.动静分离 1.通过中间件将动态请求和静态请求分离. 2.为什么? 分离资源,减少不必要的请求消耗,减少请求延时. 3.场景 还可以利用php,fastcgi,python 等方式 处理动态请求 # ...

  6. 3D Computer Grapihcs Using OpenGL - 12 Rotation Matrix

    为了证明我们上节渲染出来的是一个立方体而不是一个平面,我们决定将它旋转一定角度,这样我们就需要一个旋转矩阵(也属于ModelTransformMatrix的一部分) 上一节我们的ModelTransf ...

  7. elasticsearch堆内存的配置建议

    1.将最小堆大小(Xms)和最大堆大小(Xmx)设置为彼此相等 防止内存抖动 2:给多大的堆内存? 给ES的内存配置不是越大越好,建议不能超过32GB,不同jdk版本最大边界值是不同的,对于32位小于 ...

  8. es之IK分词器

    1:默认的分析器-- standard 使用默认的分词器 curl -XGET 'http://hadoop01:9200/_analyze?pretty&analyzer=standard' ...

  9. Python学习笔记(二)Sublime Text 3 安装Package Control

    原来Subl3安装Package Control很麻烦,现在简单的方法来了 一.简单的安装方法 使用Ctrl+`快捷键或者通过View->Show Console菜单打开命令行,粘贴如下代码: ...

  10. Qt 之 ZIP开源库 QuaZIP

    2013-10-31 21:46 10856人阅读 评论(0) 收藏 举报  分类: Qt(12)  版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   一.简介     ...