RobotFramework学习系列--(一)

2023-11-09

测试工作需要用到了RobotFramework,之前只是使用,用了一段时间后,决定深入研究一下它。使用平台为Windows + Linux。由于是基于Linux 系统方面的测试工作,使用的RobotFramework版本为2.8.5

  先简单介绍一下Robot中的一些概念

关键字(Keyword): 分为内部关键字和用户关键字。

      内部关键字顾名思义为Robot内置的部分关键字,例如Should Be Equal,Run Keyword 等等

      用户关键字,开发人员或者测试人员自行通过内部关键字组合 OR 采用外部代码导入构成的关键字

资源(Resource): 关键字的组合包,例如将多个关键字放在一个文件里,这个文件在Robot里可以称为一个资源

库(Library): Robot支持很多库,分为内置和外置,内置的如Collections等,外置的,可以是python写成的文件,java写成的文件,以及通过xml-rpc导入的远程库,这些库一般都是通过代码写成

用例(Case):多个关键字的组合,顺序 or 带分支控制等组成的文件为Case

Suite:可以理解为多个用例的组合,一个suit 文件下可以写多条用例。

  Windows的入口文件为pybot.bat

  Linux的入口文件为pybot

  由上图可以知道,robot的入口文件为robot\run.py(可以查看robot\__init__.py中代码可知)

  看一下run_cli()和run()的区别

  从上图和下图的代码看,run_cli调用的是RobotFramework类下的execute_cli方法,run调用的是RobotFramework类下的execute方法,不同的是execute_cli多了一些参数解析的操作,所以推荐当代码中调用的时候,使用run_cli,而当工具调用的时候,使用run。

  不管是run还是run_cli,核心都调用了_execute这个内部函数,而它又调用了main函数,这个main,在Application类中是一个需要被继承重写的函数,所以需要去继承它的类中寻找具体实现

def execute_cli(self, cli_arguments):
        with self._logging():
            options, arguments = self._parse_arguments(cli_arguments)
            rc = self._execute(arguments, options)
        self._exit(rc)

    def execute(self, *arguments, **options):
        with self._logging():
            return self._execute(list(arguments), options)

    def _execute(self, arguments, options):
        try:
            rc = self.main(arguments, **options)
        except DataError, err:
            return self._report_error(unicode(err), help=True)
        except (KeyboardInterrupt, SystemExit):
            return self._report_error('Execution stopped by user.',
                                      rc=STOPPED_BY_USER)
        except:
            error, details = get_error_details()
            return self._report_error('Unexpected error: %s' % error,
                                      details, rc=FRAMEWORK_ERROR)
        else:
            return rc or 0

下面为main函数的具体实现,核心为5~9行,5行前面为初始化一些基础的配置,9行以后为生成测试log

def main(self, datasources, **options):
        settings = RobotSettings(options)
        LOGGER.register_console_logger(**settings.console_logger_config)
        LOGGER.info('Settings:\n%s' % unicode(settings))
        suite = TestSuiteBuilder(settings['SuiteNames'],
                                 settings['WarnOnSkipped'],
                                 settings['RunEmptySuite']).build(*datasources)
        suite.configure(**settings.suite_config)
        result = suite.run(settings)
        LOGGER.info("Tests execution ended. Statistics:\n%s"
                    % result.suite.stat_message)
        if settings.log or settings.report or settings.xunit:
            writer = ResultWriter(settings.output if settings.log else result)
            writer.write_results(settings.get_rebot_settings())
        return result.return_code

  以windows运行命令行为例  python run.py --outputdir C:\\logs --test 初始化环境 C:\\环境验证

  5~7行,suite为TestSuiteBuilder根据Settings中的部分参数进行构建,并执行build函数,其中datasources为List类型的数据,即['C:\\环境验证'],说明指定用例suit的时候,是可以同时指定多个Suit一起跑

  9行,为执行指定suite(用例),并获取结果

  看一下build具体执行操作

