精华内容
下载资源
问答
  • 自动化测试之验证码处理

    千次阅读 2020-01-29 20:44:52
    自动化测试过程中,经常会遇见有验证码的场景,例如:用户登录,用户支付,用户注册,用户重置密码,身份确认等场景。 验证码主要分为以下几种: 1.图文验证码(普通验证码) 基本由数字,中文,英文等组合而成...

    在自动化测试过程中,经常会遇见有验证码的场景,例如:用户登录,用户支付,用户注册,用户重置密码,身份确认等场景。

    验证码主要分为以下几种:

    1.图文验证码(普通验证码)

    基本由数字,中文,英文等组合而成,用户在文本框中输入验证码进行校验。如下图:

    2. 短信验证码

    输入手机号,点击获取验证码,将手机上获取到的验证码输入到文本款中进行验证。如下图:

    3.滑动验证码

    根据提示绘图或者拖动图片完成拼图

    或者:

    4.识物点击验证码

    根据目标(电饭锅)选中图中相关的物体

    自动化测试遇到验证码,处理过程:

    1.第一种处理办法:修改代码,直接绕过去,取消前后端代码对验证码的校验

       适用于场景:主要是 测试需求功能 是否正确,这里暂时对验证码需要不高,可屏蔽。这几种验证码都可以采用这个办法

    2.第二种处理方法:万能验证码

       适用于场景:主要是 测试需求功能 是否正确,这里暂时对验证码需要不高。相较于第一种而言,不需要隐藏代码,只需要在测试环境中对于所有使用验证码的地方给与通过:图文验证码和短信验证码可设定一个万能验证码,其他两种行为验证码返回true。这几种验证码都可以采用这个办法

    3.第三种处理办法:sleep.time(等待时间),设置等待时间,测试人员手动完成验证码校验。这几种场景都可以使用。优点:不需要修改代码也不需要屏蔽任何代码,同时可以进行验证码与功能联合起来的测试。缺点:不是完全的自动化,需要人为干预。主要用于初期脚本调试或者初期时间紧张查看验证码和功能是否完美衔接。

    4.第四种处理办法:保存验证码(数据库或者文件),主要用于图文验证码和手机短信验证码。以手机验证码为例进行原理说明:程序生成5位随机数,一方面调用短信接口,将随机数发送到用户手机上,一方面将随机数存入数据库。用户在前端输入验证码之后与数据库的验证码进行对比,相同则验证码通过,否则验证码验证失败。自动化测试可以从数据库读取验证码进行前端验证码元素send_keys来进行验证码的验证。好处:自动化测试完美模拟用户的操作过程。

    5.第五种处理方法:从内存中读取验证码(cookie或者session),部分网站会将验证码临时存储于session内存中,可以通过读取session来获取验证码,进行脚本自动化测试研发。仅适用于图文验证码和短信验证码

    6.第六种处理方法:绕过验证码。用户登陆之后保存用户的token信息,未到期之前用户再次登可直接使用token登录,这种方式绕过了验证码的校验。四种验证码都可以使用

    7.第七种处理方法:采用第三方的api接口对验证码进行识别。目前网上有很多免费的或者很便宜的验证码接口可供测试人员使用,比如易源网站。原理:我们调用易源_验证码 提供的接口进行参数传入,上面api有详细的参数说明,(特别是验证码类别这个参数,中文,英文,数字互相组合时,要传递不同的参数)识别错误返回-1,识别成功返回验证码,我们可根据return的value进行前端页面验证码元素的输入,来完成前端页面的自动化测试。目前第7中只能用于语音验证码,图文验证码。

     

     

     

    展开全文
  • 公司要求招一名自动化测试,能力要求不高,1年左右自动化经验+部分性能经验即可,让我出一份题,我就百度+公司项目遇到的问题,出了一份,出题整体思路是:接口自动化问题+性能问题+规划的ui、app自动化+整体质量...

    写在前面

    公司要求招一名自动化测试,能力要求不高,1年左右自动化经验+部分性能经验即可,让我出一份题,我就百度+公司项目遇到的问题,出了一份,出题整体思路是:接口自动化问题+性能问题+规划的ui、app自动化+整体质量体系建设等多方面考虑。下面是正题

    岗位JD

    在这里插入图片描述
    | 1、【技术能力】能独立完成产品线中自动化测试工作,根据测试任务,搭建软件测试环境,编写测试脚本,输出报告;
    2、【项目管理】熟练开发测试工具、测试脚本,及迭代优化测试框架,使用合理方式进行自动化管理项目;
    3、【业务推动】对测试项目的结果负责,使用合理方式推动业务端测试的效率、开发质量;
    4、【规范制定】 熟悉CI系统,完善准入/准出标准,持续提升测试效率;
    5、【效率提升】根据业务特点,引入新的测试方法和工具,探索新技术。改进测试工具或测试方法,提高效率,培训测试人员并支持技术难题解决 | |

    |-1)3年以上测试工作经验,1年以上自动化测试经验或开发经验;
    2)至少熟悉一种脚本语言,如Shell、Python、java等;
    3)至少熟悉一种测试框架,unittest、pytest、testng等;可独立完成复杂逻辑的接口自动化测试;
    4)熟悉appium、selenium可独立完成android和ios的UI自动化测试;
    5)熟悉jenkins、svn、git的搭建和使用;
    6)熟悉常用性能测试工具的使用,并可进行分析调优:ab、jmeter、loadrunner、locust等,有分布式压测经验优先;
    7)熟悉使用django开发框架,可完成web页面和功能的开发(此条可放宽);
    8)具备丰富的系统测试经验,并且能够进行系统级的原因定位与分析;
    9)具备较强的计划、组织、协调、沟通及分析能力,优秀的职业素养和团队协作精神、敬业精神,能承受工作压力;
    10)学习能力强,对技术有着特别的渴求,在关注的领域有着深入的研究,并不断创新;具备较强的技术培训能力和领导能力-|–|

    自动化测试面试题1:基础篇

    目的:验证求职者是否在自动化测试岗位有实际应用于生产的工作经验

    1、使用什么测试框架做的上一个项目的自动化测试?说下怎么做的?对自动化的理解?
    答:(junit、unittest、testng、 pytest ,优先python语言,用过pytest或unittest框架的;只会selenium能力较弱)
    2、使用什么测试框架做的上一个项目的自动化测试?说下怎么做的?对自动化的理解?
    答:最好能答出独立负责且封装页面元素、断言封装、请求封装、取参方式具体实现
    3、GET与POST的区别?
    (1)GET请求资源数据,POST向服务器传递需要处理的数据
    (2)GET传递数据大小不超过2kb,POST没有限制
    (3)GET请求的参数会在Url上暴露显示,POST请求参数在Requestbody里,所以相对GET来说,POST安全性较高
    (4)GET 请求的静态资源会被浏览器缓存,POST不会被缓存
    (5)GET传递的数据类型是文本,POST是文本或者二进制
    (6)GET请求被回退时是无害的,POST请求被回退是会被重新再执行一次
    GET和POST的使用场景:
    (1)在传递一些机密信息时必须要使用POST
    (2)只是查询获取数据时可以用GET
    (3)POST请求速率会比GET慢,因为GET请求产生一个TCP数据包;POST请求产生两个TCP数据包
    4、//*[contains(@text,“登录”)] 是什么意思?
    答:查包含登录关键字的所有元素
    5、自动化遇到用例fail掉如何排查故障?
    答:看出错log,如果能按层次说清楚排查失败:手工查应用是否真的有bug, 确认不是bug,是不是新版本引入了新的变更,调试脚本看看自己的脚本是不是因为没有等待元素出现后就操作了,是不是元素上面有其他元素出现这样操作是不是操作了其他的元素上了
    6、说说接口测试的流程和接口自动化流程,介绍一下request有哪些内容?
    答:(1)流程:获取接口文档,依据文档设计接口参数,获取响应,解析响应,校验结果,判断测试是否通过。 (2)request 内容:1,封装了get、post等;
    2、以关键字参数的方式,封装了各类请求参数,params、data、headers、token、cookie等;3,封装了响应内容,status_code、json()、cookies、url等;
    session会话对象,可以跨请求;
    7、接口测试用例的编写要点有哪些?
    1)必填字段:请求参数必填项、可选项
    2)合法性:输入输出合法、非法参数
    3)边界:请求参数边界值等
    4)容错能力:大容量数据、频繁请求、重复请求(如:订单)、异常网络等的处理
    5)响应数据校验:断言、数据提取传递到下一级接口…
    6)逻辑校验:如两个请求的接口有严格的先后顺序,需要测试调转顺序的情况
    7)性能:对接口模拟并发测试,逐步加压,分析瓶颈点
    8)安全性:构造恶意的字符请求,如:SQL注入、XSS、敏感信息、业务逻辑(如:跳过某些关键步骤;未经验证操纵敏感数据)
    8,postman的使用方式?高级用法?mock的应用场景和基础用法?
    答:A,基础使用:入参出参校验返回;
    b,Environment–配置不同的环境参数,Globals即设置全局变量,Pre-request Script–配置使用环境变量或进行前置脚本处理;
    c,团队可以更好地并行工作,前后端人员只需要定义好接口文档就可以开始并行工作,互不影响,只在最后的联调阶段往来密切,开启TDD(Test-Driven Development)模式,即测试驱动开发;
    9,你之前自动化测试的数据放哪?怎么使用?公共变量的管理方式?管理测试用例的手段?如何提高用例覆盖率?接口测试关联性接口实现方式?
    答:测试数据存放总结:
    1.对于账号密码,这种管全局的参数,可以用命令行参数,单独抽出来,写的配置文件里(如ini)
    2.对于一些一次性消耗的数据,比如注册,每次注册不一样的数,可以用随机函数生成
    3.对于一个接口有多组测试的参数,可以参数化,数据放yaml,text,json,excel都可以
    4.对于可以反复使用的数据,比如订单的各种状态需要造数据的情况,可以放到数据库,每次数据初始化,用完后再清理
    5.对于邮箱配置的一些参数,可以用ini配置文件
    6.对于全部是独立的接口项目,可以用数据驱动方式,用excel/csv管理测试的接口数据
    7.对于少量的静态数据,比如一个接口的测试数据,也就2-3组,可以写到py脚本的开头,十年八年都不会变更的。
    10,不可逆的操作,如何处理,比如删除一个订单这种接口如何测试?
    此题考的是造数据的能力,接口的请求数据,很多都是需要依赖前面一个状态的
    比如工作流这种,流向不同的人状态不一样,操作权限不一样,测试的时候,每种状态都要测到,就需要自己会造数据了。
    平常手工测试造数据,直接在数据库改字段状态。那么自动化也是一样,造数据可以用python连数据库了,做增删改查的操作
    测试用例前置操作,setUp做数据准备
    后置操作,tearDown做数据清理
    11、、说出5个以上 Linux 命令(注重考察性能测试监控常用命令?)
    答:cd、ls、grep、mkdir、pwd、ping等等,重要是性能测试常用监控命令:netstat 、top 、Nmon 、dstat、ulimit、vmstat 、tcpdump、free 、lsof ,需回答上至少两个。
    12、介绍一下你在这个项目中是如何使用 Jenkins 的。
    答:基本操作,比如定时构建执行代码等。
    13、举例说明,Linux下命令行cURL的种常见用法和示例?
    答:常用10种,这里举出三种常用:A,获取页面内容:curl+get请求;curl https://www.baidu.com
    B,把链接页面的内容输出到本地文件中:curl https://www.baidu.com > index.html
    C,使用 -d 发送 POST 请求:curl -d “userName=tom&passwd=123456” http://www.example.com/login
    14,jmeter上一个接口参数返回值做为下一个接口入参的实现方式有几种,举例?
    答:正则表达式处理器、JSON Path Extractor
    15、接口自动化中,遇到签名、鉴权加密等,如何处理的,用到哪些方法?
    答:比如MD5加密–hashlib内置库,看怎么回答怎么具体问:开放性。
    16、对pytest的理解程度?使用规范?参数化方法?说说常用装饰器?
    答:pytest是一个非常成熟的全功能的的Python测试框架,主要特点有以下几点:
    1,简单灵活,容易上手,文档丰富;
    2,支持参数化,可以细粒度地控制要测试的测试用例;
    3,能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/ appnium等自动化测试,接口自动化测试(pytest +请求);
    4,pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如pytest - selenium(集成selenium),pytest-HTML(完美的HTML测试报告生成),pytest-rerunfailures(失败情况下重复执行),pytest -xdist(多CPU分发)等;
    5,测试用例的跳跃和xfail处理;
    使用规范:
    测试文件名必须以“test_”开头
    测试类以Test开头,并且不能带有 init 方法
    测试方法必须以“test_”开头
    除了有setup/teardown,还能更自由的定义fixture装载测试用例
    参数化方法:
    pytest支持在多个完整测试参数化方法:
    pytest.fixture(): 在fixture级别的function处参数化
    @pytest.mark.parametrize:允许在function或class级别的参数化,为特定的测试函数或类提供了多个argument/fixture设置。
    pytest_generate_tests:可以实现自己的自定义动态参数化方案或扩展。
    17、举例说明pytest.mark标记的使用?
    答:1,无条件跳过测试pytest.mark.skip
    2,有条件跳过测试pytest.mark.skipif
    3,标记测试功能按预期失败pytest.mark.xfail
    4,将测试功能标记为使用给定的夹具名称pytest.mark.usefixtures
    5,向特定测试项添加警告过滤器,以便更好地控制应在测试,类甚至模块级别捕获哪些警告@pytest.mark.filterwarnings
    6,自定义标记:标记指定标签
    18,自动化测试报告生成方式?如果是allure详述?
    答:@allure.severity(“critical”) # 优先级,包含blocker, critical, normal, minor, trivial 几个不同的等级
    @allure.feature(“测试模块_demo1”) # 功能块,feature功能分块时比story大,即同时存在feature和story时,feature为父节点
    @allure.story(“测试模块_demo2”) # 功能块,具有相同feature或story的用例将规整到相同模块下,执行时可用于筛选
    @allure.issue(“BUG号:123”) # 问题表识,关联标识已有的问题,可为一个url链接地址
    @allure.testcase(“用例名:测试字符串相等”) # 用例标识,关联标识用例,可为一个url链接地址

    19、什么是冒泡排序,手写一个冒泡排序?
    答:冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

    自动化测试面试题2:细节篇之语言:python基础

    目的:验证求职者自动化岗位的开发、脚本语言的基础以及熟悉程度

    1、super 是干嘛用的?在 Python2 和 Python3 使用,有什么区别?为什么要使用 super?请举例说明。
    答:super 用于继承父类的方法、属性。super 是新式类中才有的,所以 Python2 中使用时,要在类名的参数中写 Object。Python3 默认是新式类,不用写,直接可用。使用 super 可以提高代码的复用性、可维护性。修改代码时,只需修改一处。
    2、L = [1, 2, 3, 11, 2, 5, 3, 2, 5, 3],用一行代码得出 [11, 1, 2, 3, 5]
    答:list(set(L))
    3、列表和字典有什么区别?
    答:一般都是问列表和元组有什么不同。 (1)获取元素的方式不同。列表通过索引值获取,字典通过键获取。 (2)数据结构和算法不同。字典是 hash 算法,搜索的速度特别快。 (3)占用的内存不同。
    4,json和字典dict的区别?
    答:json是一种轻量级的数据交换格式
    dict是python中的数据类型(python里面的基础数据类型有:int、str、 float、list、bool、tuple、dict、set这几种类型,里面没json这种数据类型,json本质上字符串,按照key:value键值对格式的字符串;在json中空值是用Null表示,在dict中空值是用None表示)
    主要区别:json的key只能是字符串,python的dict可以是任何可hash对象(hashtable type);
    json的key可以是有序、重复的;dict的key不可以重复。
    json的value只能是字符串、浮点数、布尔值或者null,或者它们构成的数组或者对象。
    json任意key存在默认值undefined,dict默认没有默认值;
    json访问方式可以是[],也可以是.,遍历方式分in、of;dict的value仅可以下标访问。
    json的字符串强制双引号,dict字符串可以单引号、双引号;
    dict可以嵌套tuple,json里只有数组。
    json:true、false、null
    python:True、False、None
    json中文必须是unicode编码,如"\u6211".
    json的类型是字符串,字典的类型是字典。
    5,python深拷贝和浅拷贝的概念和区别?
    答:浅拷贝:拷贝最外层容器
    深拷贝:拷贝的最外层容器,还拷贝容器中的元素
    对于不可变元素,使用浅拷贝
    6、python单行注释和多行注释分别用什么?
    答:单行注释用# 多行注释用""" “”"
    7,Python垃圾回收机制?
    答:1,回收计数引用为0的对象,释放其占用空间
    2、循环垃圾回收器。释放循环引用对象
    8,如何安装第三方模块?以及用过哪些第三方模块?
    答:使用官方推荐的setuptools的包管理工具,easy – install和pip、requests模块
    9、进程、线程有什么区别?什么情况下用进程?什么情况下用线程?
    答:(1)区别:
    ① 地址空间和其它资源(如打开文件):进程之间相互独立,同一进程的各线程之间共享。某进程内的线程在其它进程不可见。② 通信:进程间通信 IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。③ 调度和切换:线程上下文切换比进程上下文切换要快得多。④ 在多线程操作系统中,进程不是一个可执行的实体。(2)使用场景:同时操作一个对象的时候,比如操作的是一个全局变量,我用线程,因为全局变量是所有线程共享的。
    10,谈谈你对面向对象的理解?
    体现在三个方面: 封装、继承、多态
    继承有两种方式:
    1、将同一类的方法封装到类中
    2、将数据封装到对象中
    继承:子类拥有父类的所有方法和属性,
    好处:抽取重复代码,减少代码冗余。
    坏处:耦合性太强。
    多态:对于不同的类可以有同名的方法,同名的方法应用到不同的类可以有不同行为。

    自动化测试面试题3:细节篇之selenium

    目的:验证求职者在自动化测试岗位的selenium工具的熟悉程度

    1、selenium中如何判断元素是否存在?
    答:isElementPresent
    2、selenium中hidden或者是display = none的元素是否可以定位到?
    答:a、可以:定位是可以定位到的,但是不能操作,可以判断元素is_displayed()
    想点击的话,可以用js去掉dispalay=none的属性;b、不能:可以写JavaScript将标签中的hidden先改为0,再定位元素。两个答案都算对,说明出原因即可。
    3、selenium中如何保证操作元素的成功率?也就是说如何保证我点击的元素一定是可以点击的?
    答:添加元素智能等待时间 driver.implicitly_wait(30)
    添加强制等待时间(比如python中写 sleep)
    try 方式进行 id,name,clas,x path, css selector 不同方式进行定位,如果第一种失败可以自动尝试第二种
    4、如何提高selenium脚本的执行速度?
    答:1.少用sleep,尽量不用implicitly_wait
    2.多用显式等待方法
    3.弄个性能好的电脑具体?(看个人思路)
    5、用例在运行过程中经常会出现不稳定的情况,也就是说这次可以通过,下次就没办法通过了,如何去提升用例的稳定性?
    答:
    6、你的自动化用例的执行策略是什么?
    答:自动化测试与软件开发本质上是一样的,利用自动化测试工具,经过测试需求分析,设计出自动化测
    试用例,从而搭建自动化测试的框架,设计与编写自动化脚本,验证测试脚本的正确性,最终完成自
    动化测试测试脚本(即主要功能为测试的应用软件)并输出测试结果
    7、什么是持续集成?
    答:持续集成是一种软件开发实践,即团队开发成员经常集成它们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。
    每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。
    8、自动化测试的时候是不是需要连接数据库做数据校验?
    答:一般来说1、 UI自动化不需要(很少需要);2、接口测试会需要:从数据库层面来进行数据校验可以更方便验证系统的数据处理方面是否正确;
    9、有几种元素常用定位方式,分别是?你最偏爱哪一种,为什么?
    答:8种:id、name、class name、tag name、link text、partial link text、xpath、css selector 偏爱哪一种?答:xpath、css几乎所有的元素都可以定位到,但是它们的短处在于页面上更改了元素后位置很容易改变,且xpath语法长,定位慢,还不稳定;css语法简洁,定位快,瑕不掩瑜,所以首先使用的还是id或者name、css等。
    10、如何去定位页面上动态加载的元素?
    答:1,触发动态加载元素的事件,直至动态元素出现,进行定位
    2,WebDriverWait()方法循环去查询是否元素加载出来了
    11、如何去定位属性动态变化的元素?
    答:xpath或者css通过同级、父级、子级进行定位
    点击链接以后,selenium是否需要自动等待该页面加载完毕?
    答:需要
    12、webdriver client的原理是什么?
    答:Selenium RC的原理是当浏览器启动时,向其中注入Javascript,从而使这些JS来驱动浏览器中的AUT
    (Application Under Test),而Selenium Webdriver是通过调用浏览器原生的自动化API直接驱动浏览器
    13、什么是page object设计模式?
    答:简单来说,就是把页面作为对象,在使用中传递页面对象,来使用页面对象中相应的成员或者方法,能更好的体现面向对象语言(比如java或者python)的面向对象和封装特性。
    14、什么是断言(assert),常用断言方法,UI自动化中断言方式?
    答:断言的英文是assertion,断言检查的英文是assertion checking。
    断言是指定一个程序必须已经存在的状态的一个逻辑表达式,或者一组程序变量在程序执行期间的某个点上必须满足的条件
    UI自动化中断言方式:定位页面当前页面或跳转页面中元素唯一的一个或多个元素判断是否存在,即可。
    15、你觉得自动化测试最大的缺陷是什么?
    答:不稳定、可靠性、不易维护、成本与收益
    16、什么是分层测试?
    答:行业里面提的一般是金字塔的分层模型:UI测试、集成/接口测试、单元测试
    17、列举出你熟悉的自动化工具,并说明其实现原理
    18、高质量的自动化脚本应该具有什么特性?

    自动化测试面试题4:细节篇之性能篇

    目的:验证求职者在性能测试方面熟悉程度

    1,基础概念:HPS、TPS、QPS、RPS、RT、并发用户数概念?简要介绍?
    HPS(Hits Per Second):每秒点击次数,单位是次/秒。
    TPS(Transaction per Second):系统每秒处理事务数,简称TPS, 每秒事务数, 是衡量系统性能的一个非常重要的指标。
    QPS(Query per Second):系统每秒处理查询次数,单位是次/秒。对于互联网业务中,如果某些业务有且仅有一个请求连接,那么TPS=QPS=HPS,一般情况下用TPS来衡量整个业务流程,用QPS来衡量接口查询次数,用HPS来表示对服务器点击请求
    RPS 即每秒请求数(Request Per Second),通常用来描述施压引擎实际发出的压力大小。PS:并发数过低时可能达不到预期的 RPS,并发数过高时可能压力过大压垮服务器
    并发用户数:简称VU ,指的是现实系统中操作业务的用户,在性能测试工具中,一般称为虚拟用户数(Virutal User),注意并发用户数跟注册用户数、在线用户数有很大差别的,并发用户数一定会对服务器产生压力的,而在线用户数只是 ”挂” 在系统上,对服务器不产生压力,注册用户数一般指的是数据库中存在的用户数。
    响应时间:简称RT,指的是业务从客户端发起到客户端接受的时间。
    2,压测工具?你主要看哪些指标?
    答:jmeter:
    Label:每个 JMeter 的 element(例如 HTTP Request)都有一个 Name 属性,这里显示的就是 Name 属性的值
    #Samples:表示你这次测试中一共发出了多少个请求,如果模拟10个用户,每个用户迭代10次,那么这里显示100
    Average:平均响应时间——默认情况下是单个 Request 的平均响应时间,当使用了 Transaction Controller 时,也可以以Transaction 为单位显示平均响应时间
    Median:中位数,也就是 50% 用户的响应时间
    90% Line:90% 用户的响应时间
    Note:关于 50% 和 90% 并发用户数的含义,请参考下文
    http://www.cnblogs.com/jackei/archive/2006/11/11/557972.html
    Min:最小响应时间
    Max:最大响应时间
    Error%:本次测试中出现错误的请求的数量/请求的总数
    Throughput:吞吐量——默认情况下表示每秒完成的请求数(Request per Second),当使用了 Transaction Controller 时,也可以表示类似 LoadRunner 的 Transaction per Second 数
    KB/Sec:每秒从服务器端接收到的数据量,相当于LoadRunner中的Throughput/Sec
    3,性能测试中TPS上不去的几种原因浅析?
    TPS(Transaction Per Second):每秒事务数,指服务器在单位时间内(秒)可以处理的事务数量,一般以request/second为单位。
    a、网络带宽 在压力测试中,有时候要模拟大量的用户请求,如果单位时间内传递的数据包过大,超过了带宽的传输能力,那么就会造成网络资源竞争,间接导致服务端接收到的请求数达不到服务端的处理能力上限。
    b、连接池
    可用的连接数太少,造成请求等待。连接池一般分为服务器连接池(比如Tomcat)和数据库连接池(或者理解为最大允许连接数也行)。
    c、垃圾回收机制
    从常见的应用服务器来说,比如Tomcat,因为java的的堆栈内存是动态分配,具体的回收机制是基于算法,如果新生代的Eden和Survivor区频繁的进行Minor GC,老年代的full GC也回收较频繁,那么对TPS也是有一定影响的,因为垃圾回收其本身就会占用一定的资源。
    d、数据库配置
    高并发情况下,如果请求数据需要写入数据库,且需要写入多个表的时候,如果数据库的最大连接数不够,或者写入数据的SQL没有索引没有绑定变量,抑或没有主从分离、读写分离等,就会导致数据库事务处理过慢,影响到TPS。
    e、通信连接机制
    串行、并行、长连接、管道连接等,不同的连接情况,也间接的会对TPS造成影响。
    f、硬件资源
    包括CPU(配置、使用率等)、内存(占用率等)、磁盘(I/O、页交换等)。
    g、压力机
    比如jmeter,单机负载能力有限,如果需要模拟的用户请求数超过其负载极限,也会间接影响TPS(这个时候就需要进行分布式压测来解决其单机负载的问题)。
    h、压测脚本
    还是以jemter举个例子,之前工作中同事遇到的,进行阶梯式加压测试,最大的模拟请求数超过了设置的线程数,导致线程不足。
    提到这个原因,想表达意思是:有时候测试脚本参数配置等原因,也会影响测试结果。
    i、业务逻辑
    业务解耦度较低,较为复杂,整个事务处理线被拉长导致的问题。
    j、系统架构
    比如是否有缓存服务,缓存服务器配置,缓存命中率、缓存穿透以及缓存过期等,都会影响到测试结果。
    4,性能测试工具了解几个?压测结果区别?
    A,ab,是apache自带的压力测试工具
    B,Jmeter 基于Java的压力测试工具
    c,Locust是一个Python编写的分布式的性能测试工具
    5,性能测试策略?
    做性能测试需要一套标准化流程及测试策略。在做负载测试的时候,传统方式一般都是按照梯度施压的方式去加用户数,避免在没有预估的情况下,一次加几万个用户,导致交易失败率非常高,响应时间非常长,已经超过了使用者忍受范围内;较为适合互联网分布式架构的方式,是用TPS模式(吞吐量模式)+设置起始和目标最大量级,然后根据系统表现灵活的手工实时调速,效率更高,服务端吞吐能力的衡量一步到位。

    6,性能测试场景设置思路?
    无论并发模式还是TPS模式,场景就是一个压测模型,压测模型中有串行的事务(如添加购物车+购物车下单+付款)也有并行的接口(在不同串联链路中的压测API),最终组成一个复杂或者简单的场景。然后根据新业务上线的目标、或者日常峰值的等比例目标、或者重大业务活动的预估支撑能力去设置每个API的目标能力(TPS是一步到位的按照吞吐能力设置的,推荐TPS模式,比如前面提到的添加购物车+购物车下单+付款这种流程就是一个漏斗模型,TPS设置为逐渐变小的模型即可),当然也可以在初期的测试中更谨慎一点,将目标量级设置得整体低一点,当最终能力达到之后建议可以调整原定目标量级到120%或者150%,验证限流准入/高可用基础设施的抗压能力。目标量级即当前压测场景中这个压测API的施压上限。而起步量级可以从5%或者10%开始,过程中视业务指标数据和被压测端的整体负载临时调整。

    7,对服务器性能测试的看法?
    针对服务器端的性能,以TPS为主来衡量系统的性能,并发用户数为辅来衡量系统的性能,如果必须要用并发用户数来衡量的话,需要一个前提,那就是交易在多长时间内完成,因为在系统负载不高的情况下,将思考时间(思考时间的值等于交易响应时间)加到串联链路(场景)中,并发用户数基本可以增加一倍,因此用并发用户数来衡量系统的性能没太大的意义。同样的,如果系统间的吞吐能力差别很大,那么同样的并发下TPS差距也会很大

    8,系统的性能决定的要素?跟并发用户数的关系?
    由TPS决定,跟并发用户数没有多大关系。
    系统的最大TPS是一定的(在一个范围内),但并发用户数不一定,可以调整。
    建议性能测试的时候,不要设置过长的思考时间,以最坏的情况下对服务器施压。

    下面是我自己的群,大家一起讨论学习,现在人不多,来了就是元老哦哈哈,失效的时候联系我

    在这里插入图片描述

    展开全文
  • 接口自动化测试之接口测试基础

    万次阅读 多人点赞 2020-02-11 13:29:38
    文章目录一、分层的自动化测试1.传统自动化测试2.测试金字塔3.分层自动化测试二、接口测试基础知识1.接口的含义2.接口的分类3.接口测试3.1 接口测试的含义3.2 接口测试的意义3.2.1 为什么测试接口3.2.2 接口测试的...

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

    一、分层的自动化测试

    1.传统自动化测试

    • 基于产品 UI 层的自动化测试,它是将黑盒功能测试转化为由程序或工具执行的一种自动化测试。
      ✔     在目前的大多数研发组织当中,都存在开发与测试团队割裂(部门墙)、质量职责错配(测试主要对质量负责)的问题,在这种状态下,测试团队的一个“正常”反应就是试图在测试团队能够掌控的黑盒测试环节进行尽可能全面的覆盖,甚至是尽可能全面的 UI 自动化测试。
      ✔     这导致,一方面测试团队规模急剧膨胀;另一方面,因为 UI 是非常易变的,所以 UI 自动化测试维护成本相对较高。

    2.测试金字塔

    由敏捷大师 Mike Cohn 在他的 Succeeding with Agile 一书中首次提出。他的基本观点是:我们应该有更多低级别的单元测试,而不仅仅是通过用户界面运行高层端到端的测试。
    在这里插入图片描述

    3.分层自动化测试

    • Martin Fowler 在测试金字塔模型的基础上提出分层自动化测试的概念。在自动化测试之前加了一个“分层”的修饰,用来区别于“传统的”自动化测试。
    • 分层自动化测试倡导的是从黑盒(UI)单层到黑白盒多层的自动化测试体系,从全面黑盒自动化测试到对系统的不同层次进行自动化测试。
      在这里插入图片描述

    二、接口测试基础知识

    1.接口的含义

    • 接口也叫 API(Application Programming Interface,应用程序编程接口)
      ✔     是一组定义、程序及协议的集合
      ✔     它提供访问一组例程的能力,无需访问源码或理解内部工作机制的细节。

    2.接口的分类

    • 第一种是代码内部的接口或称程序接口
      ✔     是程序模块间的接口,代码 A 与代码 B 在组合的时候,必然需要定义一些名称以及参数、类型。
      ✔     对于程序接口的测试,一般需要使用与开发程序接口相同的编程语言,通过对类、方法和函数的调用,验证其返回结果是否正确来进行测试。
      ✔     这种测试一般划分在白盒测试中,也算是集成测试阶段,既可以由开发人员自己完成,也可以由有良好编程能力的测试人员来做。

    • 第二种接口是协议接口
      ✔     是系统与系统之间,通过网络数据的传递进行交互,这种类型的接口对底层代码做了封装,系统通过不同的协议提供接口对外提供调用。
      ✔     此类测试一般不涉及底层程序,也看不到代码,属于黑盒层面,可以通过各种手段将网络数据发送到接口从而得到接口的响应信息,达到测试的目标。
      ✔     这一类测试工作多数情况下由测试人员完成。通常所说的的接口测试主要是对协议接口的测试。

    3.接口测试

    3.1 接口测试的含义

    • 接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。
    • 测试的重点是要检查数据的交换,传递和控制管理过程以及系统间的相互逻辑依赖关系等。

    3.2 接口测试的意义

    3.2.1 为什么测试接口

    • 接口其实就是前端页面或 APP 等调用与后端做交互用的,但是功能测试都测了,为什么还要测接口呢?
      ✔     如测试用户注册功能,规定用户名为 6~18 个字符,包含字母(区分大小写)、数字、下划线。
             ★     功能测试
                     ■     对用户名规则进行测试,比如输入 20 个字符、输入特殊字符等
                     ■     但这些可能只是在前端做了校验,后端可能没做校验,如果用户名和密码未在后端做校验,而有人又绕过前端校验的话,那用户名和密码不就可以随便输了吗?如果是登录可能会通过 SQL 注入等手段来随意登录,甚至可以获取管理员权限,那这样不是很恐怖?

    3.2.2 接口测试的意义

    • 更早地发现问题
      ✔     测试工作应该更早地介入到项目开发中,因为越早发现 bug,修复的成本越低。
             ★     功能测试必须要等到系统提供可测试的界面后才能进行。
      ✔     单元测试和接口测试是更早介入测试的两个方面。
             ★     接口测试可以在功能界面未开发出来之前对系统的接口进行测试,从而可以更早地发现问题并以更低的成本修复问题。
             ★     在一些实际项目开发过程中,开发人员并没有充足的时间去编写单元测试,并且他们往往对自己编写的代码有足够的信心,不愿意将时间“浪费”在单元测试的编写上。这个时候接口测试就会变得更加重要。

    • 缩短产品研发周期
      ✔     接口测试的介入可以更早地发现并解决 bug,使得留到功能测试阶段被修复的 bug 减少,从而缩短整个项目的上线时间。

    • 发现更底层的问题
      ✔     系统中的有些 bug 如果想通过 UI 层功能测试会比较困难,或者构造测试条件非常复杂。通过接口测试可以更简单更全面地覆盖到底层的代码逻辑,从而可以发现一些隐藏的 bug。
      ✔     通常把 UI 层的验证称为弱验证,这是因为它很容易被绕过。如果只针对 UI 层的功能进行测试,就很难发现后端系统对一些异常情况的处理能力,而接口测试可以很容易地验证这些异常情况。

    • 前端随便变,接口测好了,后端不用变
      ✔     前端与后端的分离,是近年来 Web 应用开发的一个发展趋势。
      ✔     这种模式的优势
             ★     前端的专业性越来越高,通过调用 Web 接口获取数据,从而专注于数据展示和页面交互的设计。
             ★     后端不必精通前端技术(HTML5/JavaScript/CSS),只专注于数据的处理并提供 Web 接口即可。
                     ■     由后端开发的接口既可以提供给 Web 页面调用,也可以提供给移动APP 调用;
                     ■     既可以提供给公司内部系统调用,也可以提供给公司外部系统调用。

    • 检查系统的安全性、稳定性

    3.3 协议接口的分类

    3.3.1 按系统不同的调用方式进行分类

    • 系统与系统之间的接口
      ✔     系统与系统之间的接口,既可以是公司内部不同系统之间调用的接口,也可以是不同公司不同系统之间调用的接口。
             ★     后者如微信、微博所提供的第三方登录接口,如果你开发的系统不想自建用户体系,那么完全可以调用这些接口来实现用户的登录。

    • 系统内部,服务与服务之间的调用
      ✔     大多情况下是指程序之间的调用。
             ★     假设系统开发一个用户查询接口,输入用户名,返回用户信息(性别、年龄、手机号、邮箱地址等),如果用户不存在则返回 null。
             ★     现在需要新开发一个用户抽奖的接口,该接口需要用户名和抽奖活动 id,抽奖接口得到用户名后可以调用用户查询接口,如果用户查询接口返回null,那么抽奖接口就可以直接返回用户不存在了。
             ★     这个例子中,用户抽奖接口调用的就是用户查询接口。用户查询接口和抽奖接口本质上就是程序开发的函数或方法,提供入参与返回值。

    • 下层服务对上层服务的接口
      ✔     应用层
             ★     可以认为是系统所提供的 UI 层功能。对于 Web 系统来说,就是浏览器页面上所提供的功能,如登录、注册、查询、删除等。
      ✔     Service 层
             ★     可以理解为服务器所提供数据的处理。
      ✔     DB 层
             ★     数据库(DataBase)主要用来存放数据。
      ✔     各层之间的调用过程
             ★     首先应用层实现了一个用户查询的功能,需要用户输入查询的关键字,并显示查询结果。
             ★     当用户使用查询功能时,首先底层调用 Service 层所提供的查询接口,查询接口得到应用层调用的查询数据;然后再通过 DAO 访问数据库,根据用户输入的查询数据,查询数据库中的数据。
             ★     最后,将查询到的数据库数据返回给应用层,用户在应用层看到查询结果。
             ★     在这个过程中,各层之间的交互就是通过接口,应用层与 Service 主要通过HTTP 接口,Service 层与 DB 层主要通过 DAO(Data Access Object)数据库访问接口。

    3.3.2 按协议的不同进行分类

    • webService 接口
      ✔     使用 soap 协议
      ✔     通过 http 传输,请求报文和返回报文都是 xml 格式的
      ✔     通常使用的工具 SoapUI、jmeter、loadrunner 等

    • http api 接口
      ✔     使用 http 协议
             ★     HTTP 是 Hyper Text Transfer Protocol(超文本传输协议)的缩写,是从万维网(www,World Wide Web)服务器传输超文本到本地浏览器的传送协议。
             ★     HTTP 基于 TCP/IP 通信协议来传递数据(HTML 文件、图片文件、媒体等)。
             ★     HTTP 协议工作于客户端-服务端架构上。浏览器作为 HTTP 客户端通过 URL向HTTP 服务端(即 Web 服务器)发送请求。
      ✔     通过路径来区分调用的方法,请求报文都是 key-value 形式的,返回报文一般都是 json 串
      ✔     最常用的两种请求方式是 get 和 post 等方法
      ✔     通常使用的工具有 postman、RESTClient、jmeter、loadrunner 等

    3.4 接口测试的原理

    模拟客户端向服务器发送请求报文,服务器接收请求报文后对相应的报文做处理并向客户端返回应答,客户端再接收应答的一个过程。

    4.接口的组成

    4.1 接口文档的内容

    • 接口说明
    • 调用 url
    • 请求方法(get/post)
    • 请求参数、参数类型、请求参数说明、请求头 header
    • 返回参数说明、请求响应的代码、响应内容

    4.2 http 请求方法与请求参数

    • 参数是客户端向服务器发送的数据,有的可见,有的不可见。

    • GET 请求
      ✔     发送指定参数的请求来取得服务器上的某一资源
      ✔     提交的数据会放在 URL 之后,以?分割 URL 和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456
      ✔     get 请求数据不会出现在 body 中

    • POST 请求
      ✔     向指定资源提交数据,数据被包含在请求体中(提交的数据放在 HTTP 包的 Body 中)
      ✔     不在 url 中出现

    • GET 请求和 POST 请求的区别
      ✔     GET 使用 URL 或 Cookie 传参,而 POST 将数据放在 BODY 中。
      ✔     GET 的 URL 会有长度上的限制,而 POST 的数据则可以非常大。
             ★     不同浏览器要求不同,如 IE6 要求最大 256
      ✔     POST 比 GET 安全。
             ★     get 请求能够被缓存,请求会保存在浏览器的浏览(历史)记录中,请求的数据会显示在地址栏中,不安全,请求的 url 能够保存为浏览器书签(收藏夹)
             ★     post 请求不能被缓存,请求不会保存在浏览器浏览记录中;请求的数据不会显示的地址栏中,相对安全;请求的 url 无法保存为浏览器书签
      ✔     一般 get 请求用来获取数据,post 请求用来发送数据。
      ✔     get 请求数据只支持 ASCII 类型,post 请求数据类型没有限制,支持二进制数据。

    4.3 header

    • 标头 (header) 是服务器以 HTTP 协议传 HTML 资料到浏览器前所送出的字串,一般存放cookie、token 等信息。
      ✔     header 和入参的关系
             ★     它们都是发送到服务器里的参数,但它们是有区别的,header 里存放的参数一般存放的是一些校验信息,比如 cookie,它是为了校验这个请求是否有权限请求服务器,如果有,它才能请求服务器,然后把请求地址连同入参一起发送到服务器,然后服务器会根据地址和入参来返回出参。也就是说,服务器是先接受 header 信息进行判断该请求是否有权限请求,判断有权限后,才会接受请求地址和入参的。
      ✔     Cookie
             ★     万维网站点使用 Cookie 来跟踪用户。
             ★     Cookie 表示在 HTTP 服务器和客户之间传递的状态信息。
             ★     使用 Cookie 的网站服务器为用户产生一个唯一的识别码。利用此识别码,网站就能够跟踪该用户在该网站的活动。
      ✔     Session
             ★     Session 是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间,以及如果需要的话,可能还有一定的操作空间。
             ★     Session 是用于保持状态的基于 Web 服务器的方法。
             ★     Session 允许通过将对象存储在 Web 服务器的内存中在整个用户会话过程中保持任何对象。

    • 请求头信息
      ✔     请求报头允许客户端向服务器端传递请求的附加信息以及客户端自身的信息。
      ✔     常用的请求报头如下:
             ★     Accept:浏览器可接受的 MIME 类型。
                     ■     MIME 用于设定某种扩展名的文件用哪种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。
             ★     Accept-Encoding:浏览器能够进行解码的数据编码方式,比如 gzip。
             ★     Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时会用到。
             ★     Connection:表示是否需要持久连接。从 HTTP/1.1 起,默认都开启了 Keep-Alive,保持连接特性。
             ★     Host:初始 URL 中的主机和端口,它通常是从 HTTPURL 中提取出来的。
             ★     User-Agent:请求报头域允许客户端将它的操作系统、浏览器和其他属性告诉服务器。

    • 响应头信息
      ✔     响应报头允许服务器传递不能放在状态行中的附加响应信息,以及关于服务器的信息和对 Request-URI 所标识的资源进行下一步访问的信息。
      ✔     常用的响应报头如下:
             ★     Content-Type:表示后面的文档属于哪种 MIME 类型。
             ★     Date:当前的 GMT(国际时)时间。
             ★     Server:包含了服务器用来处理请求的软件信息。
             ★     X-Frame-Options:用来给浏览器指示允许一个页面可否在<frame>、<iframe>或者<object>中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,从而也避免了点击劫持(click jacking)的攻击。

    4.4 http 响应状态码

    • 每发出一个 http 请求之后,都会有一个响应,http 本身会有一个状态码,来标示这个请求是否成功。
    • 常见的状态码有以下几种:
      ✔     1**
             ★     表示服务器收到请求,需要请求者继续执行操作。
      ✔     200
             ★     2 开头的都表示这个请求发送成功
             ★     最常见的是 200,代表这个请求是 ok 的,服务器也返回了。
      ✔     300
             ★     3 开头的代表重定向,最常见的是 302,把这个请求重定向到别的地方了。
      ✔     400
             ★     400 代表客户端发送的请求有语法错误,401 代表访问的页面没有授权,403表示没有权限访问这个页面,404 代表没有这个页面。
      ✔     500
             ★     5 开头的代表服务器有异常,500 代表服务器内部异常,503 代表由于超载或系统维护,服务器暂时无法处理客户端请求,504 代表服务器端超时,没返回结果。

    4.5 响应数据

    • 当我们在请求一个页面的时候,会显示服务器返回的资源,其中包含了 HTML、CSS 和JavaScript,除此之外,服务器还可以返回图片、视频、字体和插件等类型的资源。这些资源全部使用 HTTP 协议传输。

    • 如果把 HTTP 协议看作是高速公路的话,那么在高速公路上跑的各种拉满不同货物的车辆就是资源。不同的车辆装载的货物不一样,因此它们的目的地也不一样。
      ✔     如有些车辆拉的是生猪,是要送到屠宰场的;有些车辆拉的是西瓜,是要送到水果批发市场的。

    • HTTP 协议上传输的资源也是一样,类型不同,作用也不一样。数据就是其中的一种资源,数据是接口的本质。
      ✔     可以选择不同的运输方式,走高速公路或走铁路,这就是数据传输协议的选择(如HTTP/SOAP)。
      ✔     西瓜的存放方式,是直接将西瓜堆积到车厢里,还是把每个西瓜放到盒子里再装箱,这就是数据格式的选择(如 TEXT/XML/JSON/CSV)。

    • JSON 格式
      ✔     JSON(JavaScript Object Notation,即 JavaScript 对象表示法)是一种轻量级的数据交换格式。它独立于语言和平台,JSON 解析器和 JSON 库支持不同的编程语言。
      ✔     JSON 具有自我描述性,很容易理解。
      ✔     JSON 格式是当前主流的接口数据格式之一。从接口的调用方式和数据格式来看, JSON 不是直接给普通用户来使用的,它主要为其他开发者提供调用。

    • JSON 响应数据的格式
      在这里插入图片描述
      ✔     数据在名称/值对中。
      ✔     数据由逗号分隔。
      ✔     花括号保存对象。
      ✔     方括号保存数组。

    5.怎么做接口测试

    5.1 接口测试的流程

    • 熟悉业务和需求
    • 分析接口文档
    • 编写接口测试用例
    • 提测后开始测试
    • 提交测试报告

    5.2 编写接口文档

    • 编写接口文档是接口开发中非常重要的一个环节,因为开发的接口是给其他开发人员调用的,那么如何知道接口是怎么调用的呢?当然需要通过参考接口文档了。那么接口文档就必须要做到更新及时,内容准确。
    • 案例
    接口名称添加…说明
    URLhttp://127.0.0.1:8000/api/add_event/测试 add_event 接口
    调用方法POST
    传入参数eid
    name
    limit
    status(1/0)
    参数含义:事件编号
    参数含义:事件名字
    参数含义:限时
    参数含义:开启状态
    返回值‘status’:200,
    ‘message’:‘add event success’
    状态码10021:parameter error
    10022:event id already exists
    10023:event name already exists
    200:add event success

    5.3 通用接口用例设计

    • 通过性验证
      ✔     首先肯定要保证这个接口功能是正确的,也就是正常的通过性测试,按照接口文档上的参数,正常传入,是否可以返回正确的结果。

    • 参数组合
      ✔     现在有一个操作商品的接口,有个字段 type
             ★     type 传 1 的时候代表修改商品,商品 id、商品名称、价格有一个是必传的,这样就要测参数组合了,type 传 1 的时候,只传商品名称能不能修改成功,id、名称、价格都传的时候能不能修改成功。

    • 接口安全
      ✔     绕过验证
             ★     如购买了一个商品,它的价格是 300 元,那我在提交订单时候,我把这个商品的价格改成 3 元,后端有没有做验证,更狠点,我把钱改成-3,是不是我的余额还要增加?
      ✔     绕过身份授权
             ★     如修改商品信息接口,那必须得是卖家才能修改,那我传一个普通用户,能不能修改成功,传一个其他的卖家能不能修改成功。
      ✔     参数是否加密
             ★     如登陆的接口,用户名和密码是不是加密,如果不加密的话,别人拦截到你的请求,就能获取到你的信息。
             ★     加密规则是否容易破解。
      ✔     密码安全规则
             ★     对密码的复杂程度校验。

    • 异常验证
      ✔     就是不按照接口文档上的要求输入参数,来验证接口对异常情况的校验。
             ★     如必填的参数不填,输入整数类型的,传入字符串类型,长度是 10 的,传 11
             ★     必传非必传、参数类型、入参长度。

    5.4 根据业务逻辑来设计用例

    • 就是根据系统的业务来设计用例,这个每个公司的业务不一样,就得具体的看自己公司的业务了,其实这也和功能测试设计用例是一样的。
    展开全文
  • Appium自动化测试-入门

    万次阅读 多人点赞 2017-06-25 18:50:07
    Appium是一个移动端的自动化框架,是跨平台的。可用于IOS和Android以及firefox的操作系统。 • 原生应用是指用android或ios的sdk编写的应用; • 移动网页web应用是指网页应用,类似于ios中safari应用或者Chrome应用...

    一、Appium简介

    Appium是一个移动端的自动化框架,是跨平台的。可用于IOS和Android以及firefox的操作系统。
    原生应用是指用android或ios的sdk编写的应用;
    • 移动网页web应用是指网页应用,类似于ios中safari应用或者Chrome应用或者类浏览器的应用;
    混合应用是指一种包裹webview的应用。

    1.1 Appium架构原理

    Appium是在手机操作系统自带的测试框架基础上实现的,Android4.2版本以上使用的是UIAutomator,Android4.2及以下使用的是基于Android Instrumentation框架实现的自动化测试工具;iOS是基于iOS自带的UI自动化工具UIAutomation实现的。

    Appium由客户端和服务器组成,客户端与服务器通过JSON Wire Protocol进行通信。下图简单的介绍了各部分。

    Appium-架构

    Appium Server:
    Appium server使用node.js写的http服务器,遵守REST风格。主要作用是接受从Appium客户端发起的连接,监听客户端发送来的命令,将命令发送给Bootstrap.jar(或Bootstrap.js)执行,并将执行结果通过HTTP应答反馈给Appium客户端。

    Bootstrap.jar:
    在Android手机上运行的一个应用程序,它在手机上扮演TCP服务器的角色。当Appium需要运行命令时,Appium服务器会与Bootstrap.jar建立TCP通信,Bootstrap.jar负责运行测试。

    Appium Clients:
    是一个扩展WebDriver 协议的库,负责与Appium服务端建立连接,并将脚本的指令发动到服务端。支持多种语言。

    Session:
    Appium的客户端于服务端之间进行通信都必须在一个Session的上下文中进行。客户端在发起通信的时候,会首先发动一个叫“Desired Capabilities”的JSON对象给服务器。服务器收到该数据后,会创建一个Session并将Session ID返回给客户端。客户端可以用此ID发送命令。

    Desired Capabilities:
    是一组设置的键值对的集合,主要用于通知Appium服务器建立需要的Session,其中一些设置可以在Appium运行过程中改变Appium服务器的运行行为。

    1.2 Appium优缺点

    优点:

    • 支持多种应用程序的测试
    • 支持使用多种语言来编写测试脚本
    • 被测试的应用程序不需要特殊的编译
    • Appium支持应用之间跳转的测试

    缺点:

    • 由于服务端运行在电脑上,该工具必须连接电脑才可以运行
    • 只能用于UI的自动化测试,在很多情况下的测试验证只能通过验证界面来进行

    1.3 WebDriver

    Appium采用底层驱动商提供统一的WebDriver API,它和Selenium有着千丝万缕的联系,很多方法的使用都很相似,可以参考笔者之前写过的Selenium文章。

    Selenium自动化测试-入门
    Selenium自动化测试-unittest单元测试框架使用

    二、Appium环境搭建

    2.1 安装Appium运行环境

    1. Android运行环境
      安装Android SDK后,并将其加入到系统环境变量中。
    2. 安装Python
    3. 安装Node.js
      是为了用命令行的方式启动Appium。
    4. 安装Appium服务器
      可以从此网站下载安装http://appium.io/

    2.2 Appium服务器启动

    打开Appium软件后,点击右上角的三角形,可以打开启动服务器,如下所示:

    appium运行

    如果输出类似如下信息,没有错误提示,就表示启动成功了。

    > Launching Appium server with command: C:\tools\Appium\node.exe lib\server\main.js --address 127.0.0.1 --port 4723 --platform-name Android --platform-version 23 --automation-name Appium --device-name "8c28b78c" --log-no-color
    > info: Welcome to Appium v1.4.16 (REV ae6877eff263066b26328d457bd285c0cc62430d)
    > info: Appium REST http interface listener started on 127.0.0.1:4723
    > info: [debug] Non-default server args: {"address":"127.0.0.1","logNoColors":true,"deviceName":"8c28b78c","platformName":"Android","platformVersion":"23","automationName":"Appium"}
    > info: Console LogLevel: debug
    

    启动之后,可以在浏览器里面访问http://localhost:4723/看看是否有反应,如果正常启动的话,肯定是有反应的。我们需要在设置中改变一些设置,也可以将界面中的log信息导出到文件中,便于我们处理。

    appium setting

    appium setting2

    三、编写脚本前的准备

    3.1 查看页面元素

    Native APP:
    我们可以使用Android SDK安装目录下的uiautomatorviewer来查看APP的页面元素,~\sdk\tools\uiautomatorviewer.bat

    appium uiautomator

    也可以使用Appium inspector来查看,但是没有uiautomatorviewer那么好用。

    appium inspector

    含有webview的APP:
    可以通过Chrome的DevTools来获取,在Chrome中输入chrome://inspect/#devices后,如果有连接上的设备,可以点击inspect进入查看页面。

    devtools

    不过,有时通过这种方法是无法获取到页面的,原因可能是被测程序的WebView没有开debug模式等。这时我们可以获取当前页面的URL然后通过Chrome或Firefox等来访问并且查看元素。

    3.2 相关文档

    这个网站上说明了Appium的方方面面,如设计理念、各个平台的安装、脚本编写等等。http://appium.io/slate/cn/master/?python#about-appium

    通过appium在GitHub上的介绍我们可以获取编写脚本的一些方法,这里给出的是Python语言的链接。https://github.com/appium/python-client

    3.3 简单示例

    用Python写Appium的脚本时,只需以下几步即可以构造一个基本的用例,如下代码片断所示:

            #构造Desired Capabilities
            desired_caps = {}
            desired_caps['platformName'] = 'Android'
            desired_caps['platformVersion'] = '6.0.1'
            desired_caps['deviceName'] = '8c28b78c'
            desired_caps['appPackage'] = 'com.ss.android.article.news'
            desired_caps['appActivity'] = '.activity.SplashActivity'
            driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
    
            #1.获取元素
            videoBtn = driver.find_element_by_name("视频")
    
            #2.操作元素
            videoBtn.click()
    
            #3.结果验证
    
    

    我们首先需要构造一个Desired Capabilities,设置一些参数,用它来连接到APP中,然后就是进行UI自动化操作的标准3步了。

    1. 获取页面控件
    2. 操作控件
    3. 控件信息验证

    对这三步很熟悉了之后,我们再在这个基础上做一些封装,使得脚本更加健壮,可维护性更高。接下来按照以上几步来一步步做吧。

    四、Desired Capabilities说明

    Desired Capabilities就是一组设置,这些设置可以让测试脚本控制Appium的运行行为。下面对这些设置做一个简单的说明。从其官方网站我们可以得到全面的信息,网址为:http://appium.io/slate/en/master/?java#appium-server-capabilities

    4.1 与Appium服务器相关的

    Capability是否为必填项描述
    automationNameAppium使用的测试引擎Appium(默认)
    platformName被测设备的系统平台iOS,Android,Firefox OS,null(默认)
    platformVersion手机系统版本如6.6.1,null(默认)
    deviceName测试设备类型(测试Android时被忽略)null(默认)
    app指向APP安装文件,Android中如果设置了appActivity和appPackage,则此会被忽略null(默认)
    browserName手机网页测试时浏览器的名称设置为Safari在测iOS和Chrome时,设置为Browser在测Android时
    newCommandTimeoutAppium服务器等待Appium客户端发送新消息的时间,单位为s60s(默认)
    language(仅模拟器使用)设置模拟器的语言null(默认)
    locale(仅模拟器使用)设置模拟器的使用国家null(默认)
    udid(仅真机使用)测试设备的ID在多台设备与同一台电脑连接时必须指定
    orientation(仅模拟器使用)屏幕方向LANDSCAPE,PORTRAIT,null(默认)
    autoWebview直接切换到WebView上下文false(默认),true
    noReset在一个Session开始前不重置被测程序的状态false(默认),true
    fullReset完全重置(Android通过卸载程序的方式),Session完成后会卸载程序false(默认),true

    ~

    4.2 仅对Android测试有效的设置

    Capability是否为必填项描述
    appActivity被测APP启动的Activity名称如.MainActivity
    appPackage被测APP的包名例如:com.example.android.myApp
    deviceReadyTimeout等待设备ready的超时时间5s(默认)
    ignoreUnimportantViews会忽略一些控件,加快运行false(默认),true
    disableAndroidWatchers只针对基于UIAutomator的测试有效,不会监控ANR和Crash,这将较少CPU消耗false(默认),true
    unicodeKeyboard是否支持Unicode的键盘,如果输入中文,设置为是false(默认),true
    resetKeyboard测试结束后是否恢复键盘,为正常的手机键盘false(默认),true
    androidScreenshotPath截图存放的目录/data/local/tmp(默认)

    ~

    关于Android测试的Capability非常的多,以上只是其中常用的一部分。还有iOS相关的没有在这里叙述了,有兴趣的可以访问前面给出的官网地址去查看。

    五、获取控件

    5.1 Native APP

    API方法描述
    find_element_by_id(self,id)通过控件的resource id来查找控件
    find_element_by_name(self,name)Native APP中,name就是控件的Text
    find_element_by_class_name(self,name)控件的class name,网页测试也可以用此
    find_element_by_accessibility_id(self,id)控件的accessibility_id就是Content Description
    find_element_by_android_uiautomator(self,uia_string)根据UIAutomator的语法查找控件,是WebDriver在兼容Appium时才新加的语法

    ~

    页面中同一个ID的控件可能不止一个,最常见的就是列表项。find_element_by_id是查找页面中第一个ID为指定参数的控件,find_elements_by_id是查找页面中所有ID为指定参数的控件,返回一个控件列表。其他的查找方法类似。

    5.2 Web&Hybrid APP

    API方法描述
    find_element_by_xpath(self,xpath)通过控件的xpath来查找控件
    find_element_by_css_selector(self,css_selector)通过控件的css_selector来查找控件
    find_element_by_link_text(self,link_text)通过链接的text来查找控件
    find_element_by_partiallink_text(self,link_text)通过链接的部分文本来查找控件
    find_element_by_tag_name(self,tag_name)通过网页元素的Tag查找控件

    ~

    这一部分的控件查找和Selenium中的几乎一样,可以查看笔者之前的相关文章。

    5.3 获取控件举例

    appium find1

    下面代码片段为获取图中底部tab的视频按钮的两种方法。第一种用到了name属性,先找到其父控件,进一步缩小范围,因为页面中可能在其他地方也有相同的name。第二种是用find_elements系列的方法,再拿到列表中的第2项,因为下方的几个控件id都是相同的。

    self.driver.find_element_by_id("android:id/tabs").find_element_by_name("视频").click()           self.driver.find_elements_by_id("com.ss.android.article.news:id/b5e")[1].click()

    对于一些找不到方法去定位的元素怎么办呢?首先想到的就是坐标定位,为了兼容更多的机型,可以用相对坐标或者距离元素的位置来定位。更高端的方法就是可以采用图像识别来确定要定位的元素,从而进行点击,可以参考这篇文章。http://tmq.qq.com/2017/02/test_guide/

    六、操作控件

    6.1 获取控件信息(部分)

    API方法描述
    text(self)获取控件显示的文本信息
    is_enabled(self)判断是否可用了,可用返回true
    is_selected(self)是否被选中了,是的话返回true
    id_displayed(self)判断控件是否显示,是的话返回true
    get_attribute(self,name)获取控件某项信息,如element.get_attribute(“displayed”)等同于id_displayed方法
    parent(self)返回控件的父控件,返回值为一个控件对象

    6.2 手势操作(部分)

    主要有点击、滑动、拖拽、放缩等常用的操作。

    API方法描述
    click(self)点击控件
    clear(self)清楚文本框控件的文本
    send_keys(self,*value)发送文本到控件中
    tap(self,positions,duration=None)positions是一个列表,每个列表是一个二元组最多可以同时点击5个点;duration为时间长短,给参数的话则是长按操作
    swipe(self,start_x,start_y,end_x,end_y,duration=None)从一点滑动到另一点,时长为毫秒
    flick(self,start_x,start_y,end_x,end_y)两点快速的滑动
    scroll(self,origin_ele,destination_ele)从origin_ele控件滚动到destination_ele控件
    drag_and_drop(self,origin_ele,destination_ele)把origin_ele控件拖拽到destination_ele控件的位置
    pinch(self,element=None,percent=200,steps=50)在指定控件上执行缩小操作,默认缩放比例为2,分50步完成
    zoom(self,element=None,percent=200,steps=50)在指定控件上执行放大操作,默认缩放比例为2,分50步完成

    6.3 系统操作API(部分)

    系统操作用于模拟硬件操作、设置网络环境、获取系统信息等,下表简单的介绍一下常用的方法。

    API方法描述
    launch_app(self)启动Capability中指定的APP
    is_app_installed(self,package_name)判断应用程序是否安装
    install_app(self,app_path)安装APP,app_path指的是电脑上的apk路径
    close_app(self)如果Capability指定的APP在运行,则关闭它
    background_app(self,seconds)将APP放到后台运行一段时间
    reset(self)重置当前被测APP到初始状态
    current_activity(self)获取当前正在显示的Activity
    start_activity(self,app_package,app_activity,**opts)启动某个Activity
    pull_file(self,path)拉取手机上的一个文件,并以base64格式编码返回数据,path为手机文件路径
    pull_folder(self,path)拉取手机上的一个文件夹,打包后以base64格式编码返回数据,path为手机上的文件夹路径
    push_file(self,path,base64data)将一个base64编码格式的文件从电脑推送到手机上的路径path上
    press_keycode(self,keycode,metastate=None)模拟发送一个硬件码到手机,如返回等
    open_notification(self)打开通知栏
    network_connection(self)返回当前网络连接的类型
    set_network_connection(self,connectionType)设置网络,值为:0 未设置,1 飞行模式,2 WiFi only, 4 Data only, 6 WiFi& Data
    get_screenshot_as_file(self,filename)截图并保存在电脑上,filename为路径及截图名称
    save_screenshot(filename)截图并保存在电脑上,filename为路径及截图名称

    七、控件信息验证

    这里我们要说的是查找并操作控件后,怎么确定我们的操作起了作用。在实际的测试中也把它叫做检查点,检查点的划分和验证是UI自动化中的一个重点也是难点。常用的有以下方法:

    1. 判断某个控件是否显示(操作之后新出现的控件)
    2. 判断某个控件是否被选中
    3. 判断某个开关控件是否处于check状态
    4. 判断某个控件是否enabled
    5. 截图之后和正确的进行比对

    可以将以上判断的方式进行封装,便于我们在if语句和assert中使用。关于截图对比的方式,首先要有正确的操作截图,然后再进行对比得出结论看看是否一致,会涉及一些算法相关的知识。

    八、常见问题

    8.1 A new session could not be created

    有一次在执行的过程中,发现输出了以下错误;

    selenium.common.exceptions.WebDriverException: Message: A new session could not be created. (Original error: An unknown server-side error occurred while processing the command. (Original error: unknown error: com.android.chrome is not installed on device 8c28b78c
      (Driver info: chromedriver=2.18.343845 (73dd713ba7fbfb73cbb514e62641d8c96a94682a),platform=Windows NT 10.0 x86_64)))

    可以发现主要的错误应该是com.android.chrome is not installed on device,这个看起来应该是chrome浏览器的手机端,我们可以尝试安装它。但是,我记得手机上一直都没有安装过这个,最后又检查了一下,发现原来是打开了Appium设置中的Browser,关闭此即可。

    appium setting

    然而,除了这个原因有可能是别的原因,我们要具体分析错误输出,还可以做一些事情来来降低这种情况的发生:

    1. 在初始化的setUp()方法中调用ADB命令强制关闭被测应用一次;
    2. 添加–session-override选项,命令行中或者Appium界面中;
    3. 在tearDown()方法中,关闭Appium的session,清理环境。

    8.2 Permission to start activity denied.

    在使用start_activity()方法来启动另一个APP时,有时会遇到如下错误:

    selenium.common.exceptions.WebDriverException: Message: Unable to launch the app: Error: Permission to start activity denied.

    这时可以看到我们没有权限打开这一个Activity,通常是因为此Activity在清单文件里面没添加Android:exported=”true”,exported属性就是设置是否允许activity被其它程序调用的。所以我们需要从启动页Activity打开如下所示。这在一些情况下可能会有点麻烦。

    app_package='com.gotokeep.keep'
    app_activity='.activity.SplashActivity'
    self.driver.start_activity(app_package,app_activity)

    还有一种错误是找不到要打开的Activity:

    elenium.common.exceptions.WebDriverException: Message: Unable to launch the app: Error: Activity used to start app doesn’t exist or cannot be launched! Make sure it exists and is a launchable activity

    这时我们要检查Activity是否存在,并且路径是否填写正确。

    展开全文
  • Java接口自动化测试框架

    千次阅读 2019-11-21 12:07:20
    自动化测试框架 1. 测试框架TestNG 1.1 适合测试人员使用的原因 (1)比Junit涵盖功能更全面的测试框架 (2)Junit更适合隔离性比较强的单元测试 (3)TestNG更适合复杂的集成测试 1.2 基本介绍 (1)基本注解:...
  • WEB自动化测试面试题及答案大全

    千次阅读 2020-07-11 14:20:32
    1.Selenium是否支持桌面应用软件的自动化测试。 Selenium不支持桌面软件的自动化测试,Selenium是根据网页元素的属性才定位元素,而其他桌面软件自动化测试工具是根据桌面元素的位置来定位元素,当然现在也有根据...
  • 自动化测试面试题及答案大全(5)

    万次阅读 多人点赞 2019-04-20 09:17:45
    1.Selenium是否支持桌面应用软件的自动化测试。 Selenium不支持桌面软件的自动化测试,Selenium是根据网页元素的属性才定位元素,而其他桌面软件自动化测试工具是根据桌面元素的位置来定位元素,当然现在也有根据...
  • 一、前言 最近有童鞋和我抱怨,说很...当我第一次知道自动化测试的时候,除了知道“自动化”这三个有些高大上的称呼之外,我对自动化测试一无所知,正如谈恋爱一样,找女朋友之前要知道她是谁。 自动测试就是把以...
  • 如何简单实现接口自动化测试(基于 python)

    万次阅读 多人点赞 2017-09-05 11:52:25
    GitChat 作者:饿了么技术社区 本文从一个简单的登录接口测试入手,一步步调整优化接口调用姿势,然后简单讨论了一下接口测试框架的要点,最后介绍了一下...期望读者可以通过本文对接口自动化测试有一个大致的了解。
  • 自动化测试面试题及答案

    千次阅读 多人点赞 2020-04-26 11:48:48
    自动化测试是什么?自动化测试学什么?自动化测试面试题及答案?–看完后吊打面试官! 一、前言 最近有童鞋和我抱怨,说网上很难搜到那些全面又合适的自动化测试面试题,这里根据我个人的经验以及收集整理的: 你没...
  • 自动化测试的前沿技术分享

    千次阅读 2017-09-07 15:38:18
    一什么是自动化测试 二移动自动化测试的流程 三移动自动化测试的优点 四移动自动化测试的缺点 五移动测试自动化框架Android 六Appium 我选择的是Appium为什么呢 Appium简介 Appium的要求 Appium概念 ...
  • App自动化测试方案

    千次阅读 2019-09-29 10:56:00
    App自动化测试方案1.1 概述什么是App自动化?为什么要做App自动化?App自动化是指给 Android或iOS上的软件应用程序做的自动化测试。手工测试和自动化测...
  • 软件测试面试题整理(一)之自动化测试题大合集

    千次阅读 多人点赞 2020-11-01 23:25:18
    1 什么是POM,为什么要使用它?...为了我们测试用例写的简单,清晰,我们很多时候在页面对象会封装很多业务操作方法,测试脚本只需要调用相关方法就可以。 2如果页面元素经常发生需求变化,你是如何做? 采用POM思..
  • python分布式自动化测试框架

    千次阅读 2018-04-29 12:48:39
    先介绍下该测试框架基本架构基本功能 当要在同一台主机上进行多条测试用例的并行时,对于CPU和内存的消耗比较大,因此,当... 该使用测试框架时,测试人员可自行开发自动化测试用例,编写完成后,上传至我的服务端...
  • 不管是在做接口自动化还是在做UI自动化测试人员遇到的第一个问题都是卡在登录上。 那是因为在执行登录的时候,服务端会有一种叫做session的会话机制。 一个很简单的例子: 在做功能测试的时候,肯定会遇到一种...
  • 下面我们进入正题—接口自动化测试面试题 一、get和post的区别? http是上层请求协议,主要定义了服务端和客户端的交互规格,底层都是tcp/ip协议 Get会把参数附在url之后,用?分割,&连接不同参数,Get获取...
  • selenium 自动化测试面试题及答案

    万次阅读 2018-01-19 19:36:26
    一,自动化测试用例是用来监控的,在此目的下,我们就把自动化测试用例设置成定时执行的,如果每五分钟或是一个小时执行一次,在jenkins上创建一个定时任务即可。 二,必须回归的用例。有些儿测试用例,如BVT测试...
  •  在做接口的自动化测试中,无法绕过cookie,某些时候我们需要处理,那么怎么处理?另外一个方面,什么是cookie? cookie它的工作机制是用户识别以及状态管理,网站为了管理用户的状态会通过web的浏览器,把一些...
  • Robot Framework 框架本身并不提供任何类型的测试,它只提供作为自动化测试框架的基本功能,如用例的批量执行、测试报告的生成等。 使用简单 ✔ 可以像编写程序一样编写 Robot Framework 脚本。 ✔ 易于使用,...
  • 期望读者可以通过本文对接口自动化测试有一个大致的了解。  接口测试概念:接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查...
  • 自动化测试APP一般用什么工具?

    千次阅读 2020-09-06 13:56:57
    如今自动化测试已经应用到每天的测试中。这不足为奇,因为自动化测试在测试过程中节约了时间,还能避免包括人为因素造成的测试错误和遗漏。 自动化测试工具选择很多。一些是开源的,一些非常贵。一些自动化工具是几...
  • 前端设计完成后,看后端接收用户名和密码并进行处理,也就是去与数据库做对比,如果通过则登录成功,不通过则失败,另外登录成功还需要将session保存,其他页面的访问必须要先获取到session,才能访问。 from ...
  • Web自动化测试Selenium 学习笔记(一)

    万次阅读 多人点赞 2018-05-14 20:34:47
    1、Web自动化测试简介自动化基础:自动化用例编写、Selenium优势及原理、自动化环境搭建Selenium基础:常见8大元素定位(表格)、常见元素处理、下拉框元素处理、不同窗口切换、元素进阶、元素等待需求到框架 需求...
  • 移动APP自动化测试框架对比

    万次阅读 2016-10-20 18:34:01
     移动APP的UI自动化测试长久以来一直是一个难点,难点在于UI的”变”, 变化导致自动化用例的大量维护。从分层测试的角度,自动化测试应该逐层进行。最大量实现自动化测试的应该是单元测试,最容易实现也最容易在...
  • 一、自动化测试用例是用来监控的,在此目的下,我们就把自动化测试用例设置成定时执行的,如果每五分钟或是一个小时执行一次,那可以在jenkins上创建一个定时任务即可。 二、必须回归的用例。有些测试用例,如BVT...
  • 1.自动化测试面试技术详解: web自动化 APP自动化 接口自动化 1.今年的软件测试的招聘需求,在所有薪资相对客观的岗位上都会明确标注: 懂得一门编程语言,Java/Python 懂得研发测试工具、测试框架、具备自动化测试...
  • python全栈面试题大纲1、解释一下python的特性之一多态,以及super()?...7、在python做接口自动化测试中,怎么解决参数关联?8、jmeter、loadrunner、locusts性能测试工具的区别?9、UI自动化中如何做到
  • Pytest接口自动化测试框架搭建模板

    千次阅读 2021-01-21 16:47:54
    测试框架: Pytest、测试报告: Allure 项目源码Git地址 项目目录结构 api – 模仿PO模式, 抽象出页面类, 页面类内包含页面所包含所有接口, 并封装成方法可供其他模块直接调用 config – 配置文件目录 data – 测试...
  • python 接口自动化测试-----常见面试题汇总

    千次阅读 多人点赞 2020-09-21 10:47:59
    程序不同模块之间传输数据并作处理的类或函数 2、HTTP 和 HTTPS 协议区别? 答: https 协议需要到 CA(Certificate Authority,证书颁发机构)申请证书,一般免费证书 较少,因而需要一定费用; http 是超文本传输...
  • 现在的很多网站在登陆时都需要验证码,倘若遇到自动化测试时,怎么解决呢?验证码大概有以下几种:有的是图片验证码:图片上显示数字,汉字,英文数字以及算术题等;有短信/邮箱发送验证码:一般为四位/六位/八位...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 110,183
精华内容 44,073
关键字:

自动化测试怎么处理session