精华内容
下载资源
问答
  • 自动化框架开发
    千次阅读
    2021-03-03 10:36:09

    【51CTO.com快译】多年来,Java一直是服务器端应用开发的首选编程语言。随着时间的推移和自动化测试的兴起,业界出现了许多基于Java,并根据不同的业务逻辑而发展起来的开源框架。在此,我向大家介绍并比较五种用到了Java的自动化测试框架。

    由Kent Beck和Erich Gamma开发的JUnit是xUnit框架的一个实例。其设计的宗旨是让Java开发人员能够编写出各种脚本、并执行那些可重复的测试用例。因此,JUnit通常被用来测试各种小块的程序代码。同时,您还可以通过将JUnit与Selenium WebDriver相集成,来执行针对某个网站的自动化测试。不过,只要添加了任何新的代码,您都需要重新执行整个测试用例、以确保无任何损坏。

    安装JUnit的先决条件

    由于JUnit是一种基于Java的框架,因此它与Java的Selenium WebDriver高度兼容。您需要准备如下先决条件:

    安装最新版本的JDK。

    下载最新版本的JUnit,并设置相关的环境。

    熟悉使用面向对象编程语言(尤其是Java)进行应用开发。

    JUnit的优点和缺点

    JUnit有如下优点:

    由于必须阅读代码、并查找异常,因此开发人员普遍能够对以测试为驱动的环境处之泰然。

    能够尽早地检测出错误,进而产生更为可靠的程序代码。

    能够开发出更具可读性且无bug的程序代码,以增强项目相关人员的信心。

    最新版本的JUnit(版本4)不但可以更加轻松地识别出各种异常,而且能够执行那些由旧版JUnit所编写的测试用例。

    可与Java 5及以上版本一起使用。

    JUnit的唯一缺点是:

    该框架无法执行依赖性测试。

    JUnit的特点与竞品比较

    JUnit与下面将要提到的TestNG具有相似的功能。但是两者在参数化测试的实现过程上不尽相同。由于历史悠久,JUnit拥有更好的社区支持,并被定义为使用Selenium WebDriver进行基于Java类应用单元测试的标准。而TestNG虽然目前用户相对较少,但是其社区规模却日益增长。因此,我们认为:是选择JUnit、还是TestNG作为Java测试的框架,完全取决于目标应用的性质和需求。

    当然,如果您已选定了使用JUnit的话,请参考 《使用JUnit和Selenium执行自动化测试》 一文,以针对浏览器的兼容性开展分步测试。

    作为测试人员,您一定听说过行为驱动开发(Behavior Driven Development,BDD)。它能够以一种透明的方式,向业务用户描述验收测试。而JBehave正是一种通过Selenium WebDriver来针对BDD开展Java测试的框架。它可以让新手轻松地理解BDD概念,进而基于行为开展应用测试。

    安装JBehave的先决条件

    用户使用JBehave的理想方法是与Eclipse相集成。因此,除了具有JDK1.7及更高版本,和Indigo以上的任意Eclipse IDE之外,您还需要配备如下jar文件:

    JUnit-4.1.0.jar

    Jbehave-core-3.8.jar

    Commons-lang-2.4.jar

    Paranamer-2.5.jar

    Freemarker-2.3.9.jar

    Org.apacje.commons.io.jar

    Org.apache.commons.collections.jar

    Plexus-utils-1.1.jar

    JBehave的优点和缺点

    与所有其他BDD测试框架一样,JBehave具有如下优点:

    协调具有类似规范、却身处不同项目的开发团队,来实现行为驱动式的开发。

    根据类似的规范格式,让项目经理和利益相关者对开发团队和QA团队的输出具有更清楚地了解。

    由于JBehave具有更多值得用户推理和思考的细节,因此目标产品会具有更好的规范性。

    由于使用了半正式(semi-formal)语言、以及域词汇表(domain vocabulary),因此JBehave有助于在团队结构中保持一致性的行为。

    JBehave同样也有着其他BDD测试工具一样的缺点:

    一款BDD测试工具的成功,主要取决于项目中不同成员,包括:利益相关者、开发人员和测试人员之间的沟通,以及组织的管理。反之,沟通的缺乏则可能会导致无法逾越的问题、有缺陷的应用、业务需求未被满足、以及各方的互相推诿。

    JBehave的特点与竞品比较

    JBehave与下面将要提到的Serenity有着相同的工作方式。但是,如果您的目标是使得自动验收测试更为有效的话,那么将Serenity与JBehave相集成,则会获得更好的测试体验。

    Serenity同样是一种能被用于行为驱动测试的开源库。该框架可帮助您编写出各种结构良好、且易于维护的验收标准。它在一定程度上扩展了JUnit和WebDriver的功能。

    安装Serenity的先决条件

    由于该框架基于Java,因此您显然需要具备Java、或其他任何面向对象编程语言的知识与经验。此外,您的电脑上还需要有:

    JDK 5或更高版本。

    Maven 3.0或更高版本。

    由于Maven和Eclipse的组合更易于使用,因此作为IDE工具的Eclipse通常是所有开发人员首选的。

    Serenity的优点和缺点

    针对行为驱动测试,Serenity具有如下优点:

    该框架能够帮助测试人员创建各种REST服务的测试用例。

    用户不必花费大量的时间,来维护或构建自己的自动化框架。

    它能够在定义、理解测试用例、以及实现方式建立平衡。

    它可以与许多自动化框架相集成,其中包括:Selenium、JBehave、基于Java的高级开发框架(如Spring)、甚至是JIRA之类的持续集成工具。

    与JBehave类似,Serenity的唯一缺点便是:为了充分发挥其支持行为驱动开发的完整功能,项目参与者需要保持彼此之间的沟通。

    Serenity的特点与竞品比较

    由于主要被用于报告验收的标准,因此使用Serenity所写出的报告,比JBehave等其他BDD框架具有更丰富信息量。同时,它还可以帮助开发人员编写出更高质量的自动化测试用例场景。另外,它能够为RestAssured和Selenium WebDriver提供支持,使得测试人员能够更快、更简便地写出基于验收测试标准的自动化用例。

    也许是受到了JUnit的启发,由Cedric Beust创建的TestNG也是一种基于Java的开源自动化测试框架,不过它更为强大。此处NG表示“下一代”,因此它能够在集成的过程中采用更好的执行方式。该框架可帮助开发人员实现排序、分组和参数化等功能,进而在消除了以往框架各种缺点的基础上,让新的测试用例更具灵活性。

    安装TestNG的先决条件

    在系统中已安装了最新版本的JDK。

    最新版本的Eclipse。

    具备Java或其他任何面向对象编程语言的知识和实践经验。

    TestNG的优点和缺点

    在弥补过往框架诸多缺点的基础上,TestNG还具备如下优点:

    该框架能使用户在多个代码片段上运行各种并行的测试。

    在执行用例测试的期间,您可以生成一份HTML报告。

    可以根据优先级对测试用例进行分组和排列。该框架大幅简化了数据库测试、前端测试等方面。

    您可以对数据采取参数化、并使用注释来轻松地设置优先级。当然,如果您的项目并不需要测试用例的优先级,则也没必要用到TestNG。

    它的唯一缺点是:

    用户需要一些时间来设置TestNG。

    TestNG的特点与竞品比较

    如前所述,TestNG虽然与JUnit有着相同的功能,但是它补足了JUnit的短板。在面对既有的依赖性,您却无法控制先测试哪个的时候,TestNG允许您以任意顺序运行测试用例。此外,它还有助于实现参数化的测试。虽然JUnit 4.5已经具备了此功能,但是TestNG的实现效率更高。因此,如果您的项目很复杂、并且需要执行上百种测试用例的话,花点时间去设置TestNG是完全值得的。

    由Selenium提供的Selenide,可用作为Java应用程序编写稳定、精确且具有友好UI的测试用例。如今,针对Ajax之类Web技术的测试工具日趋复杂,动辄便会出现超时的问题。而Selenide却能够以简单的方式处理该问题。Selenide简单易学,您无需搜索任何相关教程,只需专注于业务逻辑,便可通过几行简单的代码来搞定工作。

    使用Selenide的先决条件

    Selenide的安装非常简单。如果您使用的是Maven,则只需要在pom.xml文件中添加如下代码行:

    com.codeborne selenide 5.1.0 test

    如果您使用的是Ivy,请在ivy.xml文件中添加如下代码行:

    Selenide的优点和缺点

    在测试人员处理那些由Java编写的前端应用时,往往会碰到超时的问题。也许您当前编写的测试用例尚能正常工作。而几天之后,随着某些Ajax请求的增多,相应的JavaScript的运行则可能会慢下来。此外,如果您的系统还同时运行着另一个进程的话,这些都会导致测试用例的失败。您与其花上几天时间去寻找问题的根源,不如让Selenide从如下方面帮助您:

    简洁的测试用例编写过程,消除了超时的问题。

    能够测试由AngularJS所开发的应用程序。

    减少了各种传统Selenium工具中的大量命令。

    目前,我们尚未发现Selenide的明显缺点。

    Selenide的特点与竞品比较

    WebDriver虽然是UI测试的流行工具,但是它无法解决由Ajax超时、JavaScript运行缓慢、以及加载动态内容耗时等一系列问题。过去,我们在测试用例中使用的是“wait_until”或“sleep”方法。如今有了Selenide,我们只要关注业务逻辑便可。可以说,就UI测试而言,除了Selenium WebDriver(Selenide的父框架),没有比它更好的Java框架了。

    总结

    如今的敏捷(Agile)时代,开发人员时常需要参与到测试环节中。能够了解测试的重要性,往往是Java专业开发人员与业余爱好者之间的区别。虽然您没有必要一定成为该领域的专家,但是您至少应当懂得,如何编写可自动化验证代码的测试用例。希望上述介绍与比较的五种自动化测试框架与工具,能够在UI测试、单元测试、以及针对应用程序的BDD测试中给您提供帮助。

    更多相关内容
  • 2019 Python接口自动化测试框架实战开发(一)

    万次阅读 多人点赞 2019-06-28 15:55:25
    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!...整个项目分为四个部分:接口基础丶接口开发丶Unittest与接口测试结合以及接口自动化框架从设计到开发 接口基础包括:H...

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!

    项目源码下载

    目录

    一丶叙述

    二丶接口基础知识

    三丶接口测试工具

    四丶Fiddler的使用

    五丶unittest使用

    六丶mock服务入门到实战

    七丶接口自动化框架设计到开发


    一丶叙述

    1.项目介绍

    整个项目分为四个部分:接口基础丶接口开发丶Unittest与接口测试结合以及接口自动化框架从设计到开发

    接口基础包括:HTTP接口 / 常见接口 / 接口工具 / 接口基础知识

    接口开发:通过Django来开发get/post接口

    Unittest与接口测试结合:unittest应用 / 断言 / requests引入 / HTMLTestRunner / case的管理

    接口自动化框架从设计到开发:如何设计框架 / 封装工具类 / 重构基类 / 错误调试 / 结果收集以及处理 / 解决数据依赖 / 结果统计及报告发送

    项目整体思路:通过对接口数据文档的读写操作,来获取文档中case的所有数据,然后通过requests模块来发送请求获取的响应数据,通过返回的响应数据中的某个标志性字段的值来判断是否测试成功或者失败,最后将测试的结果数据写入到测试文档或者是html页面又或者是将结果以邮件的形式发送到指定邮箱,这是整个大框架思路,要完成这一系列自动化的测试框架,则需要有一定的python代码基础,博主这里只是粗略的叙述了思路,有很多地方就不细说了比如数据依赖等就请大家慢慢的阅读吧

    2.测试报告效果预览

    • unittest和HTMLTestRunner结合生成报告(新版本的)

    •  unittest和HTMLTestRunner结合生成报告(经典版本的)

    •  测试报告邮件通知

    二丶接口基础知识

    1.什么是接口

    连接前后端以及移动端,通俗来说就是前端和后端之间的桥梁,比如网站需要去调用银行丶微信及支付宝的接口来完成业务需求

    2.接口的种类

    外部接口和内部接口;内部接口又分为上层服务与下层服务以及同级服务

    3.接口的分类

    请求方式:post丶get丶delete丶put

    4.为什么要做接口测试

    原因:不同端的工作进度肯定是不一致的,那么就需要对最开始开发出来的接口进行测试;对于项目来说缩短项目周期,提高开发效率以及提高系统的健壮性

    5.接口测试流程

    需求讨论——需求评审——场景设计——用例设计——数据准备——执行

    6.为什么要设计测试用例

    • 理清思路,避免侧漏
    • 提高测试效率
    • 跟进测试进度
    • 告诉领导做过
    • 跟进重复重复性工作

    7.用例设计分类

    功能用例测试:测试功能是否正常丶测试功能是否按照接口文档实现

    逻辑用例设计:是否存在依赖业务,例如有些操作是需要用户登录成功的状态下才能进行的操作

    异常测试用例设计:参数异常以及数据异常;参数异常包括关键字参数丶参数为空丶多参数丶少参数丶错误参数,数据异常包括关键字数据丶数据为空丶长度不一致丶错误数据

    安全测试用例设计:cookie丶header丶唯一识别码

    三丶接口测试工具

    1.接口测试工具分类

    • 抓取接口工具

    httpwatch:集成于IE和Firefox浏览器中,在其他浏览器中无法使用,查看数据也比较麻烦

    wireshark:只要是经过电脑的所有请求都会去抓取,导致数据量比较庞大,看数据也比较麻烦

    fiddler:轻量级抓包工具,功能比较全,只会记录http请求不会像wireshark工具记录tcp和udp等请求

    • 测试接口工具:

    loadrunner:不仅仅是性能测试工具,由于该工具几乎都是基于http请求,所以也可以用来测试接口

    fiddler:它除了可以抓包还可以向接口发送各种请求

    soapui:接口和自动化测试工具,功能也比较强大

    jmeter:跟loadrunner一样不仅仅是做性能测试,也可以对接口进行测试

    postman:谷歌旗下的接口测试工具

    四丶Fiddler的使用

    1.抓取不同类型接口数据(http以及https)

    • 查看windows本机的IP

    • 配置fiddler

    • 需要保证要抓取的手机与电脑保持同一网段,博主这里使用逍遥模拟器模拟安卓手机,修改手机网络

    • 在高级选项中设置手动代理IP为windows本机IP地址,端口设置与fiddler抓取端口保持一致

    • 再安卓手机中打开知乎app,抓取知乎app的http服务的数据

    • 现在的移动app都是基于https请求的,所以需要在fiddler中设置https请求

    • 然后在手机端浏览器中访问windows电脑IP+port,进行网络安全证书的下载安装

    • 点击下面一个下载证书

    • 然后设置密码即可

    • 证书安装成功后,重新打开知乎app,则成功抓取https请求的数据

    • 在知乎app中随便对一文章进行评论,抓取该app评论接口

    2.数据模拟以及过滤规则

    • 如下图进行选择要过滤的hosts类型,并在输入框添加要过滤的hosts即可

    • 对知乎上的一篇文章进行回答后,获取https://api.zhihu.com/answers接口,查看发送的post请求数据中的content字段内容也就是博主回答的内容

    • 然后进行数据模拟,也就是点击fiddler软件上的replay对https://api.zhihu.com/answers接口进行post请求数据的而二次发送,由于知乎这边设定对一个问题只能进行一次回答,所以知乎服务器返回的json数据提示我们失败,同时也说明对接口进行二次数据发送成功,只是规则逻辑失败

    3.如何模拟接口响应数据

    • 首先第一步,访问知乎app热榜,在fiddler软件中获取接口查看服务器响应的json格式数据,从服务器返回的json数据看出热榜标题字段名为title_area

    • 然后选择服务器返回的数据类型为TextView,点击.View in Notepad即打开数据记事本,如下图在记事本中找到title_area字段的内容,该字段内容进行了将中文转换为一串字符串

    • 将记事本中的title_area字段的数据修改为this is a test for cdtaogang

    • 点击文件——另存为保存到桌面 

    • 回到fiddler中,左侧选中热榜接口,右侧选中AutoResponder,在此窗口下点击Add Rule将左侧的接口添加进去,在右侧下方导入保存在桌面的zhihu_hot.htm文件,最后点击sava保存

    • 回到知乎app中刷新当前热榜页面,则成功返回修改的热榜标题

    4.使用fiddler进行评论接口测试

    • 对一篇文章进行评论,抓取评论接口,因为get请求的接口测试太简单,所以博主这里选择评论接口即POST请求方式

    • 右击评论接口选择copy复制接口的url地址

    • 右侧选择Composer,将复制的评论接口url粘贴到地址栏,并选择POST请求方式

    • 因为评论接口涉及到用户身份验证也就是登录后才能进行评论的,所以需要将comments接口中request headers请求头中的所有请求数据以及请求数据中的TextView的值进行复制

    请求头数据

    请求体数据

    • 将上面复制的请求头和请求体数据分别粘贴到如下输入框中,点击Execute执行发送,然后在左侧则出现了另一个comments接口数据

    • 查看该comments接口,服务器返回的响应数据中与第一个comments接口一致,说明接口测试成功

    五丶unittest使用

    1.unittest简单使用

    • 在IDE中使用python的环境随便创建个py文件,需要注意的是该py文件的名字不能是test.py,否在运行时会出错,unittest包是python自带的不需要下载安装,代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/17 13:10'
    
    import unittest
    
    
    class TestMethod(unittest.TestCase):
    
        @classmethod
        def setUpClass(cls):
            print("Method before class execution")
    
        @classmethod
        def tearDownClass(cls):
            print("Method after class execution")
    
        def setUp(self):
            print("------setUp------")
    
        def tearDown(self):
            print("------tearDown------")
    
        def test_01(self):
            print("First test method")
    
        def test_02(self):
            print("The second test method")
    
    
    if __name__ == '__main__':
        unittest.main()
    • 直接run运行以上代码

    2.unittest和request重构封装

    说明:使用requests模块对接口url地址发送请求,通过unittest测试框架进行case测试

    • 首先博主在逍遥安卓模拟器中下载了一个看书app,通过fiddler对app上的某一接口进行获取,之所以选择对此app进行接口测试,是因为该app的所有接口全是POST请求

    • 在PyCharm下新建工程目录,目录下创建base包,在包下创建一个demo.py文件以及test_method.py文件,用于使用unittest框架来测试以上app接口

    • 在demo.py文件中,使用requests get以及post方法进行了封装,主要是根据传递的参数method来对get以及post方法进行分别调用而已,具体实现如下
    import requests
    
    
    class RunMain:
    	def send_get(self,url,data):
    		res = requests.get(url=url,data=data).json()
    		return res
    		
    	def send_post(self,url,data):
    		res = requests.post(url=url,data=data).json()
    		return res
    
    	def run_main(self,url,method,data=None):
    		res = None
    		if method == 'GET':
    			res = self.send_get(url,data)
    		else:
    			res = self.send_post(url,data)
    		return res
    • 在test_method.py文件中则创建测试类以及test方法,在test方法中调用demo.py中的run_main方法,即使用requests模块向传递的接口url地址和请求方式以及请求体发送对应的请求,这里使用setUp方法则是利用其优先调用而对RunMain类进行实例化
    import unittest
    import json
    import HtmlTestRunner
    from .demo import RunMain
    
    
    class TestMethod(unittest.TestCase):
        def setUp(self):
            self.run = RunMain()
    
        def test_01(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
                "sstoken":"eyJleHAiOjE1Njg1MzgyNTczMzUsImlhdCI6MTU2MDc2MjI1NzMzNSwicHAiOiIxMTQwNTQ1Njg5MDYwMDQ0ODAwQHNvaHUuY29tIiwidGsiOiIwZkNYSHpjTUZzR0dFMEswbVdvUVFCNWVCanpXa0hmWiIsInYiOjB9.SDYkT9FpWrBbko6xRrESN74IXJhzkqQLtijKjGiVrqA",
                "gidinf":"x011060802ff0fd40695d68140002799751474c540b3",
                "ppinf":"2|1560762257|1561971857|bG9naW5pZDowOnx1c2VyaWQ6Mjg6MTE0MDU0NTY4OTA2MDA0NDgwMEBzb2h1LmNvbXxzZXJ2aWNldXNlOjMwOjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMHxjcnQ6MTA6MjAxOS0wNi0xN3xlbXQ6MTowfGFwcGlkOjY6MTEwNjA4fHRydXN0OjE6MXxwYXJ0bmVyaWQ6MTowfHJlbGF0aW9uOjA6fHV1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1bmlxbmFtZTowOnw",
                "pprdig":"kaKPdU0WwIdzL58CqxNz5pgMyv23P0-Y5GRnd5ufPlXIGzrk7_7TlIK5XFQiuoqAHNqGVXHCVd4cB1DIkR5yFZ_nExnSjIZbBJWYlMkrsiIjDYqWCvedZRLm8sZqS0WqA0FcKXuSn3Z0gVRus9YpEonNz5wyuWdUqxaSmzlzygY",
                "ppsmu":"1|1560762257|1561971857|dXNlcmlkOjI4OjExNDA1NDU2ODkwNjAwNDQ4MDBAc29odS5jb218dWlkOjA6fHV1aWQ6MDo|byWcaoPqy02s2_9GHLhZFAQ6Ov_GazMPFLrq115HiSTBS9Ijr33a55quRq2Mr1_6ZMruKEk-BYFpShUaMtwRYA"
            }
            res1 = self.run.run_main(url, "POST", json.dumps(data))
            print(res1)
    
    
        def test_02(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
    
            }
            res2 = self.run.run_main(url, 'POST', data)
    
            print(res2)
    
    
    if __name__ == '__main__':
        unittest.main()
    • 运行test_method模块,查看测试接口,test_02则是错误测试

    3.unittest中assert的使用

    • 首先根据返回的结果字典dict数据中的status状态值来判断测试是否通过或者失败,逻辑很基础就不细说了
    class TestMethod(unittest.TestCase):
        def setUp(self):
            self.run = RunMain()
    
        def test_01(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
                "sstoken":"eyJleHAiOjE1Njg1MzgyNTczMzUsImlhdCI6MTU2MDc2MjI1NzMzNSwicHAiOiIxMTQwNTQ1Njg5MDYwMDQ0ODAwQHNvaHUuY29tIiwidGsiOiIwZkNYSHpjTUZzR0dFMEswbVdvUVFCNWVCanpXa0hmWiIsInYiOjB9.SDYkT9FpWrBbko6xRrESN74IXJhzkqQLtijKjGiVrqA",
                "gidinf":"x011060802ff0fd40695d68140002799751474c540b3",
                "ppinf":"2|1560762257|1561971857|bG9naW5pZDowOnx1c2VyaWQ6Mjg6MTE0MDU0NTY4OTA2MDA0NDgwMEBzb2h1LmNvbXxzZXJ2aWNldXNlOjMwOjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMHxjcnQ6MTA6MjAxOS0wNi0xN3xlbXQ6MTowfGFwcGlkOjY6MTEwNjA4fHRydXN0OjE6MXxwYXJ0bmVyaWQ6MTowfHJlbGF0aW9uOjA6fHV1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1bmlxbmFtZTowOnw",
                "pprdig":"kaKPdU0WwIdzL58CqxNz5pgMyv23P0-Y5GRnd5ufPlXIGzrk7_7TlIK5XFQiuoqAHNqGVXHCVd4cB1DIkR5yFZ_nExnSjIZbBJWYlMkrsiIjDYqWCvedZRLm8sZqS0WqA0FcKXuSn3Z0gVRus9YpEonNz5wyuWdUqxaSmzlzygY",
                "ppsmu":"1|1560762257|1561971857|dXNlcmlkOjI4OjExNDA1NDU2ODkwNjAwNDQ4MDBAc29odS5jb218dWlkOjA6fHV1aWQ6MDo|byWcaoPqy02s2_9GHLhZFAQ6Ov_GazMPFLrq115HiSTBS9Ijr33a55quRq2Mr1_6ZMruKEk-BYFpShUaMtwRYA"
            }
            res1 = self.run.run_main(url, "POST", json.dumps(data))
            # print(type(res1))
            # print(res1['pub'])
            # print(type(res1['pub']))
            if res1['pub']['status'] == 0:
                print("测试通过")
            else:
                print("测试失败")
            print(res1)
    
    
        def test_02(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
    
            }
            res2 = self.run.run_main(url, 'POST', data)
            if res2['pub']['status'] == 0:
                print("测试通过")
            else:
                print("测试失败")
            print(res2)
    
    
    if __name__ == '__main__':
        unittest.main()
    • 运行以上代码,查看结果与预期一样

    • 将if判断代码更换成unittest模块中的assert断言进行判断,这里使用assertEqual方法来判断两个值是否相等,当两个值相等则返回OK,当不相同时返回assertEqual方法msg变量自定义的值
    class TestMethod(unittest.TestCase):
        def setUp(self):
            self.run = RunMain()
    
        def test_01(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
                "sstoken":"eyJleHAiOjE1Njg1MzgyNTczMzUsImlhdCI6MTU2MDc2MjI1NzMzNSwicHAiOiIxMTQwNTQ1Njg5MDYwMDQ0ODAwQHNvaHUuY29tIiwidGsiOiIwZkNYSHpjTUZzR0dFMEswbVdvUVFCNWVCanpXa0hmWiIsInYiOjB9.SDYkT9FpWrBbko6xRrESN74IXJhzkqQLtijKjGiVrqA",
                "gidinf":"x011060802ff0fd40695d68140002799751474c540b3",
                "ppinf":"2|1560762257|1561971857|bG9naW5pZDowOnx1c2VyaWQ6Mjg6MTE0MDU0NTY4OTA2MDA0NDgwMEBzb2h1LmNvbXxzZXJ2aWNldXNlOjMwOjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMHxjcnQ6MTA6MjAxOS0wNi0xN3xlbXQ6MTowfGFwcGlkOjY6MTEwNjA4fHRydXN0OjE6MXxwYXJ0bmVyaWQ6MTowfHJlbGF0aW9uOjA6fHV1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1aWQ6MTY6czk1YWIwNDk5NjE3YmJhNnx1bmlxbmFtZTowOnw",
                "pprdig":"kaKPdU0WwIdzL58CqxNz5pgMyv23P0-Y5GRnd5ufPlXIGzrk7_7TlIK5XFQiuoqAHNqGVXHCVd4cB1DIkR5yFZ_nExnSjIZbBJWYlMkrsiIjDYqWCvedZRLm8sZqS0WqA0FcKXuSn3Z0gVRus9YpEonNz5wyuWdUqxaSmzlzygY",
                "ppsmu":"1|1560762257|1561971857|dXNlcmlkOjI4OjExNDA1NDU2ODkwNjAwNDQ4MDBAc29odS5jb218dWlkOjA6fHV1aWQ6MDo|byWcaoPqy02s2_9GHLhZFAQ6Ov_GazMPFLrq115HiSTBS9Ijr33a55quRq2Mr1_6ZMruKEk-BYFpShUaMtwRYA"
            }
            res1 = self.run.run_main(url, "POST", json.dumps(data))
            # print(type(res1))
            # print(res1['pub'])
            # print(type(res1['pub']))
            # if res1['pub']['status'] == 0:
            #     print("测试通过")
            # else:
            #     print("测试失败")
            self.assertEqual(res1['pub']['status'], 0, "测试失败")
            print(res1)
    
    
        def test_02(self):
            url = 'http://api.ishugui.com/asg/portal/call/265.do'
            data = {
    
            }
            res2 = self.run.run_main(url, 'POST', data)
            # if res2['pub']['status'] == 0:
            #     print("测试通过")
            # else:
            #     print("测试失败")
            self.assertEqual(res2['pub']['status'], 0, "测试失败")
            print(res2)
    
    
    if __name__ == '__main__':
        unittest.main()
    • 测试查看结果,断言失败,测试结果如下很清晰

    4.unittest中case的管理及运用

    • 在测试一些接口时,有些接口的返回数据需要在下一个接口进行使用,所以需要定义全局变量,方便每个case都能够得着,当在test_01中定义全局变量userid,然后在test_02中进行打印

    • 在unittest中,是按照字母数字来进行case先后执行顺序的,将test_01改为test_03后,运行代码后,会提示test_02中的userid未定义,原因是程序先去执行了test_02这个case,所以出现该提示是正常的

    • 当在测试代码中有很多case时,我想跳过某个case,则在该case方法上定义unittest的skip方法装饰器,并需要传递此方法名作为实参进行传递

    • 除了在if __name__ == '__main__'中使用unittest.main方法执行所有的case以外,还可以将要测试的case添加到unittest.TestSuite集合中执行想要执行的case,若想要全部都执行则需要一个一个的添加

    5.unittest和HTMLTestRunner结合生成报告(博主这里给大家展现两种)

    第一种:比较新版本的htmltestrunner报告

    • 然后将下载好的whl文件放在你的项目环境的Scripts目录下

    • 最后在Terminal终端或者cmd终端中进入以上目录,执行如下命令即可

    • 安装成功后,即在以下路径中可以找到安装的HTMLTestRunner的包了

    • 在if __name__ == '__main__'中只需要调用HtmlTestRunner模块中的HtmlTestRunner类,向该类传递报告标题参数值即可,其他均默认,需要注意的时启动文件run为当前的py文件,如果是Unittests开头的启动文件,则不会运行if __name__ == '__main__'下的代码,只会执行unittest框架的setUp以及test开头的case代码

    • 运行test_method.py文件,成功在base目录下创建reports目录,并在该目录下生成对应时间的测试报告

    • 打开reports目录下生成的html测试报告,查看测试内容,与预期设定一样,test_02失败test_03成功,说明一下报告中的乱码为中文

    第二种:比较经典版本的htmltestrunner报告

    • 为了方便演示效果,博主在testItems项目目录下,创建base2的模块,将base模块下的demo.py和test_method.py文件拷贝到base2目录下并将test_method.py命令为test_method2.py免得搞混淆,然后在base2目录下新建HTMLTestRunner.py文件用于存放其源码,目录结构如下

    第94行, 将import StringIO修改成import io
    第539行,将self.outputBuffer = StringIO.StringIO()修改成self.outputBuffer = io.StringIO()
    第642行,将if not rmap.has_key(cls):修改成if not cls in rmap:
    第631行,将print >> sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)修改成print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))
    第766行,将uo = o.decode('latin-1')修改成uo = e
    第775行,将ue = e.decode('latin-1')修改成ue = e
    • 在test_method2模块中首先需要从base2模块中去导入HTMLTestRunner文件,然后if __name__ == '__main__'中,需要创建一个文件源,同样是调用HTMLTestRunner模块中的HTMLTestRunner类,不同的是需要将创建的文件源传递给实例属性stream变量

    • 运行test_method2.py,成功在上一级report目录下生成html_report.html报告文件

    • 打开html_report.html测试报告,测试结果与代码设定一致

    六丶mock服务入门到实战

    1.mock简介

    mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法,mock是在测试过程中,对于一些不容易构造/获取的对象,创建一个mock对象来模拟对象的行为即就是模拟fiddler返回接口响应数据的一个过程。

    2.mock安装

    • 在终端使用pip进行安装即可

    3.在case中通过底层函数实现mock

    • 在test_method模块中导入mock,然后在test_03函数中通过以下代码设置返回的return_value的值为请求的data数据
    mock_data = mock.Mock(return_value=data)
    print(mock_data)
    • run运行Unittests in test_method.py,打印出Mock id的值

    • 将调用run_main方法的值设定为mock_data,即print(res1)则表示打印请求的data数据的值,因为res1的数据不再是接口返回的响应数据,则arrest断言是会提示报错的,这是正常的

    4.重构封装mock服务

    • 在base目录下创建mock_demo.py文件,构造一个mock_test方法,该方法就是将test_03方法中self.run.run_main = mock.Mock(return_value=data) 和 res1 = self.run.run_main(url, "POST", json.dumps(data))方法的调用进行了封装成为test_02和test_03方法通用的一个方法,上一步骤中的代码mock_data = mock.Mock(return_value=data) 和self.run.run_main = mock_data,即就相当于self.run.run_main = mock.Mock(return_value=data)而已,都是python基本的调用封装基础知识,mock_demo.py中的代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/20 16:26'
    from mock import mock
    import json
    
    def mock_test(mock_method, request_data, url, method, response_data):
        """
        :param mock_method:
        :param request_data:
        :param url:
        :param method:
        :param response_data:
        :return: res
        """
        mock_method = mock.Mock(return_value=response_data)
        print('mock_method:', mock_method)
        res = mock_method(url, method, json.dumps(request_data))
        return res
    • 那么在test_03方法中,如下进行调用即可
    res1 = mock_test(self.run.run_main, data, url, 'POST', 'ssssssss')
    print('res1:', res1)
    • 运行Unittests in test_method.py,查看运行结果和博主设定一样成功返回自定义的response_data数据

    七丶接口自动化框架设计到开发

    1.如何设计一个接口自动化测试框架

    根据接口地址丶接口类型丶请求数据丶预期结果来进行设计,对于需要登录后才能进行操作的接口那么则需要进行header cookie等数据的传递,自动化测试的难点就是数据依赖。

    2.python操作excel获得内容

    • 首先python操作excel,需要安装两个包,分别是xlrd和xlwt这两个库,xlrd这个库是负责读取excel数据的,而xlwt库是负责向excel写入数据的

    • 在项目目录下创建utils工具包,在该包下创建op_excel.py文件,在该文件中通过导入xlrd包,对excel表的数据进行读取操作

    3.重构操作excel函数

    • 根据上一步骤读取excel表的内容代码后,进行了一个简单的封装,提高代码的通用性,过程相当的简单,实现代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/20 17:33'
    import xlrd
    
    data = xlrd.open_workbook("../test_data/rs.xls")
    tables = data.sheets()[0]  # 获取表格数据对象
    print(tables.nrows) # 打印表格行数
    print(tables.cell_value(0,0))  # 打印excel表格数据,需要传递数据所在的坐标(x,y)
    print(tables.cell_value(0,1))
    print("*"*50+"封装前后数据对比"+"*"*50)
    
    
    class operationExcel(object):
        def __init__(self, file_path="../test_data/rs.xls", sheet_id=0):
            self.file_path = file_path
            self.sheet_id = sheet_id
            self.data = self.get_data()
    
        def get_data(self):
            data = xlrd.open_workbook(self.file_path)
            tables = data.sheets()[self.sheet_id]
            return tables
    
        def get_rows(self):
            """获取单元格的排数"""
            return self.data.nrows
    
        def get_cell_value(self, x=0, y=0):
            """获取某个单元格的数据"""
            return self.data.cell_value(x, y)
    
    
    if __name__ == '__main__':
        print(operationExcel().get_rows())
        print(operationExcel().get_cell_value())
        print(operationExcel().get_cell_value(0,1))
    • 运行op_excel.py文件后,结果与封装之前代码结果一致,表示重构封装代码成功

    4.学习操作json文件

    • 自定义一个登录的json文件名为login.json,文件内容如下,存放在test_data目录下

    • 在utils工具包下创建op_json.py文件,在文件中对login.json文件内容进行读取操作,代码如下

    5.重构json工具类

    • 将上一步操作json的代码进行封装
    class operationJson(object):
        def __init__(self, file_path="../test_data/login.json"):
            self.file_path = file_path
            self.data = self.get_data()
    
        def get_data(self):
            with open(self.file_path) as f:
                data = json.load(f)
                return data
    
        def get_key_words(self, key=None):
            if key:
                return self.data[key]
            else:
                return self.data
    
    
    if __name__ == '__main__':
        print(operationJson().get_key_words())
        print(operationJson().get_key_words("login"))
        print(operationJson().get_key_words("login")['username'])
    • 运行op_json.py文件,结果与封装之前代码结果一致,表示重构封装代码成功

    6.封装获取常量方法

    • 首先打开excel表格,查看需要获取的字段有哪些

    • 对excel表的字段进行获取,在项目目录下创建名为data的python包,在该包下创建data_conf.py,代码就是简单的获取对应的变量值,具体如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/21 9:29'
    
    
    class global_var:
        id = '0'  # id
        module = '1'  # 模块
        url = '2'  # url
        run = '3'  # 是否运行
        request_type = '4'  # 请求类型
        request_header = '5'  # 是否携带header
        case_depend = '6'  # case依赖
        response_data_depend = '7'  # 依赖的返回数据
        data_depend = '8'  #  数据依赖
        request_data = '9'  # 请求数据
        expect_result = '10'  # 预期结果
        reality_result = '11'  # 实际结果
    
    
    def get_id():
        return global_var.id
    
    def get_module():
        return global_var.module
    
    def get_url():
        return global_var.url
    
    def get_run():
        return global_var.run
    
    def get_request_type():
        return global_var.request_type
    
    def get_request_header():
        return global_var.request_header
    
    def get_case_depend():
        return global_var.case_depend
    
    def get_response_data_depend():
        return global_var.response_data_depend
    
    def get_data_depend():
        return global_var.data_depend
    
    def get_request_data():
        return global_var.request_data
    
    def get_expect_result():
        return global_var.expect_result
    
    def get_reality_result():
        return global_var.reality_result

    7.封装获取接口数据

    • 在data目录下创建data_get.py文件,在该文件中对excel表数据以及json数据结合上一步封装的常量方法整合后的实现,代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/21 10:01'
    from utils.op_excel import operationExcel
    from utils.op_json import operationJson
    from data import data_conf
    
    class getData(object):
        def __init__(self):
            self.op_excel = operationExcel()
    
        def get_case_lines(self):
            """获取表格行数"""
            return self.op_excel.get_rows()
    
        def get_is_run(self, x):
            """获取case是否运行"""
            flag = None
            y = data_conf.get_run()
            run_value = self.op_excel.get_cell_value(x, y)
            if run_value == 'yes':
                flag = True
            else:
                flag = False
            return flag
    
        def get_is_header(self, x):
            """是否携带header"""
            y = data_conf.get_request_header()
            header = self.op_excel.get_cell_value(x, y)
            if header == 'yes':
                return data_conf.get_header_value()
            else:
                return None
    
        def get_request_method(self, x):
            """获取请求方式"""
            y = data_conf.get_request_type()
            request_method = self.op_excel.get_cell_value(x, y)
            return request_method
    
        def get_request_url(self, x):
            """获取请求地址"""
            y = data_conf.get_url()
            request_url = self.op_excel.get_cell_value(x, y)
            return request_url
    
        def get_request_data(self, x):
            """获取请求数据"""
            y = data_conf.get_request_data()
            request_data = self.op_excel.get_cell_value(x, y)
            if request_data == '':
                return None
            return request_data
    
        def get_data_for_json(self, x):
            """通过excel中的关键字去获取json数据"""
            op_json = operationJson()
            data = op_json.get_key_words(self.get_request_data(x))
            return data
    
        def get_expect_data(self, x):
            """获取预期结果数据"""
            y = data_conf.get_expect_result()
            expect_data = self.op_excel.get_cell_value(x, y)
            if expect_data == '':
                return None
            return expect_data

    8.post、get基类的封装

    • 在base包下创建run_method.py文件,在文件中重新编写对get丶post请求方式的代码封装,具体如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/21 11:19'
    import requests
    
    
    class RunMain(object):
    
        def get_main(self, url, data=None, header=None):
            res = None
            if header is not None:
                res = requests.get(url=url, data=data, headers=header).json()
            else:
                res = requests.get(url=url, data=data).json()
            return res
    
        def post_main(self, url, data, header=None):
            res = None
            if header is not None:
                res = requests.post(url=url, data=data, headers=header).json()
            else:
                res = requests.post(url=url, data=data).json()
            return res
    
    
        def run_main(self, url, method, data=None, header=None):
            res = None
            if method.lower() == 'post':
                res = self.post_main(url, data, header)
            elif method.lower() == 'get':
                res = self.get_main(url, data, header)
            else:
                return "what ?????"
            return res

    9.主流程封装及错误解决调试

    • 首先在testItems项目目录下新建一个名为main的python包,在该包下创建名为run_test的py文件,该文件为主程序启动文件,代码的逻辑就是将前面封装的方法进行了调用核心就是读取excel表的数据,通过读取到的数据,发送请求,其中包括某一些变量的判断,根据该判断然后到json数据中获取请求的数据,最后就这么的简单,代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/21 11:57'
    from base.run_method import RunMain
    from data.data_get import getData
    
    
    class RunTest(object):
        def __init__(self):
            self.runmain = RunMain()
            self.data = getData()
    
        def run(self):
            res = None
            row_counts = self.data.get_case_lines()  # 获取excel表格行数
            # print(row_counts) 5
            for row_count in range(1, row_counts):
                # print(row_count) 1,2,3,4
                url = self.data.get_request_url(row_count)  # y行不变遍历获取x列的请求地址
                method = self.data.get_request_method(row_count)  # y行不变遍历获取x列的请求方式
                is_run = self.data.get_is_run(row_count)  # y行不变遍历获取x列的是否运行
                data = self.data.get_data_for_json(row_count)  # y行不变遍历获取x列的请求数据,这里面时三次调用,依次分别是get_data_for_json丶get_key_words丶get_request_data
                header = self.data.get_is_header(row_count)
                print('url:', url)
                print('method:', method)
                print('is_run:', is_run)
                print('data:', data)
                print('header:', header)
    
                if is_run:
                    res = self.runmain.run_main(url,method,data,header)
                    print("*"*60+"分割线"+"*"*60)
            return res
    
    
    if __name__ == '__main__':
        print('res:', RunTest().run())
    • 运行run_test,成功的将excel以及json数据正确打印出来,返回res服务器返回结果,需要说明的是excel表中的所有数据都不是真实存在的,包括json文档数据也是,这里主要是测试整个框架的正确性读取excel以及json文档数据,并正确的发送请求获得相应数据

    • 运行结果出现红色的内容,是由requests模块发送请求的安全请求警告,如不想显示此警告,可以在run_method.py发送请求核心代码进行禁用,禁用代码如下

    • 重新运行run_test,安全请求警告不再显示

    • 根据代码运行结果,对比excel表以及json数据文档内容,数据正确无误

    10. 返回数据格式处理以及调错

    • 为了测试返回的接口的响应数据,博主这里在excel文档以及json文档中添加了一条数据

    • 因为在excel文档中小说的接口不携带header所以在向接口发送请求数据核心代码块,进行了如下修改,因为在excel文档中的最后一个接口时真实的,所以只需要对最后一个接口url返回的字典类型的响应数据进行转换成json格式的数据,并按照关键字进行排序

    • 运行run_test,在最后一个接口中成功打印出我们想要的数据

    11.获取接口返回状态

    • 在发送请求数据核心代码中,进行打印返回的状态码status_code即可,最后一个接口比较特殊,返回的响应数据中没有status_code,所以需要对返回的json数据中的status进行判断,并向其返回数据中添加我们所要的status_code的值

    • 运行代码,当返回的状态码为404表示接口不存在,只要是存在响应数据,则status_code为200,必须说明一点的就是status_code为200不一定表示接口存在,有些大型网站会对其域名下不存在的接口返回200的错误页面显示,所以在测试文档中会体现预期结果和实际结果两项数据需要一致才能表示测试通过

    12.通过预期结果判断case是否执行成功

    • 进行接下来的测试,博主这里重新准备了另一个excel表来进行测试,需要对json文件中的数据进行添加,在excel表Book-05中的请求数据book5关键字对应的json文件的数据故意为空,可以对测试结果有一个对比

    • 在数据获取核心类中定义了一个方法来获取excel表模块字段的数据

    • 回过头在启动文件中获取模块名预期结果并进行打印

    • 运行启动文件,查看运行结果

    • 在utils目录下,创建common_util.py文件,在该文件代码中通过启动文件传递过来的数据来判断excel表预期结果数据的status状态码与res结果中的status状态码是否一致,一致表示测试通过,不一致则失败,代码如下
    # -*- coding: utf-8 -*-
    __author__ = 'cdtaogang'
    __date__ = '2019/6/21 18:43'
    import json
    
    class CommonUtil(object):
        def is_contains(self, expect, reality):
            flag = None
            reality = json.loads(reality)
            expect = json.loads(expect)
            if expect['status'] == reality['pub']['status']:
                flag = True
            else:
                flag = False
            return flag
    • 在启动文件中需要注释掉res响应数据,利于查看测试结果,还需要在启动文件调用is_contains方法来根据其返回值判断测试是否通过

    • 运行启动文件,查看测试结果

    13.将测试结果写入到excel中

    • 首先在op_excel.py中定义一个方法,该方法实现读取excel的数据,并进行copy复制,然后再write方法将数据写入到坐标位置

    • 然后在data_get.py中需要定义一个方法,在该方法中核心逻辑为获取y坐标的值

    • 最后在启动文件中,调用data_get模块中的write_reality_data方法,并将剩余的x坐标的值以及data数据传递给最终的核心方法write_reality_result_data来完成对excel表中的实际结果数据的写入

    • 将excel表进行关闭后,运行启动文件,再次打开excel表,实际结果数据写入正确,之所以需要关闭excel是避免提示提示错误,无法写入保存数据

    展开全文
  •  本文章主要会讲解Python中pytest框架的讲解,介绍什么是pytest、为何要测试、为何使用以及参考和扩展等

    一、前言

      本文章主要会讲解Python中pytest框架的讲解,介绍什么是pytest、为何要测试、为何使用以及参考和扩展等,除此之外下方有系列文章的传送门,还在持续更新中,感兴趣的小伙伴也可以前往查看,话不多说,让我们一起看看吧~

    系列文章:
      系列文章1:【Python自动化测试1】遇见Python之美
      系列文章2:【Python自动化测试2】Python安装配置及PyCharm基本使用
      系列文章3:【Python自动化测试3】初识数据类型与基础语法
      系列文章4:【Python自动化测试4】字符串知识总结
      系列文章5:【Python自动化测试5】列表与元组知识总结
      系列文章6:【Python自动化测试6】字典与集合知识总结
      系列文章7:【Python自动化测试7】数据运算符知识合集
      系列文章8:【Python自动化测试8】流程控制语句讲解
      系列文章9:【Python自动化测试9】函数知识合集
      系列文章10:【Python自动化测试10】文件基础操作
      系列文章11:【Python自动化测试11】模块、包与路径知识合集
      系列文章12:【Python自动化测试12】异常处理机制知识合集
      系列文章13:【Python自动化测试13】类、对象、属性与方法知识合集
      系列文章14:【Python自动化测试14】Python自动化测试基础与进阶练习题
      系列文章15:【Python自动化测试15】unittest测试框架的核心概念与作用
      系列文章16:【Python自动化测试16】测试用例数据分离
      系列文章17:【Python自动化测试17】openpyxl二次封装与数据驱动
      系列文章18:【Python自动化测试18】配置文件解析与实际应用
      系列文章19:【Python自动化测试19】日志系统logging讲解
      系列文章20:【Python自动化测试20】接口自动化测试框架模型搭建
      系列文章21:【Python自动化测试21】接口自动化测试实战一_接口概念、项目简介及测试流程问答
      系列文章22:【Python自动化测试22】接口自动化测试实战二_接口框架修改及用例优化
      系列文章23:【Python自动化测试23】接口自动化测试实战三_动态参数化与数据伪造
      系列文章24:【Python自动化测试24】接口自动化测试实战四_Python操作数据库
      系列文章25:【Python自动化测试25】接口自动化测试实战五_数据库断言、接口关联及相关管理优化

      

    二、pytest讲解

    2.1 什么是pytest?

      pytest是一款单元测试框架,在编程过程中,单元主要指的是代码中最小的组成部分,例如函数或类,在面向对象中,最小的单元就是类下面的方法。
      当我们编写好一段程序后,会对这些函数和方法进行检测,是否出现程序错误,这种对程序的函数和方法进行测试的过程,就叫做单元测试。
      pytest的测试框架类似于unittest框架相似,但pytest的测试框架比unittest更加简洁、高效,具体的pytest的基础介绍,大家可以参考:pytest使用介绍

      

    2.2 为什么使用pytest?

      pytestunittest类似,但pytest还是有很多的优势:

    """
    pytest优势
    1、pytest能够兼容unittest,如果之前用例是unittest编写的,可以使用pytest直接进行使用
    2、pytest的断言直接使用assert断言,并非使用self.asert等语法语句以及其他各式各样的断言方式
    3、pytest对于失败的测试用例会提供非常详细的错误信息
    4、pytest可以自动发现并收集测试用例
    5、pytest有非常灵活的fixture管理
    6、pytest有mark标记机制,可以标记某些用例为冒烟测试用例
    7、pytest提供了非常丰富的插件系统
    8、pytest不需要写类,unittest是需要写类并继承的,这里pytest更加简洁
    """
    

      

    2.3 使用pytest

      安装pytest库后设置默认的运行器为pytest

    def test_add():
        assert True
    

    在这里插入图片描述
    在这里插入图片描述
      在之前的文章提到了,框架就意味着规则,pytest用例规则如下:

    """
    pytest用例规则:
    1、模块名称 test开头.py结尾,或者*_test.py
    2、测试用例函数的名称 def test_XXX()
    3、可以不定义测试类
    """
    
    """
    pytest的运行方式:
    1、pycharm当中的运行图标,pytest开头开头运行,如不是pytest可以在setting中查找pytest并设置成pytest运行器
    2、pytest命令行:要进入项目的根目录运行pytest命令,pytest命令会自动收集运行指令时候,所有子目录下符合要求的测试用例,例如test_login.py,模块且以test开头,函数test开头,类也是如此
    3、通过python包或者python模块运行
    
    """
    
    
    
    
    

      

    2.4 pytest的运行方式

      pytest有三种运行方式:

    """
    方式一:直接通过代码左侧的三角进行运行(pycharm)
    """
    
    """
    方式二:通过命令行运行 -- pytest -- html=output.html
    """
    
    """
    方式三:通过python运行
    """
    from datetime import datetime
    
    import pytest
    
    date_str = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
    # 测试报告的名称
    report_name = date_str + "萌笑天的专属测试报告.html"
    
    pytest.main([f"--html={report}"])
    

      

    2.5 pytest高级特性

    2.5.1 pytest用例筛选

      我们都做过冒烟测试,也知道冒烟测试用例,pytest支持用例筛选,你可以在想要的用例上进行标记,以此来表示这是一个冒烟测试用例:

    import pytest
    
    # 格式为:@pytest.mark.自定义标记名
    @pytest.mark.smoke
    def test_True()
    	assert True
    
    @pytest.mark.smoke
    def test_False()
    	assert False
    

      我们可以给一个用例或多个用例附上单独的标记,但这样是无法运行的,我们需要先注册标记,新建一个pytest.ini的配置文件并进行配置:

    [pytest]
    markers = 
    	smoke
    

      注册完成后我们需要运行,在命令行输入pytest - m "smoke",这样就可以运行刚刚标记过的测试用例了,值得一提的是,如果这个标记是在函数上,那么就代表着函数属于标记的筛选用例,如果标记在类上,那么整个类下的所有函数都属于筛选用例,如例子所示,即全部为冒烟测试用例

    """
    用例筛选流程:
    1、需要在pytest.ini中注册标记的名称
    2、在测试用例函数或者测试用例类上面加上@pytest.mark.标记名
    3、运行指定标签 pytest -m "标记名"
    """
    

      如果运行多个标记那么可以继续在函数或类上再次进行新的标记,例如login标记,意味着我只想要执行登录模块的冒烟测试用例里,那么再次进行注册并运行即可,运行使用pytest -m "smoke and login",如果是冒烟测试用例和登录模块用例满足一个即可,那么就可以使用or即可,两者选其一,满足即运行

      

    2.5.2 pytest实现数据驱动

      pytest实现数据驱动可以使用unittest进行实现,也可以使用自己的ddt:

      注意:pytest参数化与unittest的参数化只能有一个,不能够共同使用

    """
    pytest使用unittest进行数据驱动的实现
    """
    import unittest
    imoort pytest
    from unittesetreport import ddt, list_data
    
    @pytest.mark.smoke
    @unittestreport.ddt
    class TestAddwithUnittest(unittest.TestCase):
    	
    	@unittestreport.list_data(["hello", "world", "mengxiaotian"])
    	def test_add_three(self, case_info):
    		aseert "萌笑天" in "最棒的萌笑天"
    	
    	def test_add_four(self):
    		assert "萌笑天" in "最棒的萌笑天"
    
    
    """
    使用自己的pytest实现
    """
    @pytest.mark.smoke
    @pytest.mark.login
    @pytest.mark.parametrize("case_info", ["hello", "world"])
    def test_add(case_info):
    	assert True
    
    

    2.5.3 pytest夹具

      pytest夹具会与unittest有一些不同,详见代码:

    def setup_function():
        """前置条件,每个测试用例之前"""
        print("hello, world!")
    
    def teardown_function():
        """后置条件,每个测试用例之后"""
    
    def test_hello():
        assert 520 == 1314
    
    def test_world():
        assert "萌" in "萌笑天"
    
    import pytest
    
    # 声明这是一个测试夹具
    @pytest.fixture()
    def connet_to_db():
        print("前置条件:正在连接数据库...")
        yield # 在yield前的都是前置
    # 清理动作
        print("后置清理,断开数据库连接...")
    
    @pytest.mark.usefixtures("connect_to_db")
    def test_mengxiaotian_love():
        assert 1314 == 1314
    

      

    2.6 allure下载

      万能百度搜索allure进入到GitHub下载或直接点击超链接:allure下载
      找到Download的字眼,并在其中点击releases
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
      

    2.7 pytest插件:allure-pytest安装与目录生成

      通过pip install allure-pytest进行安装
      生成报告在命令行中输入:pytest --alluredir=目录
      查看报告使用:allure serve 目录
      allure可以翻译成中文,具体这里不过多阐述如何查看报告数据,有兴趣的同学可以自行了解

    在这里插入图片描述

      

    2.8 unittest转pytest形式

      如果以代码形式呈现会比较复杂,笔者直接使用备注进行说明,大家如果之前的项目是unittest的项目那么可以根据本次说明转换成pytest

    """
    unittest转pytest:
    1、数据驱动的ddt换成pytest的标记形式
    2、unittest的testcase继承需要移除
    3、self.asserEqual 需要重新封装
    4、setUpclass 改成 pytest setup_class (参考上面的代码)
    """
    

      
      

      好啦~以上就是本次文章分享的全部内容啦,你学会了吗?希望能给大家带来帮助哦!

      
      

    在这里插入图片描述

    展开全文
  • 自动化测试框架总结

    万次阅读 多人点赞 2021-12-26 15:05:36
    目录 1. 单元测试框架 2. Web自动化测试框架 3. iOS自动化测试框架 4. Android自动化测试框架 ...unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可..

    目录

     1. 单元测试框架

    2. Web自动化测试框架

    3. iOS自动化测试框架

    4. Android自动化测试框架

     1. 单元测试框架

    几乎所有的主流语言,都会有其对应的单元测试框架,下面简单介绍一下python,java,C#三种语言的常见单元测试框架

    1.1 Python

    python常见单元测试框架包括unittest, pytest

    1.1.1 unittest

    • unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果。
    • unittest为python内置库,不需要单独安装(好像也和版本有关系)

    1.1.2 pytest

    pytest是一个非常成熟的全功能的Python测试框架,主要有以下几个特点:

    • 简单灵活,容易上手
    • 支持参数化
    • 能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests)
    • pytest不是python内置库,需要单独安装

    1.1.3 unittest与pytest对比

    • unittest提供了test cases、test suites、test fixtures、test runner相关的类,让测试更加明确、方便、可控。使用unittest编写用例,必须遵守以下规则:

    (1)测试文件必须先import unittest
    (2)测试类必须继承unittest.TestCase
    (3)测试方法必须以“test_”开头
    (4)测试类必须要有unittest.main()方法

    • pytest是python的第三方测试框架,是基于unittest的扩展框架,比unittest更简洁,更高效。使用pytest编写用例,必须遵守以下规则:

    (1)测试文件名必须以“test_”开头或者"test"结尾(如:test_ab.py)
    (2)测试方法必须以“test
    ”开头。
    (3)测试类命名以"Test"开头。

    • unittest提供了setUp/tearDown,只能针对所有用例。
    • pytest提供了模块级、函数级、类级、方法级的setup/teardown,比unittest的setUp/tearDown更灵活。

    模块级(setup_module/teardown_module)开始于模块始末,全局的
    函数级(setup_function/teardown_function)只对函数用例生效(不在类中)
    类级(setup_class/teardown_class)只在类中前后运行一次(在类中)
    方法级(setup_method/teardown_method)开始于方法始末(在类中)
    类里面的(setup/teardown)运行在调用方法的前后

    • pytest还可以在函数前加@pytest.fixture()装饰器,在测试用例中装在fixture函数。fixture的使用范围可以是function,module,class,session。
    • fixture相对于setup和teardown来说有以下几点优势:

    (1)命名方式灵活,不局限于setup和teardown这几个命名
    (2)conftest.py 配置里可以实现数据共享,不需要import就能自动找到一些配置,可供多个py文件调用。
    (3)scope="module" 可以实现多个.py跨文件共享前置
    (4)scope="session" 以实现多个.py跨文件使用一个session来完成多个用例
    (5)用yield来唤醒teardown的执行

    • 断言方面:
      unittest提供了assertEqual、assertIn、assertTrue、assertFalse.
      pytest直接使用assert 表达式,相对而言更简单且高效.

    • unittest不支持失败重跑,pytest支持

    • unittest依赖ddt库参数化,pytest直接使用@pytest.mark.parametrize装饰器

    pytest总的来说优于unittest,提供了更多的功能和可拓展性

    1.2 Java

    Java常见单元测试框架包括Junit、testNG

    1.3 C#

    C#常见单元测试框架包括NUnit

    2. Web自动化测试框架

    2.1 Selenium

    Selenium是一个用于Web应用程序测试的工具。支持的浏览器包括IE、Mozilla Firefox、Mozilla Suite等。这个工具的主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。Selenium 是一套完整的web应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium Remote Control)和测试的并行处理(Selenium Grid)。Selenium的核心Selenium Core基于JsUnit,完全由JavaScript编写,因此可以用于任何支持JavaScript的浏览器上。Selenium可以模拟真实浏览器,自动化测试工具,支持多种浏览器,爬虫中主要用来解决JavaScript渲染问题。

    selenium 1.0 包括以下两部分:selenium server、 Client Libraries组成

    2.1.1 selenium server

    selenium server负责控制浏览器的行为。主要有launcher,Http Proxy,selenium core。selenium core使用Selenium Server嵌入到浏览器页面中。实质上,selenium core是由JS函数组成,这样我们可以实现用程序对浏览器进行操作。

    2.1.2 client Libraries

    编写测试用例时控制selenium server的库

    下图介绍了testcase的执行过程:

     

    执行过程

    (1).测试案例(Testcase)通过Client Lib的接口向Selenium Server发送Http请求,要求和Selenium Server建立连接。

    为什么要通过发送Http请求控制Selenium Server而不采用其他方式呢?从上文可以看出,Selenium Server是一个独立的中间服务器(确切地说是代理服务器),它可以架设在其他机器上!所以测试案例通过发送HTTP请求去控制Selenium Server是很正常的。

    (2).Selenium Server的Launcher启动浏览器,把Selenium Core加载入浏览器页面当中,并把浏览器的代理设置为Selenium Server的Http Proxy。

    (3).测试案例通过Client Lib的接口向Selenium Server发送Http请求,Selenium Server对请求进行解析,然后通过Http Proxy发送JS命令通知Selenium Core执行操作浏览器的动作。

    (4).Selenium Core接收到指令后,执行操作。

    (5).浏览器收到新的页面请求信息(因为在(4)中,Selenium Core的操作可能引发新的页面请求),于是发送Http请求,请求新的<u style="box-sizing: border-box; font-family: __SYMBOL, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", SimSun, sans-serif; font-variant-ligatures: none; font-variant-numeric: tabular-nums; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Web</u>页面。

    由于Selenium Server在启动浏览器时做了手脚,所以Selenium Server会接收到所有由它启动的浏览器发送的请求。

    (6).Selenium Server接收到浏览器的发送的Http请求后,自己重组Http请求,获取对应的Web页面。

    (7).Selenium Server的Http Proxy把接收的Web页面返回给浏览器。

    2.2 Selenium2(Webdriver)

    Selenium 2将浏览器原生的API封装成WebDriver API,可以直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件,配置证书之类的),所以就像真正的用户在操作一样。

    下图介绍了Selenium2的架构:

     

    Selenium2架构

    • webdriver按照server–client的经典设计模式设计

    • server端就是remote server,可以是任意的浏览器:我们的脚本启动浏览器后,该浏览器就是remote server,它的职责就是等待client发送请求并做出相应;

    • client端简单说来就是我们的测试代码:们测试代码中的一些行为,比如打开浏览器,转跳到特定的url等操作是以http请求的方式发送给被server端(也就是被测浏览器)server接受请求,并执行相应操作,并在response中返回执行状态、返回值等信息;

    • the WebDriver Wire Protocol是Selenium自己设计定义的协议,这套协议非常之强大,几乎可以操作浏览器做任何事情,包括打开、关闭、最大化、最小化、元素定位、元素点击、上传文件等。

    • WebDriver Wire协议是通用的,也就是说不管FirefoxDriver还是ChromeDriver,启动之后都会在某一个端口启动基于这套协议的Web Service,例如FirefoxDriver初始化成功,默认从http://localhost:7055开始,IE则是http://localhost:52432

    webdriver的工作原理:

    (1)启动浏览器后,selenium-webdriver会将目标浏览器绑定到特定的端口,启动后的浏览器则作为webdriver的remote server。

    (2)客户端(也就是测试脚本),借助ComandExecutor发送HTTP请求给sever端(通信协议:The WebDriver Wire Protocol,在HTTP request的body中,会以WebDriver Wire协议规定的JSON格式的字符串来告诉Selenium我们希望浏览器接下来做什么事情)。

    (3)Sever端需要依赖原生的浏览器组件,转化Web Service的命令为浏览器native的调用来完成操作。

    3. iOS自动化测试框架

    3.1 XCTest

    About Testing with Xcode

    XCTest是苹果在iOS 7和Xcode5引入的一个简单而强大的测试框架,它的测试编写起来非常简单,并且遵循xUnit风格。XCTest的优点是与Xcode深度集成,有专门的Test导航栏,但因为受限于官方测试API,因此功能不是很丰富。

    3.2 UIAutomation

    https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/UIAutomation.html

    UIAutomation是苹果提供的UI自动化测试框架,使用Javascript编写。基于UIAutomation有扩展型的工具框架和驱动型的框架。扩展型框架以JavaScript扩展库方法提供了很多好用js工具,注入式的框架通常会提供一些Lib或者是Framework,要求测试人员在待测应用的代码工程中导入这些内容,框架可以通过他们完成对app的驱动。驱动型UI Automation 在自动化测试底层使用了UI Automation库,通过TCP通信的方式驱动UI Automation来完成自动化测试,通过这种方式,编辑脚本的语言不再局限于JavaScript。

    3.3 Frank

    App Development Ireland - App Developers Dublin

    Frank是iOS平台一款非常受欢迎的app测试框架,它使用Cucumber语言来编写测试用例, Frank包含一个强大的“app inspector”–Symbiote,可以用它来获得运行中app的详细信息,便于开发者将来进行测试回顾。 它允许使用Cucumber编写结构化英语句子的测试场景。 Frank要求测试时在应用程序内部编译,这意味着对源代码的改变是强制性的。操作方式为使用Cucumber和JSON组合命令,将命令发送到在本地应用程序内部运行的服务器上,并利用UISpec运行命令。

    **优点: **测试场景是在Cucumber的帮助下,用可理解的英语句子写的。强大的Symbiote实时检查工具。 活跃的社区支持。 不断扩大中的库。

    缺点:对手势的支持有限。 在设备上运行测试有点难。 修改配置文件需要在实际设备上运行。 记录功能不可用。

    3.4 KIF

    iOS 中使用 KIF 测试 UI - OSCHINA - 中文开源技术交流社区

    KIF是Keep It Functional项目的缩写,是一款iOS app功能性测试框架,使用Objective-C语言编写,对苹果开发者来说非常容易上手,更是一款开发者广为推荐的测试工具。KIF tester使用私有API来了解App中的视图层级。但缺点是运行较慢。

    3.5 Calabash-ios

    详见Calabash-android 描述。

    3.6 Subliminal

    Subliminal

    Subliminal是另一款与XCTest集成的框架。与KIF不同的是,它基于UIAutomation编写,旨在对开发者隐藏UIAutomation中一些复杂的细节。

    3.7 Kiwi

    https://github.com/kiwi-bdd/Kiwi/wiki/Getting-Started-with-Kiwi-2.0

    Kiwi是对XCTest的一个完整替代,使用xSpec风格编写测试。 Kiwi带有自己的一套工具集,包括expectations、mocks、stubs,甚至还支持异步测试。它是一个适用于iOS 开发的Behavior Driven Development(BDD)库,优点在于其简洁的接口和可用性,易于设置和使用,非常适合新手开发者。Kiwi使用Objective-C语言编写,易于IOS开发人员上手。

    3.8 Appium

    Appium: Mobile App Automation Made Awesome.

    Appium是一个开源的、跨平台的自动化测试工具,支持IOS、Android和FirefoxOS平台。 通过Appium,开发者无需重新编译app或者做任何调整,就可以测试移动应用,可以使测试代码访问后端API和数据库。它是通过驱动苹果的UIAutomation和Android的UiAutomator框架来实现的双平台支持,同时绑定了Selenium WebDriver用于老的Android平台测试。开发者可以使用WebDriver兼容的任何语言编写测试脚本,如Java, OC, JS, PHP,Python, Ruby, C#,Clojure 和Perl语言。

    总结:IOS自动化测试框架继承关系如下. XCTest与 Xcode 的 IDE 直接集成,使用简单, 但其不支持stub和mock, 所以单使用XCTest框架的较少. Kiwi是一个iOS平台十分好用的行为驱动开发BDD的测试框架,有着非常漂亮的语法,可以写出结构性强,非常容易读懂的测试。UI Automation是Apple官方提供的UI自动化测试的解决方法,但接口不够丰富。

     

     iOS自动化测试框架

    • KIF、Frank、Calabash都是通过使用代码的形式来模拟事件触发,使得被测代码就像是由用户行为所触发的一样。但这样的代价是插入一个额外层的复杂度。

    • IOS测试框架中支持BDD的有calabash 和Kiwi。

    • 可选用的单元测试框架有Kiwi,Specta,Quick等,而KIF,Subliminal和calabash更适用于UI级验收测试。

    4. Android自动化测试框架

    4.1 Instrumentation

    https://developer.android.com/reference/android/app/Instrumentation.html

    Instrumentaion 是Android自带的一个测试框架,是很多其它测试框架的基础,可以在同进程中加载被测组件。它有很多丰富的高层封装,使用者可以使用基于instrumentation的其他框架,避免过多二次开发量。但Instrumentation不支持跨应用,导致基于instrumentation的框架都继承了这个缺点。

    4.2 Robotium

    https://github.com/robotiumtech/robotium

    Robotium是基于Instrumentation框架开发的一个更强的框架. 对常用的操作进行了易用性的封装. 用于开发功能性、系统和验收测试场景。它运行时绑定到GUI组件。它安装了一个测试用例套件作为在Android设备或仿真器上的应用程序,并提供用于执行测试的真实环境。

    优点: 容易在最短的时间内编写测试脚本,易用性高。自动跟随当前activity。 由于运行时绑定到GUI组件,所以相比Appium,它的测试执行更快,更强大。 不访问代码或不了解app实现,也可以工作。 支持Activities、Dialogs、Toasts、Menus、Context Menus和其他Android SDK控件。

    缺点: 不能处理flash和web组件。在旧设备上会变得很慢。 由于不支持iOS设备,当自动化测试同时覆盖 android与iOS的情况时,测试会被中断。没有内置的记录和回放功能.,使用记录功能需要 TestDroid 和 Robotium Recorder 这样的收费工具。

    4.3 UIAutomator

    https://google.github.io/android-testing-support-library/docs/uiautomator/

    UIAutomator是由谷歌提供的测试框架,它提供了原生Android app和游戏的高级UI测试。这是一个包含API的Java库,用来创建功能性UI测试,还有运行测试的执行引擎。该库自带Android SDK。

    优点:它在运行访问不同的进程时,会给JUnit测试案例特权。库由谷歌社区支持和维护。

    缺点:仅支持android4.1(API level 16)及以上。 不支持脚本记录。 支持的重点是Java。 你不能获得当前活动或仪表化。目前不支持web视图。 库仅支持使用Java,因此很难和使用Ruby的cucumber混合。如想支持BDD框架,建议使用Java自己的BDD框架,例如Jbehave。

    4.4 Espresso

    https://google.github.io/android-testing-support-library/docs/espresso/index.html

    Espresso是Google的开源自动化测试框架。相对于Robotium和UIAutomator,它的特点是规模更小、更简洁、API更加精确、编写测试代码简单、容易快速上手。因为是基于Instrumentation的,所以不能跨App。

    4.5 Calabash

    https://github.com/calabash

    Calabash是一个适用于iOS和Android开发者的跨平台app测试框架,可用来测试屏幕截图、手势和实际功能代码。Calabash开源免费并支持Cucumber语言,Cucumber能让你用自然的英语语言表述app的行为,实现BDD(Behavior Driven Development,行为驱动开发)。 Cucumber中的所有语句使用Ruby定义。

    **优点: **有大型社区支持。列表项 简单,类似英语表述的测试语句支持在屏幕上的所有动作,如滑动,缩放,旋转,敲击等。 跨平台开发支持(同样的代码在Android和iOS设备中都适用)。

    缺点:测试步骤失败后,将跳过所有的后续步骤,这可能会导致错过更严重的产品问题。测试耗费时间,因为它总是默认先安装app。 需要Calabash框架安装在ios的ipa文件中, 因此测试人员必须要有iOS的app源码。 除了Ruby,对其他语言不友好。

    4.6 Appium

    Appium: Mobile App Automation Made Awesome.

    Appium是一个开源的、跨平台的自动化测试工具,支持IOS、Android和FirefoxOS平台。 通过Appium,开发者无需重新编译app或者做任何调整,就可以测试移动应用,可以使测试代码访问后端API和数据库。它是通过驱动苹果的UIAutomation和Android的UiAutomator框架来实现的双平台支持,同时绑定了Selenium WebDriver用于老的Android平台测试。开发者可以使用WebDriver兼容的任何语言编写测试脚本,如Java, OC, JS, PHP,Python, Ruby, C#,Clojure 和Perl语言。

    4.7 Selendroid

    GitBook - Where software teams break knowledge silos.

    Selendroid 是一个基于Instrumentation的一个框架. 完全兼容Webdriver协议。 Selendroid 可以在模拟器和实际设备上使用,也可以集成网格节点作为缩放和并行测试。

    4.8 Robolectric

    Robolectric

    Robolectric 是一款Android单元测试框架,但它并不依赖于Android提供的测试功能,它通过实现一套JVM能运行的Android代码,然后在unit test运行的时候去截取android相关的代码调用,然后转到Robolectric实现的代码(shadow objects)去执行这个调用的过程。因此它不像模拟器或设备需要dexing(Android dex编译器将类文件编译成Android设备上的Dalvik VM使用的格式)、打包、部署和运行的过程,大大减少了测试执行的时间。Pivotal实验室声称使用Robolectric可以在28秒内运行1047个测试。

    除了实现Android里面的类的现有接口,Robolectric还给每个Shadow类额外增加了很多接口,可以读取对应的Android类的一些状态。比如它为ImageView提供了getImageResourceId()方法,测试者可以通过getImageResourceId()接口来确定是不是正确显示了期望的Image。

    4.9 RoboSpock

    http://robospock.org/

    RoboSpock是一个开源的Android测试框架,它提供了简单的编写BDD行为驱动开发规范的方法,使用Groovy语言,支持Google Guice库。RoboSpock合并了Robolectic和Spock的功能。

    4.10 Cafe

    项目管理iCafe_项目进度管理-百度智能云

    Cafe是百度出品的一个基于Robotium的测试框架,它提供了跨进程的测试解决方案。

    4.11 Athrun

    http://code.taobao.org/p/athrun/wiki/index/

    Athrun 是taobao出的一个移动测试框架,它支持Android和IOS。Android部分是基于Instrumentation,在Android原有的ActivityInstrumentationTestCase2类基础上进行了扩展,提供了一整套面向对象的API。 IOS上的自动化测试包括注入式自动化框架AppFramework,和基于录制的自动化框架Athrun_IOS, InstrumentDriver。

    4.12 其他

    其他自动化框架还有应用于稳定性测试的Monkey系列(Monkey, Monkeyrunner, MonkeyTalk), 其中MonkeyTalk 支持iOS 和 Android,它可以为应用进行真实的,功能性交互测试。MonkeyTalk 提供简单的 “smoke tests”,复杂数据驱动的测试套件。MonkeyTalk 支持原生,移动和混合应用,真实设备或者模拟器。MonkeyTalk 使得场景捕获非常容易,可以记录高级别,可读的测试脚本。还有适用于浏览器自动测试的Selenium WebDriver,可以真实测试用户行为,用户交互如触摸、手指滚动、长按等,还支持HTML5的一些特性,比如本地存储、session存储、应用缓存等。而CTS则是应用于兼容性测试的自动化工具, CTS大部分是基于Junit和仪表盘技术编写的。还扩展了自动化测试过程,可以自动执行用例,自动收集和汇总测试结果。CTS采用XML配置文件的方式将这些测试用例分组成多个测试计划(plan),第三方也可以创建自己的plan。

    总结:

    各个测试框架的继承关系如下,继承关系决定了有些框架的先天优势或先天不足. 在实际应用中可以集成多个框架。

     

     Android 自动化测试框架

    • 基于Instrumentation的测试框架,比如Espresso,Robotium,Selendroid等,都不能支持跨APP使用。 如自动化测试中有跨APP操作,可以结合UiAutomator实现。

    • 支持BDD的自动化框架比较少,可以在calabash 和 RoboSpock及Jbehave之间选择。

    • 若想同时支持Android和IOS,可选框架有Appium和Calabash,或AthRun。

    • 若为单元测试选择框架,可选Instrumentation或Robolectric。Robolectric实现了shadow object 类,耗时短。

    感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接免费拿走:

    ① 2000多本软件测试电子书(主流和经典的书籍应该都有了)

    ② 软件测试/自动化测试标准库资料(最全中文版)

    ③ 项目源码(四五十个有趣且经典的练手项目及源码)

    ④ Python编程语言、API接口自动化测试、web自动化测试、App自动化测试(适合小白学习)


    ⑤ Python学习路线图(告别不入流的学习)

    上图的资料 在我的QQ技术交流群里(技术交流和资源共享,广告进来腿给你打断)

    可以自助拿走,群号953306497(备注“csdn111”)群里的免费资料都是笔者十多年测试生涯的精华。还有同行大神一起交流技术哦。

    展开全文
  • UI 自动化框架对比2

    千次阅读 2021-10-26 13:26:32
    1、pytest 在开始本文之前,我想跟大家澄清两个概念,一个是测试框架一个是测试...好的测试框架应该具有很高的扩展性,支持二次开发,并能够支持多种类型的自动化测试。 测试工具的作用是为了完成某一类型的测试,.
  • 自动化框架到底是什么?

    千次阅读 2020-09-30 21:16:46
    微型,小型和中型企业(SME)使其测试过程自动化变得越来越必要,但是最关键的方面是选择正确的测试自动化框架。网上各式各样的介绍是否让你眼花缭乱?接下来,让我从实践出发,介绍一下什么是自动化测试框架。 ...
  • 俗话说 “没有最好的,只有最合适的”,今天我们就Python当前使用较为频繁的4大主流自动化测试框架, 来一回比拼,从中挑选最为合适你当前项目需求的那一款。 Robot Framework Unittest Nose2 ...
  • 一、前言 上一章节我们实现了用户模块的增删改查接口,现在有了接口了就需要开始开发前端页面...这一章节将通过react(Web开发框架)+antd(UI组件库)+ts(Javascript的超集)的技术栈来搭建我们的前端项目。 ......
  • 自动化测试框架有什么作用?

    千次阅读 2022-04-02 16:16:34
    在自动化测试中使用框架是很常见的,除了手动干预外,一般来说使用自动化框架有着以下几种优点。 1.更快的上市时间:通过允许测试用例的持续执行,使用一个好的测试自动化框架有助于减少应用程序的上市时间。一旦...
  • 搭建的自动化测试框架要包括API测试,UI测试,APP测试三类。以上三类其实可以简化为两类,那就是:
  • 后面所谈到的 测试自动化 也将围绕着 接口自动化 来介绍。 本系列选择的测试语言是 python 脚本语言。由于其官方文档已经对原理有了比较清楚的解释,本文就不做一些多余的翻译工作了。偏向于实战部分,而且为了偏向...
  • 5种比较常见的自动化测试框架

    千次阅读 2020-10-26 14:34:43
    自动化测试框架
  • Python Pytest 自动化测试框架搭建

    千次阅读 2022-01-04 17:20:15
    casefiletemplate.py 用于根据 params 文件夹下的测试数据文件自动生成.py 的测试用例 consts.py 定义发送报告用的全局变量 email.py 封装的发送 email 报告功能 get_casedate.py 读取 params 文件夹下的测试数据...
  • 自动化测试】自动化测试框架与工具

    万次阅读 多人点赞 2021-05-06 21:01:01
    文章目录1)什么是自动化测试框架?...1.4 判断是否需要自动化测试适用项目:2)自动化测试框架的类型2.1 自动化测试框架的分类2.1.1 基于模块的测试框架:2.1.2 库架构测试框架2.1.3 数据驱动测试框架2.1.4 关键字驱动
  • Android 自动化测试框架简介

    千次阅读 2020-11-18 20:39:38
    Android常用的自动化测试工具框架: Monkey,MonkeyRunner,UIAutomator,Robotium,Appium,Monkey Talk...... 但这些工具框架都是什么呢有什么联系呢,先通过一张图来了解一下吧 是不是一脸懵逼,不知道这...
  • 分享我的第一次Selenium自动化测试框架开发过程

    万次阅读 多人点赞 2017-08-19 14:08:40
    由于公司的开发团队偏向于使用Java技术,而且公司倡导学习开源技术,所以我选择用Java语言来进行Selenium WebDriver的自动化框架开发。由于本人没有Java开发经验,以前虽然学过QTP但从没有接触过Selenium,正好通过...
  • 每一个测试人员都应该了解每种框架的优缺点,以帮助你的团队更好地确定最适合的测试的框架,以达到事半功倍。
  • Robot Framework是一个基于Python的可扩展关键字驱动的自动化框架,用于验收测试,验收测试驱动开发(ATDD),行为驱动开发(BDD)和机器人流程自动化(RPA)。它可以用于分布式异构环境,其中自动化需要使用不同的...
  • pytest接口自动化测试框架搭建

    千次阅读 2022-01-26 16:10:40
    Pytest目前已经成为Python系自动化测试必学必备的一个框架,最近抽时间梳理了一份pytest接口自动化测试框架,尽量简单通俗易懂。如果能够对新学习这个框架的同学起到一些帮助,那就更好了~
  • 5大自动化测试的 Python 框架

    千次阅读 2020-09-14 16:49:53
    随着该编程语言的广泛使用,基于Python的自动化测试框架也应运而生,且不断发展与丰富。 因此,开发与测试人员在为手头的项目选择测试框架时,需要考虑许多方面的因素,其中包括:框架的脚本质量,测试用例的简单性...
  • 框架为用户提供了各种优势,帮助他们有效地开发、执行和报告自动化测试脚本。它更像是一个专门为自动化组织的测试而创建的系统。简而言之,我们可以说框架是各种指导方针、编码标准、概念、过程、实践、项目层次、...
  • 今日内容:接口自动化测试框架必会之pytest插件,运行规则以及参数,pytest.ini配置文 件,跳过用例,用例执行顺序,夹具等
  • 基于appium的app自动化测试框架

    千次阅读 2021-12-15 21:19:26
    App自动化测试主要难点在于环境的搭建,appium完全是基于selenium进行的扩展,所以app测试框架也是基于web测试框架开发的 一、设备连接 (即构建基础的测试环境,保证可以驱动设备进行操作) 0.准备测试环境 1)安装...
  • 五种常见的自动化测试框架

    千次阅读 2021-10-09 16:57:06
    一、什么是测试自动化框架 自动化测试框架就是用于测试自动化的框架。具体来说,它提供了自动化测试用例编写、自动化测试用例执行、自动化测试报告生成等基础功能。我们只需要基于这个框架,完成和业务高度相关的...
  • Robot Framework自动化测试框架

    千次阅读 2022-02-18 22:29:26
    它是一个基于Python语言开发的,可扩展的,是以关键字驱动模式的自动化测试测试框架。也是一个跨平台的通用的,与应用程序和技术无关的测试框架。它有一个高度模块化的架构: 数据层、测试框架、测试库或第三方...
  • 浅谈python+requests接口自动化框架

    千次阅读 2022-02-26 21:39:21
    为什么要做接口自动化框架 1、业务与配置的分离 2、数据与程序的分离;数据的变更不影响程序 3、有日志功能,实现无人值守 4、自动发送测试报告 5、不懂编程的测试人员也可以进行测试 正常接口测试的流程是...
  • 不同框架接口自动化的优劣

    千次阅读 2022-03-21 20:31:55
    5、框架设计能力与实际适用场景匹配难度大 优点: 1、灵活性,支持单场景/多场景,特别适合微服务架构下的系统测试 2、支持jenkins持续集成 自动化测试平台 缺点: 1、工具平台开发人力投入成本大 2、自研平台稳定...
  • 几种典型的软件自动化测试框架

    千次阅读 2020-09-22 15:30:24
    因此,如何选择一个合适的测试自动化框架,是一个自动化测试小组开始启动前需要最优先考虑的一个问题。 一个自动化测试框架就是一个由假设、概念以及为自动化测试提供支持的实践的集合。以下描述五种基本的自动测试...
  • Selenium自动化测试框架

    千次阅读 2021-10-15 16:41:31
    1.什么是框架框架(framework)是一个框子——指其约束性,也是一个架子——指其支撑性。是一个基本概念上的结构,用于去解决或者处理复杂的问题。 框架是整个或部分系统的可重用设计,表现为一组抽象构件及构件...
  • 好用的安卓自动化测试框架Espresso

    千次阅读 2022-04-06 14:28:36
     Android自动化测试是应用开发中提升开发效率的一种方式,它可以在短时间内跑完所有的测试方案以及实现各种交互,从而让开发者更加方便和直观的知道代码的实现效果。  Android自动化测试可以分为单元测试、UI测试...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 639,919
精华内容 255,967
关键字:

自动化框架开发