def build(self, *paths):
        if not paths:
            raise DataError('One or more source paths required.')
        if len(paths) == 1:
            return self._build_and_check_if_empty(paths[0])
        root = TestSuite()
        for path in paths:
            root.suites.append(self._build_and_check_if_empty(path))
        return root
    def _build_and_check_if_empty(self, path):
        builded = self._build_suite(self._parse(path))
        if not self._empty_suites_allowed and not builded.test_count:
                raise DataError("Suite '%s' contains no tests." % builded.name)
        builded.remove_empty_suites()
        return builded

   def _build_suite(self, data, parent_defaults=None):
        defaults = TestDefaults(data.setting_table, parent_defaults)
        suite = TestSuite(name=data.name,
                          source=data.source,
                          doc=unicode(data.setting_table.doc),
                          metadata=self._get_metadata(data.setting_table))
        for import_data in data.setting_table.imports:
            self._create_import(suite, import_data)
        self._create_setup(suite, data.setting_table.suite_setup)
        self._create_teardown(suite, data.setting_table.suite_teardown)
        for var_data in data.variable_table.variables:
            self._create_variable(suite, var_data)
        for uk_data in data.keyword_table.keywords:
            self._create_user_keyword(suite, uk_data)
        for test_data in data.testcase_table.tests:
            self._create_test(suite, test_data, defaults)
        for child in data.children:
            suite.suites.append(self._build_suite(child, defaults))
        return suite

  build根据传入的datasources的个数进行构建,对于单独的一个文件的情况下,调用了内部函数_build_and_check_if_empty,这个函数会判断传入的datasource是否真实存在,如果存在,会再次调用_build_suite进行suite构建

  _parse()这个内部的函数完成了robot文件(.txt 或者.robot文件)到robot的数据结构TestData的转换, TestData数据结构会在后面的文章详细讲解

def _parse(self, path):
        try:
            return TestData(source=abspath(path),
                            include_suites=self.include_suites,
                            warn_on_skipped=self.warn_on_skipped)
        except DataError, err:
            raise DataError("Parsing '%s' failed: %s" % (path, unicode(err)))

  回到_build_suite

  data.setting_table.imports是指suite最开始定义的可以进行导入的Source, Libriary等

  data.setting_table.suite_setup 是指在suite中定义的 Suite Setup,同理 data.setting_table.suite_teardown 是指 Suite Teardown

  data.variable_table.variables 是指在suite中定义的变量

  data.keyword_table.keywords 定义的关键字

  data.testcase_table.tests 是指suite中定义的case,对test,会调用下面的代码进行创建test

def _create_test(self, suite, data, defaults):
        values = defaults.get_test_values(data)
        test = suite.tests.create(name=data.name,
                                  doc=unicode(data.doc),
                                  tags=values.tags.value,
                                  template=self._get_template(values.template),
                                  timeout=self._get_timeout(values.timeout))
        self._create_setup(test, values.setup)
        for step_data in data.steps:
            self._create_step(test, step_data, template=values.template)
        self._create_teardown(test, values.teardown)

 values是获取了单个test的一些具体信息,如tags,test Setup, Test Teardown等

  suite.tests为 TestCase类型数据,TestSuite 继承于model.TestSuite, 而model.TestSuite 中通过装饰器为tests 赋予TestCase类型数据

 @setter
     def tests(self, tests):
         return TestCases(self.test_class, self, tests)

  后续代码创建了分解了整个case的各个步骤,通过_create_step对test的步骤进行扩充

  到此为止,TestSuiteBuilder便构建完成

  由于Case执行部分复杂,将在下一篇文章中详细讲解

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RobotFramework学习系列--(一) 的相关文章

随机推荐

  • nginx---四层七层代理

    理论部分 所谓四层负载均衡 也就是主要通过报文中的目标地址和端口 再加上负载均衡设备设置的服务器选择方式 决定最终选择的内部服务器 它一般走的是tcp udp协议 所谓七层负载均衡 也称为 内容交换 也就是主要通过报文中的真正有意义的应用层
  • 2022年4月23日第十三届省赛蓝桥杯真题答案_python_第五题_统计未被污染的海域

    第五题如约而至哈 和第六题差不多 但比第六题简单 好 上题目 题目 有一片海域划分为N M个方格 其中有些海域已被污染 用0表示 有些海域没被污染 用1表示 请问这片N M海域中有几块是没被污染的独立海域 没被污染的独立海域是指该块海域上下
  • Obsidian流程图

    下载的obsidian进行安装时自动在C盘建立文件夹 但是该文件夹大小不大 关于在obsidian中安装插件 参考以下文章进行操作 https zhuanlan zhihu com p 403001135 我自己弄mermaid这个插件时
  • CSDN不再更新,后续文章在掘金发布

    掘金地址 方大可的主页
  • 用手机版python爬虫_Python爬虫也能用手机进行抓包?没错!这个技巧我只告诉你...

    今天要说说怎么在我们的手机抓包 我们知道了 HTTP 的请求方式 以及在 Chrome 中摸清了一些套路 但是 除了对数据进行解析之外 有时候我们想 对请求的数据或者响应的数据进行篡改 怎么做呢 我们经常在用的手机 手机里面的数据 怎么对它
  • Memcached 学习笔记(三)——多节点测试

    Memcached 学习笔记 三 多节点测试 一 启动两个 或者多个 节点 memcached d p 11212 u nobody c 1024 m 64 memcached d p 11213 u nobody c 1024 m 64
  • 跳跃列表(skipList)、压缩列表(zipList)和快速列表(quicklist)

    跳跃列表 skipList 压缩列表 zipList 和快速列表 quicklist 都是Redis底层重要的数据结构 跳跃列表 skipList Redis使用跳跃表作为有序集合键的底层实现之一 通过在每个节点中维持多个指向其他节点的指针
  • python信号端点检测_python的webrtc库实现语音端点检测

    引言 语音端点检测最早应用于电话传输和检测系统当中 用于通信信道的时间分配 提高传输线路的利用效率 端点检测属于语音处理系统的前端操作 在语音检测领域意义重大 但是目前的语音端点检测 尤其是检测 人声 开始和结束的端点始终是属于技术难点 各
  • 网站被DDOS攻击怎么办?防护经验!

    为了能够及时发现ddos攻击 下面我们就详细介绍一下网站受ddos攻击的症状 网站遇到ddos攻击的表现之一 服务器CPU被大量占用 ddos攻击其实是一种恶意性的资源占用攻击 攻击者利用肉鸡或者攻击软件对目标服务器发送大量的无效请求 导致
  • AngularJS的使用总结

    1 AngularJS是一个前端JavaScript框架 它可通过
  • 无法使用域名访问服务器,但IP访问正常

    具体判断方法和解决办法 问题判断 在电脑的windows系统左下角点击 开始 运行 输入 cmd 确定 然后在弹出的命令提示符界面输入命令 nslookup 空格 域名 若命令结果中域名指向的ip和服务器实际公网ip一致 那么问题产生的原因
  • C语言 cortex-A7核 点LED灯 (附 汇编实现、使用C语言 循环实现、使用C语言 封装函数实现【重要、常用】)

    1 汇编实现 text global start start LED1点灯 gt PE10 RCC章节初始化 CC INIT 1 使能GPIOE组控制器 通过RCC MP AHB4ENSETR寄存器设置GPIOE组使能0x50000A28
  • C++11多线程之条件变量

    文章目录 一 关于多线程的同步 二 初始条件变量 三 关于条件变量的例题 四 生产者消费者模型 一 关于多线程的同步 函数被调用 分配相应的栈帧 进行现场保护 void func char c char filename 20 sprint
  • elementUI table组件渲染问题

    elementUI table组件渲染问题 1 问题 问题描述 页面内 使用选项卡 进行内容显示的切换 切换后 原本高度合适的表格出现白边 以及滚动条 检查Dom会发现 el table组件内 发现了一个类名为 is scrolling n
  • 分布式文件存储Minio学习入门

    文章目录 一 分布式文件系统应用场景 1 Minio介绍 Minio优点 2 MinIO的基础概念 3 纠删码ES Erasure Code 4 存储形式 5 存储方案 二 Docker部署单机Minio 三 minio纠删码模式部署 四
  • html空格符号代码及特殊符号

    一 html空格符号代码 nbsp 一个字符的半角的不断行的空格 如果需要在网页中插入多个空格 可以将 nbsp 代码写多遍 ensp 一个字符的半角的空格 也可以将 写多遍来插入多个空格 emsp 两个字符的全角的空格 也可以将 emsp
  • Flask框架入门教程(非常详细)从零基础入门到精通,看完这一篇就够了

    Flask框架 一 简介 Flask是一个非常小的PythonWeb框架 被称为微型框架 只提供了一个稳健的核心 其他功能全部是通过扩展实现的 意思就是我们可以根据项目的需要量身定制 也意味着我们需要学习各种扩展库的使用 二 概要 1 安装
  • 【学习笔记】python实现excel数据处理

    概述 Excel固然功能强大 也有许多函数实现数据处理功能 但是Excel仍需大量人工操作 虽然能嵌入VB脚本宏 但也容易染上宏病毒 python作为解释性语言 在数据处理方面拥有强大的函数库以及第三方库 excel作为主要基础数据源之一
  • MySQL中的事务(隔离性详解)

    1 什么是事务 事务是指逻辑上的一组操作 组成这组操作的各个单元 要么全部成功 要么全部失败 通俗的说一组SQL语句 要么全部执行成功 一条语句出错则全部出粗 在不同的环境中 都可以有事务 对应在数据库中 就是数据库事务 2 为什么使用事务
  • RobotFramework学习系列--(一)

    测试工作需要用到了RobotFramework 之前只是使用 用了一段时间后 决定深入研究一下它 使用平台为Windows Linux 由于是基于Linux 系统方面的测试工作 使用的RobotFramework版本为2 8 5 先简单介绍