测试理论

B/S架构和C/S架构区别

  1. B/S架构需要重点考虑系统在不同的浏览器中的兼容性问题(浏览器的内核不同)
  2. C/S 架构需要考虑系统在不同平台的安装、卸载、升级

HTTP协议

超文本传输协议,应用层协议,由请求与响应组成。
常见的请求方式有POST/GET,常见的状态码200ok,301永久移动,302临时移动,404找不到资源,500服务器内部错误。

POST与GET区别

  1. get请求常用在获取数据,post常用于发送数据
  2. get请求速度比post稍快
  3. get请求的数据是跟随请求地址一起发送,而post是在请求体中单独发送。

Cookie和Session的区别与联系

cookie是存放在浏览器上而session是存放在服务器上的。
cookie不是很安全,涉及到用户隐私方面尽量存放在session中。
当访问量增多时,session会更加占用服务器资源。

测试的目的

发现软件的缺陷与漏洞,对软件的质量进行评估,提升软件质量。

软件测试原则

  1. 所有的软件测试都应追溯到用户需求。
  2. 尽早地和不断地进行软件测试
  3. 完全测试是不可能的,测试需要终止。
  4. 充分注意测试中的群集现象。
  5. 程序员应避免检查自己的程序。
  6. 尽量避免测试的随意性

软件测试分为哪几个阶段?

单元测试、集成测试、系统测试、验收测试

单元测试与集成测试的侧重点

单元测试是对程序最小可测试的模块进行测试
集成测试是把各个模块连接起来时,穿越模块接口的数据是否会丢失。

系统测试范围

功能测试、用户体验测试、性能测试、UI测试、兼容性测试、安装测试、文档测试、稳定性测试等

a测试与ß测试的区别

a测试:公司组织的内部人员进行的测试
ß测试:公司组织的典型客户在实际生活中使用。

验收测试怎么做?

在UAT测试之前,我们会制定测试方案,选择基线用例,即级别高的用例,在UAT测试环境上进行测试,如果测试通过,验收测试就通过了。

白盒、黑盒和灰盒测试区别

白盒测试:对程序的内部结构与算法进行的测试
黑盒测试:不考虑程序的内部结果,只检查程序是否实现了需求的功能
灰盒测试:关注系统接口所实现的功能,是否和需求一致。

冒烟测试的目的

检查程序的基本功能是否正常

回归测试怎么做?

首先,把bug单对应的用例执行一遍,还要检查有数据交互的模块会不会受影响,有没有引入新的问题;项目上线前,还要把当前版本的重要功能以及冒烟测试的用例都回归一遍,确保重要功能上线后不出问题。

全部回归与部分回归的区别?

全量回归:对软件的新版本测试时,重复执行上一个版本测试时使用的测试用例,防止以前没有的问题现在出问题了
部分回归:当开发修复某个bug时,我们需要去检查该bug是否被修复,还需要检查与之相关联的模块是否受到影响。

需求分析的目的

澄清需求,提取测试点

测试计划的目的

规范软件测试内容、方法和过程

什么时候开始写测试计划

需求分析之后

由谁来编写测试计划

一般都是由测试经理或者测试组长来编写

测试计划的内容

测试项目的背景、测试范围和测试策略、测试环境、测试开始和结束条件、进度安排,测试组织,以及与测试有关的风险等方面的内容。

结束条件(项目上线的条件)

需求的覆盖率、用例的执行率和缺陷的遗留率达到质量目标。
通常来说:需求覆盖率和用例执行率需要达到100%
致命/严重的缺陷需要当天解决,轻微/一般遗留率不得超过30%

常见的测试风险

进度风险、质量风险和需求变更

测试用例的要素

用例编号,用例名称,级别,预置条件,测试步骤,期望结果

测试用例级别的划分

一般是依据用户使用该场景的频率,和该功能对系统的影响程度来确定

怎样保证覆盖用户需求?

项目开始前,我们会先熟悉需求,画好流程图,保证整个流程都覆盖全面,小组之间每个人都要根据各自的流程图,各个功能点有哪些限制条件,来讲解一下自己对测试点的理解,防止之后编写测试用例时出现遗漏;用例编写完之后,再进行用例的评审,看看测试点有没有用遗漏,对需求理解有没有错误,测试场景是否覆盖完全。

写好测试用例的关键 /写好用例要关注的维度

  1. 覆盖用户的需求;
  2. 从用户使用场景出发,考虑用户的各种正常和异常的使用场景;
  3. 用例的颗粒大小要均匀。通常,一个测试用例对应一个场景;
  4. 用例各个要素要齐全,步骤应该足够详细,容易被其它测试工程师读懂,并能顺利执行;
  5. 做好用例评审,及时更新测试用例。

测试用例的状态

英文 中文
No Test 未执行状态
Pass 通过状态
Fail 失败状态
Block 阻碍状态。
Investigate 观察中状态。

常见的测试用例设计方法

  1. 等价类
  2. 边界值
  3. 判定表
  4. 场景法
  5. 错误推测法

判定表用在哪些时候/哪些功能

  • 判定法,是用在不同的输入组合,可能会产生不同的输出这种情况,比如,一个有多个查询条件的查询功能,输入不同的查询条件组合,输出的结果是不一样的,这样的功能就要用到判定表

什么时候用到场景法

  • 使用场景法通常是在冒烟测试中或者 一些流程性比较强的软件/功能(比如安装,卸载等等)

测试环境怎么搭建的?

参考答案:搭建环境前,开发都会给到我们一份系统发布手册,我们会根据这个手册来搭建。比如,我这个xx系统,是搭建在Unix系统下的,web服务器用的是Tomcat8,MySQL版本是5.7,程序是JAVA编写的,首先我们向开发拿到编译好的安装包,然后用xshell(或CRT)远程连接上Unix系统,把tomcat服务器停掉,把程序包放到webapps目录下,然后再启动tomcat服务器就可以了。

偶然性问题的处理

  1. 发现bug之后,我们会先截图,如果确定是偶然性的问题,会将日志和截图一起提单给开发定位;
  2. 如果缺陷在当前版本无法复现,且缺陷的影响程度比较低,可以提交问题单进行跟踪,跟踪三个版本,如果后三个版本都无法复现,就可以关闭该缺陷;
  3. 如果是很严重的Bug,比如导致系统崩溃等,并且,实在没有再次出现,除了要及时反馈给上级之外,最后还要写到测试报告中,说明出现了什么现象,但无法再现!

当我们认为某个地方是bug,但开发认为不是bug,怎么处理?

  1. 先跟开发沟通,确认系统的实际结果是不是和需求有不一致的地方;有些地方可能需求没提及,但是用户体检不好,我们也可以认为是bug。
  2. 如果开发以不影响用户使用为理由,拒绝修改,我们可以和产品经理,测试经理等人员进行讨论,确定是否要修改,如果大家都一致认为不用改,就不改。

产品在上线后用户发现bug,这时测试人员应做哪些工作?

  1. 测试人员复现问题后,提交问题单进行跟踪;
  2. 评估该问题的严重程度,以及修复问题时的影响范围,回归测试需要测试哪些功能;
  3. 问题修复后,先在测试环境上回归,通过后再在生产环境上打补丁,然后再进行回归测试;
  4. 总结经验,分析问题发生的原因,避免下次出现同样问题。

二八定理

80%的缺陷出现在 20%的模块。

如何跟踪缺陷

当发现缺陷后,我们要在禅道上提交问题单给开发,并每隔一段时间(间隔一个小时,或两个小时都可以)去检查缺陷是否被处理,如果没及时处理,就要提示开发,让开发及时修复问题,问题修复后,要及时进行回归测试。

缺陷的状态

激活,确认,已解决,关闭

缺陷的等级

致命,严重,一般,轻微

缺陷单应该包含这些要素

缺陷标题,严重级别,问题所属模块,复现步骤,预期结果,实际结果,有关的日志和截图。

测试报告的主要内容

人力投入,用例统计,问题单分类统计,遗留bug情况,测试风险,测试对象评估,测试结论

如何定位bug:

  1. 检查测试环境配置是否有问题,测试数据是否有问题
  2. 用fiddler抓包,分析请求和响应数据是否存在问题
  3. 查看应用服务器的日志
  4. 然后再查看数据库的数据是否存在问题

开发没时间修复,如何推进bug的修复:

  1. 和开发说明该问题的严重性,会怎样影响产品的正常使用,如何还是坚持不改,就上报领导,让领导辅助推进;
  2. 确认问题的严重程度,如果影响不大,不是非要改的bug,并且修复风险比较大,和领导商量后,如果认为暂时可以不用修复,也可以不修复。

软件测试流程

我们这个项目是两个人负责测试的,按模块进行分工,我负责xxx模块。项目启动后,我们会到服务器上下载相关的需求文档,熟悉项目的流程,进行需求澄清,提取测试点;然后编写测试用例,再进行组内的评审,修改,定稿;在开发阶段,开发人员写完一个接口,我们就测试一个接口;等开发转测后,我们从svn上获取安装包,搭建测试环境;之后我们开始进行冒烟测试,冒烟通过后,我们就进入SIT测试,之后进行UAT用户验收测试,验收通过后,编写测试报告。

项目介绍

参考思路:项目叫什么名字,什么架构,有哪些模块,用来干什么的,主要的操作流程

参考:我就说一下最近的一个项目,是集书芸管理系统,主要是一款基于B/S架构的电商分销管理系统,前台模块有店铺首页,购物车,会员中心,申请分销等,后台模块有店铺管理,书籍管理,订单管理,分销管理等,在后台可以上架新的商品,设置店铺活动,管理订单等,用户可以在前台注册成为会员,然后登陆系统,搜索上架的商品,将商品加入购物车之后进行结算下单,或者直接进行结算下单,下单后在用户的‘我的订单’能看到该订单信息,订单状态为待付款,在系统后台的订单管理列表也能看到该订单的信息,买家付款后,订单状态为待发货状态 ,卖家就可以进行发货,买家收到产品后进行确认,评论,整个购物的流程就结束了。这就是我这个项目的大概情况。

对一支圆珠笔进行测试,要从哪些方面进行测试?(扩展:还有可能是对一个水杯,一个注册功能,登陆功能,电梯等,进行测试。)

对任何东西测试一定要从质量的各个方面去说

三角形测试用例设计

解题思路
我们可以设三角形的3条边分别为A,B,C。如果它们能够构成三角形的3条边,必须满足:

A B C均是正数且大于0,还需满足

  • A>0,B>0,C>0,且A+B>C,B+C>A,A+C>B。
  • 如果是等腰的,还要判断A=B,或B=C,或A=C。
  • 如果是等边的,则需判断是否A=B,且B=C,且A=C。

在项目中发现哪些经典bug?什么原因导致的?

  1. 注册信息中的错误提示信息:如手机信息栏应填入11位有效电话号码,但提示信息却为“13位电话号码”,这是因开发人员粗心大意造成的
  2. 接口bug:传的字段值为空,但是开发没给默认值设个0导致接收不到
  3. 数据用fiddler可以抓包拦截篡改数据
  4. 弱网环境下订单可以重复提交
  5. 验证码可以重复使用
  6. 跑性能测试的时候,当前账号下的订单跑到别的账户上去了每次重新登陆都提示重设支付密码,而且设置的密码不能和上次相同
  7. 在未登录的情况下添加商品到购物车跳转到登录页面,登录成功后购物车数量不会增加
  8. 第一次提现申请未审核,再继续第二次提现申请无法成功
  9. 前台发布出租房源,后台通过审核并且成功加入出租列表,前台搜索失败

一个项目完成时,有多个重要的缺陷没有被修复,但是项目负责人说可以不修改,你认为测试是不通过的,请简述你的理由。

测试是对软件的质量进行的把关,如果一个项目仍然有很多的缺陷未被修复,那么从质量的角度上我们会认为这个软件质量是不达标的,一般来说缺陷的遗留,是不允许严重、致命bug的遗留,轻微和一般的bug遗留率不超过30%。

在需求文档不太详细的情况下,如何开展测试?

  1. 首先,把需求文档中有异议的部分标识出来,再找产品和开发一起讨论,把需求明确下来;
  2. 提取测试点,然后再叫上产品和开发一起对测试点进行讨论,看有没有遗漏,是不是合理的,
    然后再编写测试用例,再评审,评审通过后,再进行后续的测试。

如何尽快找到软件中的bug?

  1. 尽快熟悉公司的产品业务,只有熟悉了产品的业务流程、你才能迅速找出软件中存在的一些重要的缺陷;
  2. 把自己当成用户,把自己当成是用户去使用该系统
  3. 善于怀疑,不要过于相信开发人员的能力;

什么是bug?

  1. 软件未实现需求和规格要求的功能 ;
  2. 软件未实现需求和规格未明确提及但应该实现的内容 ;
  3. 软件难以理解,不易使用,运行缓慢,或者最终用户(估计会)认为不好;
  4. 测试用例执行中发现的与预期结果不符的现象

ATM机吞卡的吞卡现象是不是BUG?

不一定,看是什么情况下吞卡。如:输入三次密码错误吞卡是正常的,不属于BUG;若输入一次密码错误吞卡则是不正常的,属于BUG。

如何减少非问题单的提交?

  1. 熟悉项目需求,充分了解各个各个功能模块的功能、参数、约束条件,弄清存在数据交互的模块之间的数据来源、数据流向;
  2. 跟产品确认该问题是否属于非问题单。

有个程序,在windows上运行很慢,怎么判断是程序存在问题,还是软硬件系统存在问题?

将程序放在其他的windows上运行,如果运行的还是很慢则是程序的问题。

你们发现bug会怎么处理。

答:发现bug后,我们会先自己定位一下,比如,抓个包,看看是前端的问题,还是后端的问题,检查下数据库的数据是不是正确的,尽量把问题发生的原因或者产生的日志找出来,方便开发定位问题,然后就提单给开发,然后开发做出相应的处理,开发修复完后就进行回归测试,回归测试通过后就关闭这个bug,没有通过就继续给回开发修复。如果遇到开发认为这个不是bug的话,那么我们就要和开发沟通,然后我们要坚持自己的立场,通过讨论后一致认为是bug就给开发修复,不是就关闭这个bug。如果开发和我们意见一直不一致,那么就要将问题升级,召集开发经理和测试经理一起讨论,再做决定。

功能模块测试

支付怎么测试

  • 从功能方面考虑:

    1. 正常完成支付的流程;
    2. 支付中断后继续支付的流程;
    3. 支付中断后结束支付的流程;
    4. 单订单支付的流程;
    5. 多订单合并支付的流程;
    6. 余额不足;金额的最小值 :如0.01;金额为0;金额为负数
    7. 未绑定银行卡;
    8. 密码错误;
    9. 密码错误次数过多;
    10. 找人代付;
    11. 弱网状态下,连续点击支付功能功能,会不会支付多次;
    12. 有优惠券、折扣、促销价进行结算是否正确;
    13. 不同终端上支付:包括PC端的支付、笔记本电脑的支付、平板电脑的支付、手机端的支付等;
    14. 不同的支付方式:银行卡网银支付、支付宝支付、微信支付等;
    15. 支付失败后,再次支付。
  • 从性能方面考虑:

    1. 多个用户并发支付能否成功;
    2. 支付的响应时间;
  • 从安全性方面考虑

    1. 使用Fiddler拦截订单信息,并修改订单金额,或者修改订单号,(下两个订单A,B,付款时拦截订单B,并把订单B的订单号改为A订单的订单号)无法完成支付;
  • 从用户体验方面考虑

    1. 是否支持快捷键功能;
    2. 点击付款按钮,是否有提示;
    3. 取消付款,是否有提示;
    4. UI界面是否整洁;
    5. 输入框是否对齐,大小是否适中等。
  • 兼容性

    1. BS架构:不同浏览器测试。

购物车怎么测试?

  • 功能测试

    1. 未登录时:将商品加入购物车,页面跳转到登录页面,登录成功后购物车数量增加。
    2. 登录后:
      • 所有链接是否跳转正确;
      • 商品是否可以成功加入购物车;
      • 购物车商品总数是否有限制;
      • 商品总数统计是否正确;
      • 全选功能是否可用;
      • 删除功能是否可用;
      • 价格总计是否正确;
      • 商品文字太长时是否显示完整;
      • 购物车中下架的商品是否有标识,是否还能支付;
      • 新加入购物车商品排序(添加购物车中存在的店铺的商品和购物车中不存在的店铺的商品);
      • 是否支持快TAB、ENTER等快捷键;
      • 商品删除后商品总数是否减少;
      • 收藏功能是否可用;
      • 购物车结算功能是否可用。
  • 兼容性测试
    1. BS架构:不同浏览器测试,比如:IE,火狐,谷歌,360这些。
    2. APP:在主流的不同类型,不同分辨率,不同操作系统的手机上测试,华为,vivo,oppo等
  • 用户体验测试
    1. 删除商品是否有提示;
    2. 是否支持快捷键功能;
    3. 是否有回到顶部的功能;
    4. 商品过多时结算按钮是否可以浮动显示;
    5. 购物车有多个商品时,能不能只对单个商品结算;
    6. 界面布局、排版是否合理;
    7. 文字是否显示清晰;
    8. 不同卖家的商品是否区分明显。
  • 性能测试
    1. 打开购物车页面要多长时间
  • 安全性测试
    1. 加入购物车时,抓包拦截数据

搜索功能怎么测试?

  • 功能方面的测试:

    1. 搜索单个字,词语,句子,检索到的内容是否准确,链接是否准确
    2. 长度:例如输入框支持100字符, 那需要测试100字符、101字符,最大长度的显示是否正常;
    3. 哪些是支持的字符类型:数字、字母、汉字、字符!@!#、特殊字符;
    4. 是否支持换行;
    5. 字符串前后中带空格,前后的空格是否过滤, 中间的空格是否保留
    6. 全角半角的字母、数字
  • 性能方面的测试
    1. 点击搜索按钮后,搜索结果多长时间能够显示
    2. 进入搜索页面需要多久
  • 安全性方面的测试
    1. 能否防止SQL注入攻击,否防止XSS攻击
  • 用户体验测试:
    1. 页面布局是否合理,输入框和按钮是否对齐
    2. 输入框的大小和按钮的长度,高度是否合理
    3. 快捷键:能不能全选,部分选择,复制剪切粘贴是否可用,粘贴超过最大长度的字符串怎么显示,table键盘是否可用;
  • 兼容性测试
    1. BS架构:不同浏览器测试,比如:IE,火狐,谷歌,360这些。
    2. APP:在主流的不同类型,不同分辨率,不同操作系统的手机上测试,华为,vivo,oppo等

文件上传怎么测试?

  • 功能测试

    1. 选择符合要求的文件,上传--------上传成功;
    2. 上传成功的文件名称显示----------显示正常(根据需求)
    3. 查看,下载上传成功的文件--------上传的文件可查看或下载
    4. 删除上传成功的文件-------------可删除
    5. 替换上传成功的文件-------------可替换
    6. 上传文件是否支持中文名称--------根据需求而定
    7. 文件路径是否可手动输入----------根据需求而定
    8. 手动输入正确的文件路径,上传-----上传成功
    9. 手动输入错误的文件路径,上传-----提示,不能上传
  • 文件大小测试
    1. 符合格式,总大小稍小于限制大小的文件------上传成功
    2. 符合文件,总大小等于限制大小的文件--------上传成功
    3. 符合文件总大小稍大于限制大小的文件--------在上传初提示附件过大
    4. 小为0kb的txt文档-----------------------不能上传
  • 文件名称测试
    1. 文件名称过长。Win2000标准:255个字符(指在英文的字符下),如果是中文不超过127个汉字-----提示过长
    2. 文件名称达到最大长度(中文,英文或混在一起)上传后名称显示,页面排版-----------页面显示正常
    3. 文件名称中包含特殊字符-------------根据需求而定
    4. 文件名全为中文--------------------根据需求而定
    5. 文件名全为英文--------------------根据需求而定
    6. 文件名为中、英混合-----------------根据需求而定
  • 文件格式测试
    1. 上传正确格式-----------------上传成功
    2. 上传不允许的格式--------------提示不能上传
    3. 上传rar,zip等打包文件(多文件压缩)---------根据需求而定
  • 安全性测试
    1. 上传可执行文件(exe文件)-----------------根据需求而定
    2. 上传常见的木马文件------------------------提示不能上传
    3. 上传时服务器空间已满----------------------有提示
  • 性能测试
    1. 上传时网速很慢(限速)-----------------当超过一定时间,提示
    2. 上传过程断网--------------------------有提示是否上传成功
    3. 上传过程服务器停止工资------------------有提示是否上传成功
    4. 上传过程服务器的资源利用率---------------在正常范围
  • 界面测试
    1. 界面美观性、易用性(键盘和鼠标的操作、tab跳转的顺序是否正确)----------显示正常(根据需求)
    2. 按钮文字是否正确--------------正确
    3. 正确/错误提示的文字是否正确---------------正确
    4. 说明性文字是否正确-----------------------正确
  • 其他测试
    1. 有多个上传框时,上传相同名称的文件---------------根据需求而定
    2. 上传一个正在打开的文件-------------------------可以上传
    3. 文件路径是手工输入的是否限制长度----------------限制一定的长度
    4. 上传过程中是否有取消正在上传文件的功能-----------有
    5. 保存时有没有已经选择好,但没有上传的文件-----------提示上传
    6. 选择好但是未上传的文件是否可以取消选择------------可以取消选择

登录功能怎么测试?

  • 功能方面的测试:

    1. 输入正确的用户名和密码,点击提交按钮,验证是否能正确登录,能否能跳转到正确的页面
    2. 输入错误的用户名, 验证登录失败,并且提示相应的错误信息
    3. 输入错误的密码, 验证登录失败,并且提示相应的错误信息
    4. 用户名为空, 验证登录失败,并且提示相应的错误信息
    5. 密码为空, 验证登录失败,并且提示相应的错误信息
    6. 用户名和密码都为空,点击登陆
    7. 用户名和密码前后有空格的处理
  • 性能方面的测试
    1. 打开登录页面,需要多长时间
    2. 输入正确的用户名和密码后,登录成功跳转到新页面,需要多长时间
  • 安全性方面的测试
    1. 密码是否在前端加密,在网络传输的过程中是否加密
    2. 用户名和密码的输入框,能否防止SQL注入攻击
    3. 用户名和密码的输入框,能否防止XSS攻击
    4. 错误登陆的次数限制(防止暴力破解)
    5. 是否支持多用户在同一机器上登录
    6. 一个用户在不同终端上登陆
    7. 用户异地登陆
  • 用户体验测试:
    1. 页面布局是否合理,输入框和按钮是否对齐
    2. 输入框的大小和按钮的长度,高度是否合理
    3. 是否可以全用键盘操作,是否有快捷键
    4. 输入用户名,密码后按回车,是否可以登陆
    5. 牵扯到验证码的,还要考虑文字是否扭曲过度导致辨认难度大,考虑颜色(色盲使用者),刷新或换一个按钮是否好用
  • 兼容性测试
    1. BS架构:不同浏览器测试,比如:IE,火狐,谷歌,360这些。
    2. APP:在主流的不同类型,不同分辨率,不同操作系统的手机上测试,华为,vivo,oppo等

还款功能怎么测试?

  • 功能:
  1. 正常还款流程
  2. 逾期还款
  3. 不同的还款账户
  4. 余额不足还款
  5. 弱网状态下,连续点击还款按钮
  6. 弱网状态,或系统不稳定,支付服务方未把支付结果返回给下单发起方(如果发生这种问题,结果是,钱扣了,还款状态未发生变化)
  7. 金额不输,为0,为负数
  8. 提前还款
  9. 第三方还款
  • 性能:
  1. 还款的响应时间是否过长
  • 用户体检:
  1. 系统提示是否容易理解
  2. 界面是否友好,输入框是否对齐,按钮大小是否适中,是否有错别字等
  • 安全性:
  1. 是否能防止SQL注入,防XSS攻击
  2. 还款金额是否会被拦截篡改
  3. 还款密码等敏感信息是否加密
  • 兼容性:
  1. BS架构的系统,要考虑不同浏览器的兼容性
  2. APP:考虑在不同分辨率,不同操作系统,不同类型的手机的兼容性

订单怎么测试?

订单怎么测试?(主要测试订单的状态变化)

我们系统的订单生成的流程是这样子的,用户下单后,系统会在用户端和卖家端生成一个待付款的订单,同时在数据库也会生成一个待付款的订单;当用户付款之后,用户端显示待发货状态,卖家端显示已付款待发货状态,订单在数据库的状态为待发货,产品相应的库存量会减少,用户的账户金额减少相应的金额;当卖家发货后,用户端和卖家端的订单状态都显示为配送中,数据库中的订单状态也同时发生变化;当用户确认收货后,订单状态会显示为已完成,待评价状态,数据库中的订单状态也同时发生变化,买家支付的款项会打入到卖家的账户;当用户评论完后,订单状态显示为已结束,数据库中的订单状态也同时发生变化。这是一个正常的流程,我们测试的时候,要优先把这个流程测试通过。

然后再考虑用户的其他使用场景,比如:

  1. 用户下单后,取消订单;
  2. 下单后,一直不付款,检查订单超时不付款的场景下,会不会自动取消订单;
  3. 在订单快超时时,付款;
  4. 下单后,在不同的终端登录,一端取消订单,同时一端对该订单进行付款;
  5. 弱网状态下,多次点击提交订单按钮,检查是否会生成多个订单;
  6. 用户付款后,申请退款,买家端的订单状态为退款申请中,卖家端显示为退款审核;申请退款通过后,订单状态为已关闭状态,买家收到退还的金额;卖家拒绝退款,订单状态为待发货状态;卖家超时不处理退款申请,自动退款,订单自动设置为已退款状态,买家收到退还的金额;
  7. 当卖家发货后,买家申请退款,买家端的订单状态为退款申请中,卖家端显示为退款审核;申请退款通过后,订单状态为已关闭状态,买家收到退还的金额;卖家拒绝退款,订单状态为待发货状态;卖家超时不处理退款申请,自动退款,订单自动设置为已退款状态,买家收到退还的金额;
  8. 买家收货后,买家申请退款/退货,买家端的订单状态为退款申请中,卖家端显示为退款审核;申请退款通过后,订单状态为已关闭状态,买家收到退还的金额;卖家拒绝款/退货,订单状态为已确认收货状态;卖家超时不处理退款/退货申请,自动退款,订单自动设置为已退款状态,买家收到退还的金额;
  9. 买家长时间不确认收货,系统自动确认收货,系统自动设为好评,订单状态为已结束,卖家收到买家的货款;
  10. 收货后,超时不评论,系统自动设为好评,订单状态为已结束。
    这些是功能测试的场景,每个场景,我们都要检查数据库对应订单的数据变化。
  • 用户体验:
  1. 订单界面是否整洁,清晰,文字大小是否适中,订单编号是否能复制;
  2. 下单,取消订单,申请退款等功能是否有响应的提示,提示是否合理;
  3. 超时时长是否有倒计时提示;
  4. 只对订单的部分商品进行发货,订单里的商品发货状态是否分开展示;
  5. 是否支持Enter,tab等快捷键。
  • 安全性:
  1. 使用Fiddler,检查是否能拦截篡改修改订单的信息。
  • 兼容性:
  1. web端,在不同的浏览器,比如:谷歌,IE,火狐,360上测试;
  2. app端,在主流的不同的机型,不同的分辨率,不同的操作系统的手机上进行测试,比如:xxx;
  • 性能:
  1. 多用户并发下单;
  2. 提交订单,取消订单,申请退款的响应时间。
  • 可靠性:
  1. 多用户长时间运行提交订单功能。

自动化测试

举例来说一下你的自动化测试是怎么做的?

参考答案:就拿简历上的xxx项目来说吧,在编写脚本前,我们会对系统进行评估,确认这个系统可不可以实现UI自动化,如果可以的话,就筛选出能实现自动化测试的用例,一般优先把冒烟测试用例的转为成脚本。我们是用selenium工具来实现自动化,采用python脚本语言,基于unittest框架进行用例的编写。比如,下单这个功能的脚本,我们是这样做的:首先,我们会构建一个测试工程,测试工程包含testcase,主要用来存放测试用例,report用来存放测试报告,其次我们会把用例中公共的部分封装到public中,最后用runAllCase的python文件运行项目自动化用例,脚本调试完后,我们会用jenkins持续集成工具,设置脚本每天晚上10点跑一遍脚本,跑完后生成html格式的自动化测试报告。

自动化脚本失败的原因:

  1. 可能是测试环境的网络不稳定;
  2. 开发修改了代码没通知到测试人员修改脚本;
  3. 开发引入了新的问题。

测试脚本用到了哪些技术?

参考答案:元素定位,表单切换,模块调用,JS定位等等,脚本是基于python自带的unittest单元测试框架,采用了模块化方式编写,把复用性高的操作封装到公共模块中,如果脚本需要用到对应的操作,直接调用就可以了,如果元素发生变化,只需要调整元素封装的代码就可以了,提高测试用例的可维护性。

xpath和CSS定位方式的区别:

1、语法不一样;
2、CSS定位比较稳定。

脚本怎么组织的?(编写自动化脚本,你的思路是什么?)

参考答案:构建一个测试工程,测试工程包含testcase,主要用来存放测试用例,report用来存放测试报告,其次我们会把用例中公共的部分封装到public中,最后用runAllCase的python文件运行项目自动化用例。测试脚本使用的是python的unittest单元测试框架组织管理,将所有测试脚本通过单元测试框架组织起来运行,这样做的好处是,维护起来方便,可以生成测试html格式的测试报告,报告包括:测试用例,通过数,失败数。

自动化率多少?

一般是30%到40%,这个没有固定的,我们是优先将优先级高的测试用例,比如,冒烟测试的测试用例转换成自动化脚本的,后面有时间的时候再不断补充,能写多少写多少。

自动化脚本的通过率是多少?(注意这个题目的意思)

参考答案:这个说不准,如果没有什么异常情况,自动化脚本都是100%运行通过;如果异常情况比较多,比如出现测试环境不稳定,或者开发修改了代码没通知到测试人员及时修改脚本,又或者开发引入了新的问题等等,自动化脚本通过率可能80%都不到。

用那个方法判断元素是否显示

is_displayed()

你曾经都写过多少自动化测试用例?

这个具体没有算过。但是只要有时间,模块稳定的功能都会写。就拿上个项目来说,自动化测试用例大概写了将近有100-120条这样子吧。

python3 的数据类型有哪些?

int (整型)
float (浮点型)
str(字符串)
List(列表)
Tuple(元组)
Set(集合)
Dictionary(字典)

不可变数据(四个):int (整型)、float (浮点型)、str(字符串)、Tuple(元组)、Set(集合);
可变数据(两个):List(列表)、Dictionary(字典)。

面:unittest框架了解吗?

参考答案:unittest框架,由setUp()–环境预置,testCase()— 测试用例 tearDown()----环境恢复,三大部分组成,unittest框架可组织执行测试用例,并且提供丰富的断言方法,判断测试用例是否通过,最终生成测试结果。

怎样用python连接mysql数据。

参考答案:我们之前主要是用python语言来写web端的自动化测试脚本,连接数据库的话,我们主要使用pymysql这个模块来进行连接的。一般在进行完自动化测试之后,我们会连接上数据库,将数据进行清除

用python做过接口测试自动化测试吗?

参考答案:我们之前主要是用python语言来写web端的自动化测试脚,接口是用Jmeter来做的,用python写接口的脚本也在网上学习过,主要使用到requests模块,但是工作中没用用过,到时候工作需要的话,再学一下应该没问题。

元素定位失败的原因

  1. 页面的元素未加载完成
  2. 元素的属性值不唯一
  3. 元素的属性值是动态值
  4. 元素在另外一个表单
  5. 元素在另外一个页面

自动化脚本,如何切换不同的浏览器

参考答案:使用对应的浏览器驱动,然后在脚本中更换不同的浏览器。

你的python水平很一般啊?(遇到这种否定你的问题,一定不能虚!)

参考答案:我现在掌握的python知识,做ui层的自动化测试是可以的,代码的封装,调用这些都没问题;我一般是会做,但不是很会用文字描述出来,我以注意到这点,现在也在加强提升自己的总结能力。
PS—重点强调:凡是遇到被面试官否定的,都要想办法怼回去,输也要输得精彩些,但是,怼回去的时候,要注意语气,要有礼有节,不卑不亢。

python怎么定义一个函数,怎么定义一个类

def 函数名:函数体
class 类名:属性方法

有些元素,在谷歌浏览器上能定位,在火狐浏览器上定位失败,是什么原因呢?

参考答案:因为不同浏览器的内核不一样,他们的CSS样式不一样。

如何提高selenium脚本的执行速度?

  1. 提高网速;
  2. 少用sleep,多用隐式等待或显式等待。
  3. 提升电脑配置

元素定位的方式有哪些

d.find_element_by_id('id的值')
d.find_element_by_name('name的值')
d.find_element_by_class_name('class的值')
d.find_element_by_tag_name('标签名')
d.find_element_by_link_text('完整的文本链接')
d.find_element_by_partial_link_text('部分的文本链接')
d.find_element_by_css_selector('css表达式')
d.find_element_by_xpath('xpath表达式')
js定位

如何切换iframe

switch_to.frame()

如何切换窗口

switch_to.window()

鼠标悬停的方法是什么

鼠标悬停用到ActionChains类提供的move_to_element方法

如何定位下拉框

需要导入Select类,可以使用下标、值和文本定位

如何获取弹出警告框的text

switch_to.alert.text

什么样的项目适合做自动化

项目周期长,版本多,界面元素稳定的项目

selenium如何做兼容性测试

使用对应的浏览器驱动,然后在脚本中更换不同的浏览器。

为什么会生成HTML报告

使用了HTMLTestRunner第三方工具包来实现的

脚本运行出错,应该怎样定位,说出分析过程

运行结束之后我们会得到一个测试报告,我们根据测试报告先定位一下是脚本的原因还是程序的原因,一般来说脚本的原因在报告中都会显示出哪一行代码出错了,如果是程序的原因通常来说都是断言的问题。

如果系统有验证码,怎么做自动化?

  1. 去掉验证码。
  2. 设置万能验证码。
  3. 用python调用OCR模块,自己写代码来识别。这种方法可以识别出简单的验证码。
  4. 调用第三方平台提供的接口进行识别。比如:斐斐打码,尖叫数据这些平台接口。

setUp(),tearDown()和setUpClass(),tearDownClass()的区别:

参考答案:当测试用例有多个,setUp()和tearDown()就会被执行多次;不管测试用例有多少个,setUpClass()和tearDownClass()只会被执行一次。

python的第三方模块/标准库有哪些?

time,random,unittest,selenium,HTMLTestRunner

python的pass语句的作用是什么?

参考答案:占位符,当方法没有内容时,防止出现语法错误。

自动化写过哪些模块的脚本?

参考答案:主要是把冒烟测试的用例转化为脚本,比如,我这个xx商城系统,做自动化的模块有后台的上架商品,订单查询,添加团购活动,促销活动,前台的搜索商品,添加商品到购物车,下单等等。

元素的属性值是动态变化的,怎么定位这个元素?

参考答案:如果元素有属性值是动态变化的,我们就不要使用这个属性进行定位;我们可以使用这个元素的非动态变化,并且是唯一的值属性进行定位;也可以使用xpath或者css,使用层次+属性的方式定位。

webdriver的原理是什么?

参考答案:浏览器的驱动,接收客户端发过来的指令(指令就是我们的脚本),浏览器的驱动根据接收到的指令,驱动浏览器工作。

你们是怎么检查自动化的结果是不是正确的?

参考答案:我们会用unittest单元测试框架提供的断言方式来检查实际结果和预期结果是否一致,常用的断言方式有assertEqual(),assertIn(),还有一些其他的,不常用就没记了。

怎么样提升自动化脚本成功率

  1. 在容易失败的地方,加上sleep
  2. 尽量定位一些稳定的元素
  3. 使用try…except多中方式定位

run_all_case中有哪些内容?

run_all_case具体的内容不太记得了,一般都是直接使用的,一般需要修改的是测试报告的路径,测试用例的路径,还有用例的匹配规则。

自动化的优点和缺点?

自动化的优点的话,可以提升测试的效率,比如我们之前是将冒烟测试的用例转换成自动化用例。可以节省自己的测试时间。

缺点的话,可能他的执行速度比较慢,其次他对于测试人员的代码能力需要一定要求。

unittest单元测试怎么安装的?

参考答案:不需要安装,是python自带的,直接通过import 关键字引用就可以了。

pytest了解吗?

参考答案:也是python的一个单元测试框架,它的用法比unittest框架复杂些。自动化测试我们一般是基于unittest框架来做的,pytest用的少,以后工作需要,我业余时间学习一下,很快上手。

po(page object:页面对象)设计模式了解吗?

参考答案:po还是了解的。po是web自动化测试目前最佳的一种实践方式,简单来说就是类和类之间的封装和调用。
包括基础类、页面类、用例层等部分。目前正在往这个方面进阶脚本。

禅道搭建手册?

在SVN中07_测试执行\禅道\安装包可以查看到禅道安装包

xampp-win32-1.7.7-VC9.zip复制到C盘
注意:必须是C盘的根目录下

直接右键,解压到当前文件夹

解压之后会得到一个xampp的文件夹

进入xampp文件夹中的htdocs文件夹
如下是我的路径,仅供参考
C:\xampp\htdocs

将安装包文件夹中的ZenTaoPMS.8.0.1.zip复制进来

复制进来之后,跟之前一样,解压到当前文件夹

解压完成后,回到上级目录,也就是xampp目录
然后拉倒最下面

双击xampp-control.exe文件

依次点击这两个start(apache和mysql的)
注意:依次点击,先等前一个running,再点击下一个

至此搭建完成,接下来就是禅道的安装了

打开浏览器输入网址
http://localhost/zentaopms/www/

开始安装

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jEj0XtZp-1617696547036)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230165903675.png)]

一直下一步,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TUTeTjvF-1617696547037)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230165914191.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kb8RjDZi-1617696547039)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230165934119.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SenD1jM9-1617696547039)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230165951049.png)]

禅道的基本使用

使用管理员账号可以去创建产品、添加人员等等

  • 创建产品
  • 给产品添加模块
  • 自定义严重程度
  • 添加用户
创建产品

进入产品

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QbRkWFDK-1617696547040)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170107589.png)]

添加产品
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tfCnNygH-1617696547041)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170119352.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AyiagD9s-1617696547042)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170138466.png)]

切换所负责的产品
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sXUvCXMj-1617696547043)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170151492.png)]

给产品添加模块

切换到需要添加模块的产品,点击维护模块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dnqOSUYa-1617696547043)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170203405.png)]

添加模块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZqKROGOC-1617696547045)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170215631.png)]

添加子模块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VKupqBx7-1617696547046)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170229638.png)]

自定义严重程度

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pLDCitNx-1617696547046)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170243990.png)]

添加用户

进入添加用户

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UV0ZQV0l-1617696547047)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170301123.png)]

添加一个用户

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VPa31kKH-1617696547048)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170312163.png)]

基于Python3_Selenium的自动化

python3的安装

进入Python官网

根据操作系统进行下载选择

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dyAm1XvK-1617696547049)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170514085.png)]

根据 自己电脑位数下载64位和32位

下载后会得到python-3.7.4-amd.exe

双击该文件进行安装

点击customize installation

直接next

选择advanced options,前五项勾选并且改路劲

然后点击install进行安装

找到Python安装目录

在开始处输入idle

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-75uHcdSq-1617696547049)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170748681.png)]

鼠标右键 打开文件位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l7iKdoG0-1617696547050)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170802641.png)]

检查Python的环境变量

在dos界面输入命令python -V注意V需要大写

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8LONgDqt-1617696547050)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230170824258.png)]

注意如果提示Python不是内部或外部命令也不是可运行的程序则需要添加环境变量至Path

先找到Python的安装目录,在dos界面输入如下命令
setx "Path" "Python的安装目录;%Path%;" /m

比如我的Python安装在C:\Python中,那么我的命令则是
setx "Path" "C:\Python;%Path%;" /m

python基础

Python的脚本后缀名是以.py结尾的

执行Python代码

在dos界面,输入命令
python 需要执行的py文件

输出/打印内容 print()

print('李四')
print(5)
  • 修改print() 结束符

print默认是以\n换行为结尾
如果需要修改print的结束符,在print最后增加,end=‘以什么结尾’
print(需要输出的内容,end=’’)

print('hello',end='>>>>>>>>>')
print('world',end='\t')
print('python',end='<<<<<<<<<<<<')

数据类型

在Python3中基本的数据类型有三个

  • 字符串 str
  • 整型 int
  • 浮点型 float

字符串使用引号引起来
注意一下必须是用成对成对的引号引起来,也就是以什么引号开头,就要以什么引号结尾。

'张三'
"张三"
'''张三'''
"""张三"""
  • 数据类型之间的转换

str() 转换成字符串 int()转换成整型 float()转换成浮点型

a = '5.6'
a = int(a)
print(type(a))
print(a)
  1. int类型 和float类型可以转换成str数据类型
  2. str类型不一定可以转换成int 或者 float类型
  3. int 和 float 可以互相转换

字符串常用方法

  • 获取字符串的长度 len()
lenth = len(a)
print(lenth)
  • split()分割字符串
a = '23462346@qq.com'# 切割字符串,将字符串切割成列表
qqnum = a.split('@')
print(qqnum)
  • 统计字符串中字符的个数
a  ='hello,world'
a.count('o')
  • 读取字符串的某一个字符 读取长度[下标],下标从0开始
bingo = a[3]
print(bingo)
  • 拼接 (只能够用在字符串与字符串之间)
b = 'hello,'
c = b+a
print(c)
  • 多倍运算 (只能够用在字符串与整数之间)
print(a*5)
  • 格式化输出字符串
name = '李四'
age = 18
nation = '汉族'
location = '深圳市'
msg = '你好,我是{0},我今年{1}岁,我是{2}人,来自{3}'.format(name,age,nation,location)
print(msg)
  • 转义字符
    \n >>> 换行 \t >>> tab键
# 如果我想打印出来的是"随便打\n印一\t行字符串"
print('随便打\\n印一\\t行字符串')
print(R'随便打\n印一\t行字符串')
  • 判断 in /not in ,如果成立,则返回True 否则返回False
a = 'world'
result = 'or' in a
  • and /or
# result1 = 'o' in a or 'asdb' in a
result1 = 'o' in a and 'asdb' in a
print(result1)

变量

在Python定义变量其实就是给一个值取一个名字,或者给某一个变量赋值

name='张三'

讲变量之前,我们先来看一看这一段代码,这个代码的意思就是说把张三这个字符串给到了name,把一个值(张三)赋值给一个名字(name)。变量名就像我们现实社会的名字,把一个值赋值给一个名字时,称之为变量(variable),在大多数语言中,都把这种行为称为“给变量赋值”或“把值存储在变量中”。

定义变量使用=定义,=左边的是变量名,=右边的是变量的值

变量名=变量值
  1. 在使用变量之前,需要定义变量。
  2. 变量名可以包括字母、数字、下划线,但变量名不能以数字开头。
  3. 字母可以是大写或小写,但大小写是不同的。
  4. 等号(=)是赋值的意思,左边是名字,右边是值,不可写反咯。
  5. 变量的命名理论可以取任何合法的名字,但作为一个优秀的程序员,请将尽量给变量取一个专业一点儿的名字
  6. 变量名应当避开Python的关键字/保留字

  • 删除变量 del
a = 15
del a
  • 查看变量数据类型 type()
a = 15
b = 1.5
c = '1.5'
print(type(a))
print(type(b))
print(type(c))
  • 同时定义多个变量相同的值
a = b = c = 5
print(a)
print(b)
print(c)
  • 同时定义多个变量不同的值
a,b,c = 3,4,7
print(a)
print(b)
print(c)

算术运算(只能够用在数字与数字之间)

  • 加法 +
  • 减法 -
  • 乘法 *
  • 除法 /
  • 地板除 //
  • 求余数除法 %
  • 幂运算 **
print(b+c)#加法
print(b-c)#减法
print(b*c)#乘法
print(b/c) #除法
print(b//c)#地板除 求整数部分
print(b%c)#求余数的部分
print(b**c)#幂运算 b的c次方

input() 接受用户的输入

name = input('请输入您的姓名:')
print('您输入的是{0}'.format(name))

常见比较操作符

符号 含义
== 相等/等于
<= 小于等于
>= 大于等于
< 小于号
> 大于号
!= 不等于

if…else语句

在冒号后:下一行后带有缩进,缩进是Python核心,Python就是通过缩进来控制代码的。
缩进(一个tab/四个空格) 不可以混着用.。

假设 用户名 为admin,密码为 admin123,写一个程序判断用户是否登录成功

username = input('请输入用户名')
password = input('请输入密码')if username == 'admin' and password == 'admin123':print('登录成功')print('正在进入程序。。。。')
else:print('用户名或密码错误')print('登录失败')

那如果有多个条件需要判断,则需要使用elif语句
语法:

if 条件1:条件1成立时执行
elif 条件2:条件2成立时执行
elif 条件3:条件3成立时执行
elif 条件4:条件4成立时执行
else:所有条件都不成立,才执行

比如:根据分数判断等级
81 - 100 >>>> A
60 - 80 >>>> B
40 - 59 >>>> C
0 - 39 >>>> D
不在0-100 之间 >>> 输入错误

score = int(input('请输入分数'))if 81 <= score <= 100:print('A')
elif 60 <= score <=80:print('B')
elif 40 <= score <=59:print('C')
elif 0 <= score <=39:print('D')
else:print('输入错误')

循环

  • while 循环

语法:

while 条件:循环内容
  1. 条件为True的时候,才会执行循环内容
  2. 每一次循环结束,会再次检查条件是否成立
  3. 使用while循环一定要控制好条件,否则容易出现死循环
# 定义次数为3
times = 3while times > 0:print('当条件成立时')print('执行while循环')print('每一次循环结束的时候,会再一次检查条件是否成立')times = times - 1

优化猜数字游戏

num = 8# 定义次数为3
times = 3
while times > 0:guess = int(input('请输入1-10之间的整数'))if guess == num:print('猜对了')times = -999elif guess > num:print('大了')else:print('小了')times = times - 1

1+2+3+4+…100的和

# 定义和等于0
sums = 0
num = 1 # 从1开始加
while num <=100:sums = sums + numnum = num +1
print(sums)

continue 与break

  1. continue 跳出循环,并且开始下一次的循环
  2. break 终止循环
index = 1
while index < 10:print(index)if index == 5:print('执行continue语句')continueindex = index + 1print('>>>>>>>>>>>>>>>>>>>>>>>>>')
index = 1
while index < 10:print(index)if index == 5:print('执行break语句')breakindex = index + 1print('>>>>>>>>>>>>>>>>>>>>>>>>>')

结合break与continue优化猜数字游戏

num = 8
# 定义次数为3
times = 3
while times > 0:guess = int(input('请输入1-10之间的整数'))if guess < 1 or guess > 10:print('输入错误')continueelif guess == num:print('猜对了')breakelif guess > num:print('大了')else:print('小了')times = times - 1

异常处理

try:print('这是try语句的内容')int('aaaa')print('try语句报错,就直接跳转执行except语句')
except:print('这是except语句的内容')print('只要当try语句中的内容报错了')print('才会执行except语句')try:num = float(input('请输入一个小数'))num2 = int(num+0.5)print('您输入的是{0},四舍五入后为{1}'.format(num,num2))
except:print('输入错误')

词典(键值对)

一个键(key)对应一个值(value),是一个一一对应的数据类型
词典用{}表示,词典中的每一对用,分隔开。键与值之间用:对应
key/键是唯一的

a = {'中国移动':10086,'中国联通':10010,'中国电信':10000}
  • 读取词典的内容,通过key来读取
print(a['中国移动'])# 如果读取的key不存在,会报错
print(a.get('中国移动'))# 如果读取的key不存在,则返回None
  • 判断词典中是否存在这个key 使用 in、not in
result = '中国移动' in a
print(result)result2 = 'aaaa' in a
print(result2)
  • 修改key的值
a['中国移动'] = '12345'
print(a)
  • 增加一项
a['中国铁通'] = '不知道'
print(a)
  • 删除词典某一项
del a['中国铁通']
print(a)
  • keys() 所有的键
print(a.keys())
  • values() 所有的值
print(a.values())
  • items() 所有的键值对
print(a.items())

for循环

for 循环是根据目标的元素个数来决定循环的次数
语法如下:

for 变量 in 目标:循环内容目标有多少个元素,就循环多少次
a = ['python','java','php']
for i in a:print(i)print('for循环,每一次循环会找到目标的一个元素')print('并且赋值个变量,直到所有的元素都找完')

通常配合for循环一起使用的就是range()函数

range()三种用法

range(10) # 表示生成0,1,2,3,4,5,6,7,8,9
range(1,10) # 表示生成1,2,3,4,5,6,7,8,9
range(1,10,2) # 表示生成1,3,5,7,9

一筐球 红色有6个, 黄色有3个,每次随机拿4个球

for red in range(1,5):for yellow in range(4):if red+yellow == 4:print('红球有{0}个,黄球有{1}个'.format(red,yellow))

列表

在其他编程语言中有的称之为数组,列表是python仓库,他可以存放所有的数据。列表用[]表示,列表中的每一项用,分隔开

  • 列表用[]表示,列表中的每一项用,分隔开
a = [3,3.14,'world',5]
  • 获取列表的个数
print(len(a))
  • 读取列表的内容,用[下标]来读取
print(a[2])
  • 删除列表的元素
del a[1]
print(a)
  • 修改列表的元素
a[2] = 'hello'
print(a)
  • 往列表增加一个元素 列表.append(元素)
a.append('python')# 将python增加到列表a的尾部,一次只能增加一个元素
  • reverse 倒序排序,修改原来列表
a.reverse()
print(a)
  • 升序排序,修改原来列表
a.sort()
print(a)
  • sorted() 升序排序,不会修改原来的列表
b = sorted(a)
print(a)
print(b)
  • 倒序输出列表 [::-1]
a = [5,2,3,1,7,9,8,11,12,13,111,23,345]
a[::-1]

元组

元组是一个不可变的列,用()表示,每一项用,分隔开

a = (1,2,3,1,23)
  • 如果元组只有一个元素时,则需要在该元素后增加,
a = (2,)

访问元组元素的方法,与列表一样,通过下标访问,大部分的方法例如切片等等都可以使用

a = (1,2,3,1,23)
print(a[2])

集合

集合 {} 里面的每一项用,分隔开
集合里面的元素是唯一的

c = {3,4,3,4,1,2,3,4,12,3,4,5}
print(c)
  • 增加元素
c = {1,2,1,2,3,54,2}
c.add(5)# 增加一个元素
c.update([1,2,3,4,5,6,11,12,13,14,15])#增加多个元素
print(c)

函数和类

函数

什么是函数呢?数学上的函数,是指给定一个输入,就会有唯一输出的一种对应关系。编程语言里的函数跟这个意思差不多,但也有不同。就是你编写了一些语句,为了方便使用这些语句,把这些语句组合在一起,给它起一个名字。使用的时候只要调用这个名字,就可以实现语句组的功能了。它有可能需要输入,有可能会返回输出。

  • 创建函数
    语法:
def 函数名称():函数实现过程函数实现过程

比如创建一个hello函数

def hello():print('这是我创建的第一个函数')print('一个叫做hello的函数')print('我现在有些激动')print('函数只要被调用才会执行')

注意,函数只有调用才会执行

hello()#调用函数
  • 创建一个有参数的函数
def add(num1,num2):print('第一个参数是:{0}'.format(num1))print('第二个参数是:{0}'.format(num2))

有参数的函数,在调用时,一定要传递参数

add(5,16)# 顺序传参
add(num2=15,num1=7)# 关键字传参
  • return 函数返回值
def login(username,password):if username =='admin' and password =='admin123':return '登录成功'else:return '登录失败'result = login('admin','admin123')
print(result)

相信我们之前百度也好通过其他途径也好,应该都听说过Python是一个面向对象的语言,python处处都是对象,但是我们并不知道什么是对象。简单的来说对象=属性+方法,打个比方,把一个人当做对象,我们就可以从这两个方面去描述这个人。

  1. 属性:即静态的特征,例如,身高155cm,体重200斤。
  2. 方法:即动态的行为,例如开车、吃饭等。

在Python中的对象也是如此,如果把计算器写成代码会是如下情况:

class calc():name='超级计算器'def add(self,a,b):print(a+b)

看到这个代码没,这个代码就是定义了对象的属性和方法,我们将这个定义的过程叫做类(class)。就叫做类的实例对象也叫实例。

  • 属性,在代码层面就是变量、
  • 方法,就是在类里面定义的函数。

我们需要使用类来创建一个真正的对象,而这个对象

说到这里,如果大家还是不明白,你可以这样想我们造房子需要图纸,但是仅仅有个图纸你也住不进去啊,图纸只告诉我们房子长成什么样子,但图纸不是真正的房子,我们需要根据图纸真金白银的造房子才能住进去。另外我们根据图纸是可以造出很多房子来的。这就跟我们的类一样,类就像我们的图纸,而我们创建的类的实例,就是一个又一个的房子。

对象

好了说了这么多,创建一个对象,也叫类的实例化其实so easy

tt = calc()#这样就创建了calc类的实例化

注意类名后面带着(),如果需要调用对象的方法,使用点操作符(.)即可

tt = calc()
tt.add(5,2)

self是什么?

我们应该发现了,每一个方法下都会有一个self参数,self到底是什么呢?如果我们之前把类比作图纸,那么由类实例化后的对象才是真正可以住人的房子,我们可以根据图纸建造成千上万的房子,但是每一个房子都有各自的主人,self这里就相当于门牌号,有了self,每个主人才能正确的进入自己的房子
切记:所有方法的第一个参数必须是self,但是使用时,无需传参!
我们需要注意的东西:
• 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
• 类变量:定义在类中的变量,我们叫做类变量
• 实例化:创建一个类的实例,类的具体对象。
• 方法:类中定义的函数。
• 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

单继承
比如我现在实现一个会员等级功能

class vip1():name = '初级VIP'def download(self):print('下载速度提升10%')

现在我想增加一个vip2的等级,要求拥有VIP1的所有特权外,上传速度还能提升10%
这个时候我们可以用到继承

class类名(被继承的类):pass#pass为占位符,表示什么都不做
class vip2(vip1):def upload(self):print('上传速度提升10%')

被继承的类我们称之为父类,继承者我们叫做子类,一个子类可以继承父类的全部属性和方法。

我们可以对继承过来的方法与变量进行重新定义。

class vip3(vip2):name = '高级VIP'def download(self):print('下载速度提升20%')

模块

Python自带了功能丰富的标准库,另外还有数量庞大的各种第三方库。使用这些功能的基本方法就是使用模块,通过模块,可以重用别的程序中的代码。模块可以理解为是一个包含了函数和变量的py文件。在你的程序中引入了某个模块,就可以使用其中的函数和变量。

使用模块的方式

  • import 模块名
  • from 模块 import 方法

time模块

time模块提供了很多方法,先来看这两个

  • sleep(n)
    n为具体的数字,表示休眠多长时间
  • time()
    没有参数,返回当前时间戳
import time
start_time = time.time()
time.sleep(5)
end_time = time.time()
print('开始时间为{0}'.format(start_time))
print('结束时间为{0}'.format(end_time))

random模块

random模块同样也有很多方法,先看这两个

  • randint(a,b)
    a,b为两个整数,会返回一个a-b之间的随机的整数
  • choice(seq)
    seq为一个由多个元素组成的数据,会从该数据中随机选取一个元素
import random
bingo = random.randint(1,10)
print(bingo)
a =['小米','华为','OPPO','vivo']
bingo2 = random.choice(a)
print(bingo2)

PyMySQL模块

安装

pymysql 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb。
因此在操作数据库前安装pymysql第三方库
在dos界面输入命令python -m pip install pymysql

数据库信息

演示数据库如下:

名称 内容
数据库ip 120.77.212.195
端口 3306
数据库名称 brtctest
用户名 admin
密码 admin123

表名stu字段如下

字段 含义 约束
id 学员id number,主键
name 学员姓名 varchar
age 学员年龄 number
nation 学员民族 varchar,默认汉族

数据库操作

  • 增/删/改数据
import pymysql# 打开数据库连接
db = pymysql.connect("数据库IP","用户名","密码","连接的数据库",数据库端口)# 使用cursor()方法获取操作游标
cursor = db.cursor()# SQL 插入语句
sql = "需要执行的sql语句"
# 执行sql语句
cursor.execute(sql)# 提交变动的数据
db.commit()
# 回滚变动的数据
db.rollback()# 关闭数据库连接
db.close()
  • 查询数据

查询数据与之前的增删改无任何太大的区别,主要有如下区别:

  1. 不需要commit或者rollback
  2. 查询数据会有查询的结果返回

主要用到如下方法:

方法 作用
fetchone() 获取一条结果
cursor.fetchall() 获取所有结果
cursor.rowcount 获取结果有多少条
# 操作mysql数据库,需要导入pymysql
import pymysql# 先连接数据库
# pymysql.connect(数据库ip地址,用户名,密码,数据库名称,端口)
db =pymysql.connect('120.77.212.195','admin','admin123','brtctest',3306)# 创建数据库操作游标
cs = db.cursor()sql = "select * from stu"执行sql语句
cs.execute(sql)# 通过rowcount 计算出查询了多少条数据
all_line = cs.rowcount
print(all_line)# 读取全部查询结果
result = cs.fetchall()
for i in result:print(i)读取下一条数据
one = cs.fetchone()
two = cs.fetchone()
three = cs.fetchone()
print(one)
print(two)
print(three)db.close()

Requests模块

python 做接口测试

用到模块 requests

安装模块 python -m pip install requests

  1. 由于pip命令可能安装失败所以有时我们要通过下载第三方库文件来进行安装。
  2. 在github上的地址为:https://github.com/requests/requests
  3. 下载文件到本地之后,解压到python安装目录。
  4. 然后在dos界面cd到该目录,在此处运行命令行并输入:python setup.py install 即可。

requests发送请求

方法 解释
requests.get() 获取html的主要方法
requests.post() 向html网页提交post请求的方法
requests.delete() 向html提交删除请求
requests.put() 向html网页提交put请求的方法
requests.head() 获取html头部信息的主要方法
requests.patch() 向html提交局部修改的请求
  • 发送请求示例
import requests
r = requests.get(url)#发送get请求
r = requests.post(url)#发送post请求
# 其余请求的发送方式一样,故不再演示

在发送请求时,除了url之外,还有许多参数,一一来看

  • url

url,请求的路径,表示这个请求发送到哪里去

import requests
myurl = 'http://brtc.imsam.cn'r = requests.get(url=myurl)
  • params

跟url一起发送的参数(以字典方式传递),通常使用在get请求中

import requests
myurl = 'http://brtc.imsam.cn'kv = {'username':'张三','age':'18'}r = requests.get(url=myurl,params=kv)
  • data

字典,与params不同的是,data提交的数据并不放在url链接里,通常在post请求中使用

import requests
myurl = 'http://brtc.imsam.cn'kv = {'username':'张三','age':'18'}r = requests.post(url=myurl,data=kv)
  • json

以json的方式发送请求数据,通常也用在post请求中

import requests
myurl = 'http://brtc.imsam.cn'kv = {'username':'张三','age':'18'}r = requests.post(url=myurl,json=kv)
  • headers

定制请求的头部信息

import requests
myurl = 'http://brtc.imsam.cn'
kv = {'username':'张三','age':'18'}
hd ={"User-Agent":" Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"}r = requests.get(url=myurl,params=kv,headers=hd)
  • files

发送带文件的请求

import requests
myurl = 'http://brtc.imsam.cn'upfile = {'file': open('文件路径', 'rb')}r = requests.post(url=myurl,files=upfile)
  • timeout

设置超时时间

import requests
myurl = 'http://brtc.imsam.cn'kv = {'username':'张三','age':'18'}r = requests.post(url=myurl,data=kv,timeout=0.01)
  • proxies

设置访问代理

import requests
myurl = 'http://brtc.imsam.cn'
kv = {'username':'张三','age':'18'}
proxy = {"http": "http://10.10.1.10:3128","https": "https://10.10.1.100:4444"}
r = requests.post(url=myurl,data=kv,proxies=proxy)

如果代理需要用户名和密码,则需要这样:

import requests
myurl = 'http://brtc.imsam.cn'
kv = {'username':'张三','age':'18'}
proxy = {"http": "http://用户名:密码@10.10.1.10:3128","https": "https://用户名:密码10.10.1.100:4444"}
r = requests.post(url=myurl,data=kv,proxies=proxy)
  • 自动带上cookie
s = requests.Session()
r = s.get('url')

响应内容

import requests
myurl = 'http://brtc.imsam.cn'kv = {'username':'张三','age':'18'}r = requests.post(url=myurl,data=kv)r.text# 以字符串方式返回响应内容
# 更多响应内容如下
响应 含义
r.encoding #获取当前的编码
r.encoding = ‘utf-8’ #设置编码
r.text #以encoding解析返回内容。字符串方式的响应体,会自动根据响应头部的字符编码进行解码。
r.content #以字节形式(二进制)返回。字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩。
r.headers #以字典对象存储服务器响应头,但是这个字典比较特殊,字典键不区分大小写,若键不存在则返回None
r.status_code #响应状态码
r.json() #Requests中内置的JSON解码器,以json形式返回,前提返回的内容确保是json格式的,不然解析出错会抛异常
r.raise_for_status() #失败请求(非200响应)抛出异常

hashlib加密

用于加密相关的操作,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
不同算法的使用语法都是一样的。

  • 基本使用
import hashlibm = hashlib.md5()
m.update("123456".encode('utf-8'))
print(m.digest()) #2进制格式hash
print(m.hexdigest()) #16进制格式hash
  • 其余加密的演示
import hashlib
#  md5 加密展示hash = hashlib.md5()
hash.update('123456'.encode('utf-8'))
print(hash.hexdigest())#  sha1 加密展示hash = hashlib.sha1()
hash.update('123456'.encode('utf-8'))
print(hash.hexdigest())#  sha256 加密展示hash = hashlib.sha256()
hash.update('123456'.encode('utf-8'))
print(hash.hexdigest())#  sha384 加密展示hash = hashlib.sha384()
hash.update('123456'.encode('utf-8'))
print(hash.hexdigest())#  sha512 加密展示hash = hashlib.sha512()
hash.update('123456'.encode('utf-8'))
print(hash.hexdigest())

selenium环境

安装selenium

selenium对于Python而言是一个第三方的模块
Python安装第三方模块在dos界面输入命令
python -m pip install 模块名称
比如安装selenium,那么输入命令
python -m pip install selenium

看到如下字眼则表示安装成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gbhgW5GX-1617696547053)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171307750.png)]

安装浏览器(Chrome)

进入官网安装

安装相对应的浏览器驱动(driver)

  • 先查看自己安装的浏览器的版本
    直接在chrome浏览器地址栏粘贴chrome://version/即可查看到版本

  • 下载跟浏览器版本对应的驱动
    国内淘宝镜像地址

  • 点击选择跟自己版本的对应的连接
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G2ARoMYL-1617696547054)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171319612.png)]

  • 点击下载

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-on5OxpCa-1617696547055)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171331969.png)]

  • 下载后,解压到当前目录
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u561v47I-1617696547056)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171343973.png)]

  • 得到chromedriver.exe文件

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MzrEwmPF-1617696547056)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171355198.png)]

  • 进入到Python安装目录

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ccNTmIw0-1617696547057)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171408161.png)]

  • 右键打开文件位置
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M86SD7CN-1617696547057)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171422990.png)]

  • 将这个exe文件放到Python安装目录
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wv3Q0foD-1617696547058)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171433410.png)]

检查一下是否安装成功

新建一个Python文件,执行下面脚本,看是否能打开。

  • 注意脚本名称要是selenium.py
from selenium import webdriver
from time import sleep#打开谷歌浏览器,并且赋值给变量d
d = webdriver.Chrome()
d.maximize_window()# 最大化窗口# 通过get() 打开一个网址
d.get('https://www.baidu.com')
sleep(5)# 关闭当前窗口
d.close()
# 关闭所有窗口,并且关闭驱动
d.quit()

selenium定位方式

在进行web自动化之前,需要先来了解一下web页面的基本内容。
比如,如下是一张百度首页

那如果我们需要对百度页面进行操作,那么我们就需要知道他的html代码了。
我们可以鼠标选中需要操作的元素,鼠标右键,检查

这一行代码就是百度输入框的代码了

来看看这行代码

<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">

首先第一个,这个是一个html代码,那html代码中 这个代码我们称之为input标签
那在这个input标签中,有很多的属性,其中=左边的是属性名称,=右边的是属性值
所以这个html标签有id、name、class、value、maxlength等等属性

第二个,HTML标签有自己的层级关系
如图,span标签就是input标签的父标签

定位方式 定位表达式
根据id来定位 d.find_element_by_id(‘id的值’)
根据name来定位 d.find_element_by_name(‘name的值’)
根据class来定位 d.find_element_by_class_name(‘class的值’)
根据标签名定位 d.find_element_by_tag_name(‘标签名’)
根据文本链接定位 d.find_element_by_link_text(‘完整的文本链接’)
根据部分文本链接定位 d.find_element_by_partial_link_text(‘部分的文本链接’)
根据css选择器定位 d.find_element_by_css_selector(‘css表达式’)
根据xpath定位 d.find_element_by_xpath(‘xpath表达式’)

Xpath定位

  • 根据绝对路径定位
/html/body/div/form/p/label/input
/html/body/div/form/p[2]/label/input
  • 路径与属性的结合
//标签名[@属性名="属性值"]

比如说:想定位到 for=“user_pass” 的label标签
//label[@for="user_pass"]

  • 如果想同时使用多个属性去定位
    语法:
    //标签名[@属性名="属性值"][@属性名="属性值"]
    想定位到:class=“input” id=“user_pass” 的 input标签
    //input[@class="input"][@id="user_pass"]

比如:定位到 for=“user_pass” 的label标签 的 input子标签
//label[@for="user_pass"]/input

使用Xpath实现登录blog

from selenium import webdriver
from time import sleep
d = webdriver.Chrome()
d.get('http://os-201804081018/blog/wp-login.php')
d.maximize_window()
sleep(3)d.find_element_by_xpath('//label[@for="user_login"]/input').send_keys('test')
sleep(1)
d.find_element_by_xpath('/html/body/div/form/p[2]/label/input').send_keys('test123')
sleep(1)
d.find_element_by_xpath('//input[@class="button button-primary button-large"]').submit()
sleep(1)
d.close()
d.quit()

CSS定位

  • css中用空格 表示下级标签(可以是子标签,也可是孙子级别标签)
  • 路径与属性的结合
    语法:
    标签名[属性名="属性值"]

比如说:想定位到 for=“user_pass” 的label标签
label[for="user_pass"]

  • 如果想同时使用多个属性去定位
    语法:
    标签名[属性名=“属性值”][属性名=“属性值”]
    想定位到:class=“input” id=“user_pass” 的 input标签
    input[class="input"][id="user_pass"]

比如:定位到 for=“user_pass” 的label标签 的 input子标签
label[for="user_pass"] input

  • 只用属性
    想定位到 for=“user_pass” 的标签
    [for="user_pass"]
  • 关于id与class定位
    在css定位中,id或者class定位有快捷键定位方式
    id用#表示,class用.表示

想定位到:id=“user_pass” 的 input标签
input#user_pass

想定位到:class=“button-primary” 的input标签
input.button-primary

想定位到:class=“button-primary” id=“wp-submit” 的input标签
input.button-primary#wp-submit

使用css定位实现blog登录

from selenium import webdriver
from time import sleep
d = webdriver.Chrome()
d.get('http://os-201804081018/blog/wp-login.php')
d.maximize_window()
sleep(3)d.find_element_by_css_selector('#user_login').send_keys('test')
sleep(3)
d.find_element_by_css_selector('input[type="password"]').send_keys('test123')
sleep(3)
d.find_element_by_css_selector('p.submit input#wp-submit').click()
sleep(3)
d.close()
d.quit()

Selenium常见操作

演示网站

  • 博客系统

    • 用户名:test
    • 密码:test123

打开网址 get()

最大化窗口

关闭浏览器

from selenium import webdriver
from time import sleep# 打开谷歌浏览器,并且赋值给变量d
d = webdriver.Chrome()# 最大化窗口
d.maximize_window()
sleep(2)
# 通过get()方法,在当前窗口打开网页
d.get('http://www.baidu.com')
sleep(2)
d.get('http://www.taobao.com')
sleep(2)
d.close()#关闭当前窗口
d.quit()#关闭所有窗口,并且退出驱动

点击 click()

输入内容 send_keys()

清空输入的内容 clear()

from selenium import webdriver
from time import sleep# 打开谷歌浏览器,并且赋值给变量d
d = webdriver.Chrome()
# 最大化窗口
d.maximize_window()
d.get('https://www.so.com/')
sleep(1)
# 定位到输入框,输入Python
d.find_element_by_css_selector('#input').send_keys('Python')
sleep(1)
# 清空输入的内容
d.find_element_by_css_selector('#input').clear()
sleep(1)
# 重新输入Selenium
d.find_element_by_css_selector('#input').send_keys('Selenium')
sleep(1)
# 点击搜索按钮
d.find_element_by_css_selector('#search-button').click()
sleep(1)
d.close()#关闭当前窗口
d.quit()#关闭所有窗口,并且退出驱动

is_displayed() 判断元素是否显示/可见

如果元素可见,则返回True,否则返回False
注意 :不管元素是否可见,我们都是可以定位到的。只是不可见的元素,我们是无法进行操作。

隐藏元素属性
type=“hidden”
style=“display:none”
from selenium import webdriver
from time import sleep# 打开谷歌浏览器,并且赋值给变量d
d = webdriver.Chrome()
# 最大化窗口
d.maximize_window()
d.get('http://shop.imsam.cn/wp-login.php')# 判断元素是否可见,如果可见,则返回True
res = d.find_element_by_css_selector('#wp-submit').is_displayed()
print(res)
res2 = d.find_element_by_css_selector('[name="testcookie"]').is_displayed()
print(res2)
# 隐藏元素是可以定位到的,只是无法操作d.close()#关闭当前窗口
d.quit()#关闭所有窗口,并且退出驱动

text 返回元素的文本

get_attribute(“属性”) 获取属性对应值

隐式等待 implicitly_wait(n)n为秒数

隐式等待,是通过一定的时长等待页面的某个元素加载完成。如果超出了设置的时长,元素还没有被加载出来,则抛出异常。

from selenium import webdriver
from time import sleep# 打开谷歌浏览器,并且赋值给变量d
d = webdriver.Chrome()
# 最大化窗口
d.maximize_window()
# 隐式等待
d.implicitly_wait(10)# 最大等待10s
d.get('http://shop.imsam.cn/wp-login.php')d.find_element_by_css_selector('#user_login').send_keys('admin')
d.find_element_by_css_selector('#wp-submit').click()
sleep(1)
# 获取元素文本属性
msg = d.find_element_by_css_selector('#login_error').text
print(msg)# 获取属性对应值
value = d.find_element_by_css_selector('#user_pass').get_attribute('type')
print(value)d.close()#关闭当前窗口
d.quit()#关闭所有窗口,并且退出驱动

鼠标悬停

使用该方法,首先要把ActionChains类导进来,引入ActionChains类的方法如下:
from selenium.webdriver import ActionChains

语法:
ActionChains(浏览器).move_to_element(需要悬停的元素).perform()

下拉框元素定位

  • 通用处理方法:先点击下拉框,再点击下拉框的选项
  • 针对select标签的下拉框,selenium提供了一套解决方案

需要先导包from selenium.webdriver.support.ui import Select

语法:

Select(下拉框元素定位).select_by_index(下标)#根据下标选择
Select(下拉框元素定位).select_by_visible_text('文本信息')#根据文本选择
Select(下拉框元素定位).select_by_value('value的值')# 根据value的值来选择
from selenium import webdriver
from time import sleep
#导入鼠标操作
from selenium.webdriver import ActionChains
# 针对Select标签下拉,导包
from selenium.webdriver.support.ui import Select# 打开谷歌浏览器,并且赋值给变量d
d = webdriver.Chrome()
# 最大化窗口
d.maximize_window()
# 隐式等待
d.implicitly_wait(10)# 最大等待10s
d.get('https://www.baidu.com')
sleep(1)
# 鼠标悬停
# 先定位到需要悬停的元素
mte = d.find_element_by_link_text('设置')
sleep(1)
#语法:ActionChains(浏览器).move_to_element(需要悬停的元素).perform()
ActionChains(d).move_to_element(mte).perform()
sleep(1)d.find_element_by_link_text('搜索设置').click()
sleep(2)#下拉框元素定位(1)
# d.find_element_by_css_selector('#nr').click()#先点击下拉框
# sleep(1)
# d.find_element_by_css_selector('[value="20"]').click()#再点击选项# 只针对select标签下拉框
# 先定位到下拉框
sel = d.find_element_by_css_selector('#nr')
# Select(要操作的下拉框).如何操作
# 根据文本选择
Select(sel).select_by_visible_text('每页显示50条')
sleep(1)
# 根据value来选择
Select(sel).select_by_value('10')
sleep(1)
# 根据下标选择(从0开始)
Select(sel).select_by_index(1)
sleep(1)d.close()#关闭当前窗口
d.quit()#关闭所有窗口,并且退出驱动

send_keys() 上传文件

只针对input标签的上传文件

from selenium import webdriver
from time import sleep# 打开谷歌浏览器,并且赋值给变量d
d = webdriver.Chrome()
# 最大化窗口
d.maximize_window()
sleep(1)
d.get('https://www.baidu.com/')
sleep(1)
# 定位到相机图标,进行点击
d.find_element_by_css_selector('.soutu-btn').click()
sleep(1)
# 定位到上传文件的按钮,通过send_keys()直接输入文件的路径即可上传
d.find_element_by_css_selector('.upload-pic').send_keys('D:\\360.png')
sleep(3)
d.close()
d.quit()

多表单切换

  • 切换表单`switch_to.frame()
  • 切换到最外层表单switch_to.default_content()

表单的嵌套通常是使用 frame 或者 iframe 标签实现的,因此需要先切换到该标签中。

from selenium import webdriver
from time import sleep# 打开谷歌浏览器,并且赋值给变量d
d = webdriver.Chrome()
# 最大化窗口
d.maximize_window()
d.get('https://mail.qq.com/')
sleep(1)# 表单嵌套  frame 标签  iframe标签
# (在一个网页中,嵌套了更多网页)
# 先定位到需要切换的表单
frame_ele = d.find_element_by_css_selector('#login_frame')
d.switch_to.frame(frame_ele)
sleep(1)
d.find_element_by_css_selector('#u').send_keys('123456789')
sleep(2)
# 返回到最外层表单
d.switch_to.default_content()
# # 返回到上一层表单
# d.switch_to.parent_frame()
d.find_element_by_link_text('基本版').click()d.close()#关闭当前窗口
d.quit()#关闭所有窗口,并且退出驱动

警告框 alert

  • switch_to.alert.accept()
  • switch_to.alert.dismiss()
  • switch_to.alert.text
from selenium import webdriver
from time import sleep
from selenium.webdriver import ActionChains
# 打开谷歌浏览器,并且赋值给变量d
d = webdriver.Chrome()
# 最大化窗口
d.maximize_window()d.implicitly_wait(10)# 最大等待10s
d.get('https://www.baidu.com')
sleep(1)
# 鼠标悬停
# 先定位到需要悬停的元素
mte = d.find_element_by_link_text('设置')
sleep(1)
#语法:ActionChains(浏览器).move_to_element(需要悬停的元素).perform()
ActionChains(d).move_to_element(mte).perform()
sleep(1)d.find_element_by_link_text('搜索设置').click()
sleep(2)
d.find_element_by_link_text('保存设置').click()sleep(1)# 警告框操作
msg = d.switch_to.alert.text#获取警告框的文本
print(msg)
# d.switch_to.alert.accept()#确认/接收警告框
d.switch_to.alert.dismiss()#关闭/取消警告框d.close()#关闭当前窗口
d.quit()#关闭所有窗口,并且退出驱动

多窗口处理

如果遇到多窗口处理,我们就要切换窗口了。
window_handles获取所有窗口,以列表的形式返回
switch_to.window()切换窗口

from selenium import webdriver
from time import sleep# 打开谷歌浏览器,并且赋值给变量d
d = webdriver.Chrome()
# 最大化窗口
d.maximize_window()
d.get('https://www.jianshu.com/')sleep(1)
d.find_element_by_css_selector('#q').send_keys('Python')
sleep(1)
d.find_element_by_css_selector('.ic-search').click()
sleep(1)
# 获取所有窗口,以列表的形式返回
all_windows = d.window_handles# 切换窗口
d.switch_to.window(all_windows[1])
sleep(1)
d.find_element_by_css_selector('#q').clear()d.close()#关闭当前窗口
d.quit()#关闭所有窗口,并且退出驱动

定位一组元素 find_elements_by_xxx

find_elements可以找到所有符合规则的元素,并且以列表的形式返回。


JS定位

在selenium中执行JavaScript语句需要使用execute_script(js语句)来执行

  • 滚动条的js语句

window.scrollTo(0,b);
其中b表示与顶部的距离

  • 移除属性的js语句
document.querySelector('CSS表达式').removeAttribute('需要移除的属性名称');
document.querySelectorAll('CSS表达式')[下标].removeAttribute('移除的属性名称');
隐藏元素属性
type=“hidden”
style=“display:none”
只读属性
readonly=“readonly”

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EQEwBCwq-1617696547064)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171618448.png)]

二次定位

在前一次定位的基础上,在进行一次定位
语法: **`find_element_by_xxx().find_element_by_xxx()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N1NLyweq-1617696547065)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171608070.png)]

简书实例

from selenium import webdriver
from time import sleep
d = webdriver.Chrome()
d.maximize_window()
d.get('https://www.jianshu.com/')
sleep(2)all_user = d.find_elements_by_css_selector('.list li')for i in all_user:name = i.find_element_by_css_selector('.name').textdata = i.find_element_by_tag_name('p').textprint('作者:{0},{1}'.format(name,data))sleep(0.5)

隐式等待与显式等待

什么是显示等待和隐式等待?

显示等待就是有条件的等待

隐式等待就是无条件的等待

隐式等待

当使用了隐式等待执行测试的时候,如果 WebDriver没有在 DOM中找到元素,将继续等待,超出设定时间后则抛出找不到元素的异常,

换句话说,当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间再查找 DOM,默认的时间是0、

from selenium import webdriverbrowser = webdriver.Chrome()browser.implicitly_wait(10)#等待十秒加载不出来就会抛出异常,10秒内加载出来正常返回browser.get('[https://www.zhihu.com/explore](https://www.zhihu.com/explore)')input = browser.find_element_by_class_name('zu-top-add-question')
print(input)

显式等待

指定一个等待条件,和一个最长等待时间,程序会判断在等待时间内条件是否满足,如果满足则返回,如果不满足会继续等待,超过时间就会抛出异常

from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECbrowser = webdriver.Chrome()browser.get('https://www.taobao.com/')wait = WebDriverWait(browser, 10)input = wait.until(EC.presence_of_element_located((By.ID, 'q')))button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))print(input, button)
title_is 标题是某内容title_contains 标题包含某内容presence_of_element_located 元素加载出,传入定位元组,如(By.ID, 'p')visibility_of_element_located 元素可见,传入定位元组visibility_of 可见,传入元素对象presence_of_all_elements_located 所有元素加载出text_to_be_present_in_element 某个元素文本包含某文字text_to_be_present_in_element_value 某个元素值包含某文字frame_to_be_available_and_switch_to_it frame加载并切换invisibility_of_element_located 元素不可见element_to_be_clickable 元素可点击staleness_of 判断一个元素是否仍在DOM,可判断页面是否已经刷新element_to_be_selected 元素可选择,传元素对象element_located_to_be_selected 元素可选择,传入定位元组element_selection_state_to_be 传入元素对象以及状态,相等返回True,否则返回Falseelement_located_selection_state_to_be 传入定位元组以及状态,相等返回True,否则返回Falsealert_is_present 是否出现Alert

测试用例练习

创建一个文件夹存放整个项目自动化内容

比如:我在G盘创建了一个 blog_project
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B6o9vaiu-1617696547066)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171904698.png)]

然后在该文件夹下再创建两个文件夹 testcase 与 **`report

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hi8Wgn8Q-1617696547067)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230171914458.png)]

testcase 文件夹下完成以下内容


  • 创建一个 login_case.py 文件
    编写以下几条测试用例
  1. 登录成功
  2. 用户名为空密码正确填写,登录失败
  3. 密码为空用户名正确填写,登录失败
  4. 用户名正确密码错误时,登录失败

  • 创建一个 user_case.py 文件

编写以下几条测试用例
(只需要输入用户名与邮件)

  1. 添加用户成功
  2. 用户名已存在时,添加用户失败
  3. 电子邮件已存在时,添加用户失败
  4. 电子邮件格式错误时,添加用户失败

  • 创建一个 reg_case.py 文件

编写以下几条测试用例

  1. 注册用户成功
  2. 用户名已存在时,注册用户失败
  3. 用户名为空时,注册用户失败
  4. 电子邮件已存在时,注册用户失败
  5. 电子邮件为空时,注册用户失败
  6. 电子邮件格式错误时,注册用户失败

  • 创建一个 post_case.py 文件

进入到文章-所有文章页面,编写以下几条测试用例

  1. 搜索文章成功
  2. 搜索不存在的文章
  3. 删除文章
  4. 下一页翻页功能验证
  5. 上一页翻页功能验证

给两条示例:

from selenium import webdriver
from time import sleep# 登录成功
d = webdriver.Chrome()
d.maximize_window()
d.implicitly_wait(10)
d.get('http://os-201804081018/blog/wp-login.php')
d.find_element_by_css_selector('#user_login').send_keys('test')
sleep(1)
d.find_element_by_css_selector('#user_pass').send_keys('test123')
sleep(1)
d.find_element_by_css_selector('#wp-submit').click()
sleep(1)
login_msg = d.find_element_by_css_selector('#wp-admin-bar-my-account').text
if 'test' in login_msg:print('登录成功用例:pass')
else:print('登录成功用例:fail')
d.close()
d.quit()# 用户名为空密码正确填写,登录失败
d = webdriver.Chrome()
d.maximize_window()
d.implicitly_wait(10)
d.get('http://os-201804081018/blog/wp-login.php')
d.find_element_by_css_selector('#user_login').send_keys('')
sleep(1)
d.find_element_by_css_selector('#user_pass').send_keys('test123')
sleep(1)
d.find_element_by_css_selector('#wp-submit').click()
sleep(1)
login_msg = d.find_element_by_css_selector('#login_error').text
if '用户名一栏为空' in login_msg:print('用户名为空密码正确填写,登录失败:pass')
else:print('用户名为空密码正确填写,登录失败:fail')
d.close()
d.quit()

测试用例优化

之前我们所写的是线性代码

#coding=utf-8
# @Author: SamWang
# @Date:   2019-11-15 16:33:56
# @Last Modified time: 2019-11-16 10:42:48
from selenium import webdriver
from time import sleep# 登录成功
d = webdriver.Chrome()
d.maximize_window()
d.implicitly_wait(10)
d.get('http://os-201804081018/blog/wp-login.php')
d.find_element_by_css_selector('#user_login').send_keys('test')
sleep(1)
d.find_element_by_css_selector('#user_pass').send_keys('test123')
sleep(1)
d.find_element_by_css_selector('#wp-submit').click()
sleep(1)
login_msg = d.find_element_by_css_selector('#wp-admin-bar-my-account').text
if 'test' in login_msg:print('登录成功用例:pass')
else:print('登录成功用例:fail')
d.close()
d.quit()# 用户名为空密码正确填写,登录失败
d = webdriver.Chrome()
d.maximize_window()
d.implicitly_wait(10)
d.get('http://os-201804081018/blog/wp-login.php')
d.find_element_by_css_selector('#user_login').send_keys('')
sleep(1)
d.find_element_by_css_selector('#user_pass').send_keys('test123')
sleep(1)
d.find_element_by_css_selector('#wp-submit').click()
sleep(1)
login_msg = d.find_element_by_css_selector('#login_error').text
if '用户名一栏为空' in login_msg:print('用户名为空密码正确填写,登录失败:pass')
else:print('用户名为空密码正确填写,登录失败:fail')
d.close()
d.quit()# 密码为空用户名正确填写,登录失败
d = webdriver.Chrome()
d.maximize_window()
d.implicitly_wait(10)
d.get('http://os-201804081018/blog/wp-login.php')
d.find_element_by_css_selector('#user_login').send_keys('test')
sleep(1)
d.find_element_by_css_selector('#user_pass').send_keys('')
sleep(1)
d.find_element_by_css_selector('#wp-submit').click()
sleep(1)
login_msg = d.find_element_by_css_selector('#login_error').text
if '密码一栏为空' in login_msg:print('密码为空用户名正确填写,登录失败:pass')
else:print('密码为空用户名正确填写,登录失败:fail')
d.close()
d.quit()# 用户名正确密码错误时,登录失败
d = webdriver.Chrome()
d.maximize_window()
d.implicitly_wait(10)
d.get('http://os-201804081018/blog/wp-login.php')
d.find_element_by_css_selector('#user_login').send_keys('test')
sleep(1)
d.find_element_by_css_selector('#user_pass').send_keys('tes222t123')
sleep(1)
d.find_element_by_css_selector('#wp-submit').click()
sleep(1)
login_msg = d.find_element_by_css_selector('#login_error').text
if '密码不正确' in login_msg:print('用户名正确密码错误时,登录失败:pass')
else:print('用户名正确密码错误时,登录失败:fail')
d.close()
d.quit()

引入单元测试框架

#coding=utf-8
# @Author: SamWang
# @Date:   2019-11-15 16:33:56
# @Last Modified time: 2019-11-16 10:45:53
from selenium import webdriver
from time import sleep
import unittestclass mytest(unittest.TestCase):def setUp(self):passdef tearDown(self):passdef test_login_success(self):# 登录成功d = webdriver.Chrome()d.maximize_window()d.implicitly_wait(10)d.get('http://os-201804081018/blog/wp-login.php')d.find_element_by_css_selector('#user_login').send_keys('test')sleep(1)d.find_element_by_css_selector('#user_pass').send_keys('test123')sleep(1)d.find_element_by_css_selector('#wp-submit').click()sleep(1)login_msg = d.find_element_by_css_selector('#wp-admin-bar-my-account').textif 'test' in login_msg:print('登录成功用例:pass')else:print('登录成功用例:fail')d.close()d.quit()def test_login_username_empty(self):# 用户名为空密码正确填写,登录失败d = webdriver.Chrome()d.maximize_window()d.implicitly_wait(10)d.get('http://os-201804081018/blog/wp-login.php')d.find_element_by_css_selector('#user_login').send_keys('')sleep(1)d.find_element_by_css_selector('#user_pass').send_keys('test123')sleep(1)d.find_element_by_css_selector('#wp-submit').click()sleep(1)login_msg = d.find_element_by_css_selector('#login_error').textif '用户名一栏为空' in login_msg:print('用户名为空密码正确填写,登录失败:pass')else:print('用户名为空密码正确填写,登录失败:fail')d.close()d.quit()def test_login_password_empty(self):# 密码为空用户名正确填写,登录失败d = webdriver.Chrome()d.maximize_window()d.implicitly_wait(10)d.get('http://os-201804081018/blog/wp-login.php')d.find_element_by_css_selector('#user_login').send_keys('test')sleep(1)d.find_element_by_css_selector('#user_pass').send_keys('')sleep(1)d.find_element_by_css_selector('#wp-submit').click()sleep(1)login_msg = d.find_element_by_css_selector('#login_error').textif '密码一栏为空' in login_msg:print('密码为空用户名正确填写,登录失败:pass')else:print('密码为空用户名正确填写,登录失败:fail')d.close()d.quit()def test_login_password_error(self):# 用户名正确密码错误时,登录失败d = webdriver.Chrome()d.maximize_window()d.implicitly_wait(10)d.get('http://os-201804081018/blog/wp-login.php')d.find_element_by_css_selector('#user_login').send_keys('test')sleep(1)d.find_element_by_css_selector('#user_pass').send_keys('tes222t123')sleep(1)d.find_element_by_css_selector('#wp-submit').click()sleep(1)login_msg = d.find_element_by_css_selector('#login_error').textif '密码不正确' in login_msg:print('用户名正确密码错误时,登录失败:pass')else:print('用户名正确密码错误时,登录失败:fail')d.close()d.quit()if __name__ == '__main__':unittest.main()

封装公共部分

from selenium import webdriver
from time import sleep
import unittestdef login_action(d,username,password):d.get('http://os-201804081018/blog/wp-login.php')d.find_element_by_css_selector('#user_login').send_keys(username)sleep(1)d.find_element_by_css_selector('#user_pass').send_keys(password)sleep(1)d.find_element_by_css_selector('#wp-submit').click()sleep(1)class mytest(unittest.TestCase):def setUp(self):passdef tearDown(self):passdef test_login_success(self):# 登录成功d = webdriver.Chrome()d.maximize_window()d.implicitly_wait(10)login_action(d=d,username='test',password='test123')# 调用登录函数login_msg = d.find_element_by_css_selector('#wp-admin-bar-my-account').textif 'test' in login_msg:print('登录成功用例:pass')else:print('登录成功用例:fail')d.close()d.quit()

使用setUp和tearDown优化

from selenium import webdriver
from time import sleep
import unittestdef login_action(d,username,password):d.get('http://os-201804081018/blog/wp-login.php')d.find_element_by_css_selector('#user_login').send_keys(username)sleep(1)d.find_element_by_css_selector('#user_pass').send_keys(password)sleep(1)d.find_element_by_css_selector('#wp-submit').click()sleep(1)
#同一个类下,如果该方法的变量想要能够被其他方法所使用,则在定义变量时,加上一个self.
class mytest(unittest.TestCase):def setUp(self):self.d = webdriver.Chrome()self.d.maximize_window()self.d.implicitly_wait(10)def tearDown(self):self.d.close()self.d.quit()def test_login_success(self):# 登录成功login_action(d=self.d,username='test',password='test123')# 调用登录函数login_msg = self.d.find_element_by_css_selector('#wp-admin-bar-my-account').textif 'test' in login_msg:print('登录成功用例:pass')else:print('登录成功用例:fail')

断言

断言 (判断实际结果与预期结果是否相符)

断言方式 作用
self.assertIn(a,b) 判断 a 是不是 in b
self.assertNotIn(a,b) 判断 a 是不是 not in b
self.assertEqual(a,b) 判断 a 是不是 等于 b
self.assertNotEqual(a,b) 判断 a 是不是 不等于 b
from selenium import webdriver
from time import sleep
import unittestdef login_action(d,username,password):d.get('http://os-201804081018/blog/wp-login.php')d.find_element_by_css_selector('#user_login').send_keys(username)sleep(1)d.find_element_by_css_selector('#user_pass').send_keys(password)sleep(1)d.find_element_by_css_selector('#wp-submit').click()sleep(1)
#同一个类下,如果该方法的变量想要能够被其他方法所使用,则在定义变量时,加上一个self.
class mytest(unittest.TestCase):def setUp(self):self.d = webdriver.Chrome()self.d.maximize_window()self.d.implicitly_wait(10)def tearDown(self):self.d.close()self.d.quit()def test_login_success(self):# 登录成功login_action(d=self.d,username='test',password='test123')# 调用登录函数login_msg = self.d.find_element_by_css_selector('#wp-admin-bar-my-account').textself.assertIn('test',login_msg)def test_login_username_empty(self):#用户名为空密码正确填写,登录失败login_action(d=self.d,username='',password='test123')# 调用登录函数login_msg = self.d.find_element_by_css_selector('#login_error').textself.assertIn('用户名一栏为空',login_msg)def test_login_password_empty(self):# 密码为空login_action(d=self.d,username='test',password='')# 调用登录函数login_msg = self.d.find_element_by_css_selector('#login_error').textself.assertIn('密码一栏为空',login_msg)def test_login_password_error(self):# 用户名正确密码错误时,登录失败login_action(d=self.d,username='test',password='te124st123')# 调用登录函数login_msg = self.d.find_element_by_css_selector('#login_error').textself.assertIn('密码不正确',login_msg)if __name__ == '__main__':unittest.main()

封装到public中

如果当前脚本的函数,需要被其他脚本所引用,那么我们就需要创建一个public来存放这些共用的函数.模块

比如将登陆的login_action函数封装到public中

1、在testcase文件夹下创建一个public.py的文件

2、将login_case.py中的登录函数移动到public.py上

3、 修改login_case.py的调用方式

修改后的login_case.py代码如下

from selenium import webdriver
from time import sleep
import unittest
from public import login_action#同一个类下,如果该方法的变量想要能够被其他方法所使用,则在定义变量时,加上一个self.
class mytest(unittest.TestCase):def setUp(self):self.d = webdriver.Chrome()self.d.maximize_window()self.d.implicitly_wait(10)def tearDown(self):self.d.close()self.d.quit()def test_login_success(self):# 登录成功login_action(d=self.d,username='test',password='test123')# 调用登录函数login_msg = self.d.find_element_by_css_selector('#wp-admin-bar-my-account').textself.assertIn('test',login_msg)def test_login_username_empty(self):#用户名为空密码正确填写,登录失败login_action(d=self.d,username='',password='test123')# 调用登录函数login_msg = self.d.find_element_by_css_selector('#login_error').textself.assertIn('用户名一栏为空',login_msg)def test_login_password_empty(self):# 密码为空login_action(d=self.d,username='test',password='')# 调用登录函数login_msg = self.d.find_element_by_css_selector('#login_error').textself.assertIn('密码一栏为空',login_msg)def test_login_password_error(self):# 用户名正确密码错误时,登录失败login_action(d=self.d,username='test',password='te124st123')# 调用登录函数login_msg = self.d.find_element_by_css_selector('#login_error').textself.assertIn('密码不正确',login_msg)if __name__ == '__main__':unittest.main()

修改后的public.py代码如下

from time import sleepdef login_action(d,username,password):d.get('http://os-201804081018/blog/wp-login.php')d.find_element_by_css_selector('#user_login').send_keys(username)sleep(1)d.find_element_by_css_selector('#user_pass').send_keys(password)sleep(1)d.find_element_by_css_selector('#wp-submit').click()sleep(1)

run_all_case的Python文件

# coding:utf-8
import unittest
import os
import HTMLTestRunner
from time import strftime
from HTMLTestRunner import HTMLTestRunner
import time# python2.7要是报编码问题,就加这三行,python3不用加
#import sys
#reload(sys)
#sys.setdefaultencoding('utf8')#定义路径及报告
cur_path = os.path.dirname(os.path.realpath(__file__))#获取当前路径
case_path = os.path.join(cur_path, "testcase")# 测试用例的目录名
report_path = os.path.join(cur_path, "report")# 测试报告的目录名
report_name = os.path.sep + strftime('%Y_%m_%d_%H_%M_%S') + '.html'if __name__ == "__main__":discover = unittest.defaultTestLoader.discover(case_path,"*case.py")#两个参数(路径,规则)run = HTMLTestRunner(title="测试报告",description="测试用例参考",stream=open(report_path + report_name, "wb"),)run.run(discover)

Fiddler抓包工具

安装

相关下载软件

链接:百度云提取码:3u3l

由于Fiddler需要.net环境所以需要先安装 .net

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VKSBLtrL-1617696547071)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172054580.png)]

安装.net就比较简单了。傻瓜式安装即可

  • 再进行Fiddler的安装,同样傻瓜式安装
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SQUmEEe6-1617696547072)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172108842.png)]
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SY7lTIep-1617696547073)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172119193.png)]

安装fiddler证书生成器[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c7QzT11S-1617696547073)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172133965.png)]

打开Fiddler,点击工具栏中的Tools—>Options–>https设置选项,勾选选择项

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qQWkg26X-1617696547074)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172304363.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9g6XtCEM-1617696547075)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172314242.png)]

点击Actions,点击第二项:Export Root Certificate to Desktop,这时候桌面上会出现证书FiddlerRoot.cer文件,点击OK设置成功,关闭fiddler

PC端,在浏览器中导入证书FiddlerRoot.cer,以谷歌浏览器为例说明,在浏览器上输入: chrome://settings/

1、进入设置界面点击最下面的高级然后选择管理证书在受信任的根证书颁发机构,对证书进行导入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zkXr8hQp-1617696547075)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172405656.png)]

选择刚刚导入到桌面的证书即可点击下一步然后选择浏览找到刚刚导出的证书然后一路next,直到弹出安全性警告,点击是

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tSXqUpsG-1617696547076)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172454456.png)]

然后重启fiddler即可

Fiddler使用

基本介绍

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VVAkNlsd-1617696547077)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173134465.png)]

查看请求的消耗的时间

选择一个请求,点击statistics
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iSCPXAeX-1617696547078)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173120321.png)]

清除全部请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ssDV9DZx-1617696547078)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173109022.png)]

查看请求与响应

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Z2vU7NS-1617696547079)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173056213.png)]

  • 请求头

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h6YREw7u-1617696547080)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173041161.png)]

  • 请求发送的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4YPL0rsO-1617696547080)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173028364.png)]

  • 响应头

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q21R3pEA-1617696547081)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173017590.png)]

  • 响应数据

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7MWTZh2n-1617696547081)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173003693.png)]

  1. TextView 以文本的方式展示出返回的内容
  2. Webview 以网页的方式展示出返回的内容
  3. json 以json的方式展示出返回的内容

设置fiddler过滤请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F5HTqBt1-1617696547082)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172950360.png)]

  • 根据内外网切换

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vz4ZYjqt-1617696547083)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172937029.png)]

  • 根据输入的域名/IP来过滤

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wmjRzymw-1617696547083)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172918079.png)]

模拟弱网环境 Ctrl+R

Ctrl+F 搜索 300,修改上传与下载的速度延时

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bTaRG6oA-1617696547084)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172850444.png)]

修改完成后,ctrl+s保存即可

点击后才会生效[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tM8oEX9G-1617696547084)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172834445.png)]

拦截数据,拦截数据又称“打断点”

  • 拦截请求:
  1. F11先开始拦截,然后在发送请求
  2. 修改拦截下来的请求,修改数据
  3. shift+F11关闭拦截
  4. run to complete,把所有拦截下来的请求发送过去
  • 拦截响应:
  1. alt+F11开始拦截,然后在发送请求
  2. 修改数据
  3. shift+F11关闭拦截
  4. run to complete,把修改的请求发送过去

fiddler抓取HTTPS协

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WAwpIGwV-1617696547085)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172822601.png)]
然后重启fiddler即可。

fiddler抓取手机的包

  1. 手机与电脑在同一网络下
  2. fiddler设置允许远程链接,并设置好端口
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ZAaKWcJ-1617696547086)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172809541.png)]
  3. 查询电脑所在网络的ip地址(在dos界面输入ipconfig)
  4. 手机wifi设置代理,服务器填写:电脑所在ip地址,端口填写fiddler中设置的端口
  5. 重启fiddler即可

wifi代理设置:
`IOS

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ghqa8C5q-1617696547086)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172642441.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LbcKGsbJ-1617696547087)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172651561.png)]

android(一加手机)为例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AUeGzudq-1617696547087)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172545446.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ElZyqdiC-1617696547088)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172558843.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A6AvzRIJ-1617696547089)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230172607351.png)]

接口测试

什么是接口测试

首先,什么是接口呢?

接口一般来说有两种,一种是程序内部的接口,一种是系统对外的接口。

  1. 系统对外的接口:比如你要从别的网站或服务器上获取资源或信息,别人肯定不会把数据库共享给你,他只能给你提供一个他们写好的方法来获取数据,你引用他提供的接口就能使用他写好的方法,从而达到数据共享的目的,比如说咱们用的app、网址这些它在进行数据处理的时候都是通过接口来进行调用的。
  2. 程序内部的接口:方法与方法之间,模块与模块之间的交互,程序内部抛出的接口,比如bbs系统,有登录模块、发帖模块等等,那你要发帖就必须先登录,要发帖就得登录,那么这两个模块就得有交互,它就会抛出一个接口,供内部系统进行调用。

常见接口:

  1. webService接口:是走soap协议通过http传输,请求报文和返回报文都是xml格式的,我们在测试的时候都用通过工具才能进行调用,测试。可以使用的工具有SoapUI、jmeter、loadrunner等;
  2. http api接口:是走http协议,通过路径来区分调用的方法,请求报文都是key-value形式的,返回报文一般都是json串,有get和post等方法,这也是最常用的两种请求方式。可以使用的工具有postman、RESTClient、jmeter、loadrunner等;

前端和后端:

在说接口测试之前,我们先来搞清楚这两个概念,前端和后端。

前端是什么呢,对于web端来说,咱们使用的网页,打开的网站,这都是前端,这些都是html、css写的;对于app端来说呢,它就是咱们用的app,android或者object-C(开发ios上的app)开发的,它的作用就是显示页面,让我们看到漂亮的页面,以及做一些简单的校验,比如说非空校验,咱们在页面上操作的时候,这些业务逻辑、功能,比如说你购物,发微博这些功能是由后端来实现的,后端去控制你购物的时候扣你的余额,发微博发到哪个账号下面,那前端和后端是怎么交互的呢,就是通过接口。

前面说的你可能不好理解,你只需记住:前端负责貌美如花,后端负责挣钱养家。

什么是接口测试:

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

OK,上面是百度百科上说的,下面才是我说的

其实我觉得接口测试很简单,比一般的功能测试还简单,现在找工作好多公司都要求有接口测试经验

什么是接口测试,本着不懂也要装懂的态度,我会说:所谓接口测试就是通过测试不同情况下的入参与之相应的出参信息来判断接口是否符合或满足相应的功能性、安全性要求。

我为啥说接口测试比功能测试简单呢,因为功能测试是从页面输入值,然后通过点击按钮或链接等传值给后端,而且功能测试还要测UI、前端交互等功能,但接口测试没有页面,它是通过接口规范文档上的调用地址、请求参数,拼接报文,然后发送请求,检查返回结果,所以它只需测入参和出参就行了,相对来说简单了不少。

接口测试的原理

通过测试程序或工具,模拟客户端向服务器发送请求报文,服务器接收请求报文后对相应的报文做出处理,然后再把应答报文发送给客户端,客户端接收应答报文这一个过程。

接口组成

首先,接口文档应该包含以下内容:

1、接口说明
2、调用url
3、请求方法(get\post)
4、请求参数、参数类型、请求参数说明
5、返回参数说明

一个完整的具体的接口测试文档,它告诉接口的地址/或名称,要向接口传入什么参数,每个参数有什么约束条件,成功调用接口时的预期返回结果和调用接口失败时的预期返回结果。

为什么要做接口测试:

大家都知道,接口其实就是前端页面或APP等调用与后端做交互用的,所以好多人都会问,我功能测试都测好了,为什么还要测接口呢?OK,在回答这个问题之前,先举个栗子:

比如测试用户注册功能,规定用户名为6~18个字符,包含字母(区分大小写)、数字、下划线。首先功能测试时肯定会对用户名规则进行测试时,比如输入20个字符、输入特殊字符等,但这些可能只是在前端做了校验,后端可能没做校验,如果有人通过抓包绕过前端校验直接发送到后端怎么办呢?试想一下,如果用户名和密码未在后端做校验,而有人又绕过前端校验的话,那用户名和密码不就可以随便输了吗?如果是登录可能会通过SQL注入等手段来随意登录,甚至可以获取管理员权限,那这样不是很恐怖?

所以,接口测试的必要性就体现出来了:

  1. 可以发现很多在页面上操作发现不了的bug
  2. 检查系统的异常处理能力
  3. 检查系统的安全性、稳定性
  4. 前端随便变,接口测好了,后端不用变

接口测试要关注什么内容

  1. 发送给服务器的请求数据是否正确;
  2. 服务器返回给客户端的信息是否和预期结果一致;
  3. 进入数据库,检查接口是否实现的相应的功能;
  4. 接口的响应时间是否符合需求。

接口测试怎么测:

  • 第一步:分析需求

所有的软件测试都应追溯到用户需求,接口测试也一样。在接口测试开始前,我们需要得到一份接口测试的需求文档。

产品开发负责人在完成某产品功能的接口文档编写后,在核对无误后下发给对应的接口测试负责人。测试负责人拿到接口文档需要首先做以下两方面的工作。一方面,测试人员要对接口文档中各个接口的功能以及接口中涉及的各个字段的意义和用途进行理解。另一方面,测试人员也应该充分与开发人员交流,理解清楚每个接口用到协议以及各个字段的取值规范和范围。
需求文档有很全面的,也有很简单,如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qUinmty2-1617696547089)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173311510.png)]

不完整的需求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o7kHfN64-1617696547090)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173331296.png)]

  • 第二步:创建测试计划

接口测试负责人与测试组长或者项目经理沟通测试计划安排。单独一个接口文档涉及的接口过多时,由测试组长按照接口功能的相关性以及复杂性划分接口分发给不同的测试人员进行测试,并制定测试时间以及每日测试工作量。

  • 第三步:写测试用例并评审

接口测试用例的编写方式和功能测试类似,针对接口需要输入的参数,设计各种合理和不合理的数据进行测试,然后进行用例的评审。以下面这个需求为例,编写测试用例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-duFVEeJ4-1617696547090)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173351875.png)]

测试用例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WE0q29ms-1617696547091)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173414648.png)]

  • 第四步:构造接口测试请求并执行

接口测试的工具很多,比如 postman、RESTClient、jmeter、loadrunner、SoapUI等,本人首推的测试工具是postman和jmeter

1)、Postman是谷歌的一款接口测试插件,它使用简单,支持用例管理,支持get、post、文件上传、响应验证、变量管理、环境参数管理等功能,可以批量运行,并支持用例导出、导入。

jmeter是一款100%纯Java编写的免费开源的工具,它主要用来做性能测试,相比loadrunner来说,它内存占用小,免费开源,轻巧方便、无需安装,越来越被大众所喜爱。

Jmeter的安装

  • 由于Jmeter是一个有Java程序编写的,所以需要先安装Java(JDK/JRE)环境

资源下载百度云,提取码:owi9

先安装JDK

  1. 双击安装包进行安装
  2. 点击下一步
  3. 下一步
  4. 安装过程中会弹出JRE的安装界面

然后等待安装结束即可

  • 配置Java环境变量
变量
JAVA_HOME JDK的安装路径
CLASSPATH .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
PATH %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;

打开环境变量设置界面

win+E 、 系统属性、高级系统设置、环境变量

找到Jmeter压缩包,解压

解压后的直接双击bin目录下的jmeter.bat文件启动即可

Jmeter使用

接口演示网站:
https://www.showdoc.cc/372144116738569

unicode编码转中文
http://tool.chinaz.com/tools/unicode.aspx

  • 修改语言
  • 添加线程组
  • 添加http请求
  • 添加查看结果树
  • 修改响应乱码
  • 线程组的设置
  • 聚合报告(查看汇总结果)
  • 参数化(CSV数据文件设置)
  • 信息头管理器
  • 响应断言
  • 请求默认值
  • cookie管理器
  • JSON提取器
  • 以Json的方式发送请求参数
  • 集合点

修改语言

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WkbGexAs-1617696547092)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173642413.png)]

添加线程组

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hBZIWyfV-1617696547092)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173702166.png)]

添加http请求

选择线程组,右键添加一个http请求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jzcUEZFL-1617696547093)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173713505.png)]
依次填写如下内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sx0BaYdb-1617696547094)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173724338.png)]

添加查看结果树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CptEaRjk-1617696547095)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173801199.png)]

修改响应乱码

在Jmeter的bin目录中有一个jmeter.properties文件

使用编辑器打开

找到如下这一行
#sampleresult.default.encoding=ISO-8859-1
在这一行下面增加一行
sampleresult.default.encoding=UTF-8

然后保存,重启Jmeter即可

线程组的设置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YxjhSCmH-1617696547096)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173818822.png)]

聚合报告(查看汇总结果)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-plgTE2qD-1617696547097)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173835451.png)]

  • #Samples 请求数
  • average 平均响应时间
  • 90% Line 90%响应时间
  • throughput 吞吐量、TPS
  • received 每秒接受的数据

参数化(CSV数据文件设置)

  • 模拟不同的用户使用不同的数据

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gQbrBaoh-1617696547097)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173852019.png)]

在Jmeter中使用变量,${变量名}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QXTsQSwn-1617696547098)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173908817.png)]

信息头管理器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Mm9JoKD-1617696547099)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173921186.png)]

响应断言

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-paQduQqD-1617696547099)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173933697.png)]

请求默认值

添加请求默认值,如果后续接口没有给该内容传值,则读取默认值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mLHJhpma-1617696547100)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173946105.png)]

cookie管理器

添加cookie管理器之后,Jmeter会自动处理所有请求之间的cookie

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0WZpborW-1617696547101)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230173959730.png)]

JSON提取器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uB3WcQOf-1617696547102)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174013310.png)]

Json提取器表达式

读取某个key的对应的值
.key的名称

读取列表的内容
[下标]

以Json的方式发送请求参数

  1. 在头部信息中增加一项
Content-Type:application/json
  1. 在发送请求时,选择body data

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TYcqkTEl-1617696547102)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174046273.png)]
\3. 参数以Json形式填写
{"username":"testexam","password":"123123","password_confirmation":"123123"}

集合点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GgCROwHV-1617696547103)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174033452.png)]

run_jmeter.py

import os
from time import strftime#jmeter_bin目录
jmeter_bin = r'D:\apache\apache-jmeter-4.0\bin'#需要运行的jmeter脚本
jmeter_script = r"D:\api_project\token.jmx"#测试报告存放路径
result = r'D:\api_project\report'now = strftime('%Y_%m_%d_%H_%M_%S')
log_path = result + '\\' + now + "\\log"
report_path = result+'\\' + now + "\\report"
os.system("mkdir " +log_path)
os.system("mkdir " +report_path)
command = "jmeter -n -t %s -l %s\\jmeter.log -e -o %s"%(jmeter_script,log_path,report_path)
os.chdir(jmeter_bin)
os.system(command)

Jenkins持续集成

Jenkins安装

  1. 双击jenkins安装文件进行安装

点击next

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dFjQjhrF-1617696547103)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174245678.png)]

选择安装路径安装,点击next

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gKNs46Eo-1617696547104)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174256172.png)]

点击install安装

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s4XECtMS-1617696547105)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174310847.png)]

点击finish

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DqWEv9FV-1617696547105)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174322173.png)]

安装之后默认会打开jenkins网址
http://localhost:8080

默认密码位置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JIPRt9ou-1617696547106)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174333499.png)]

插件安装界面

  • 选择插件安装

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3L0leKDT-1617696547107)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174346287.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UEQRg8Fx-1617696547107)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174403252.png)]

  • 设置密码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WophY49a-1617696547108)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174415787.png)]

至此安装结束

Jenkins配置任务

新建任务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PzAvhKOq-1617696547108)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174501811.png)]

输入任务名称等

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UfNVYCOa-1617696547109)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174517793.png)]

描述信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-31J7sA7i-1617696547110)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174530109.png)]

构建触发器[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G9WuWl68-1617696547110)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174543644.png)]

日程表语法

语法:分钟 小时 天 月 周
总共五个字段,每个字段用空格或者tab键隔开
例子:
20 12 1-25 * *
表示每周每月的1-25号的每天12点20开始执行
25 23 * * *
表示每天的23:25份执行
10 15 * * 1-5
表示周一到周五的每天15:10分执行

增加构建步骤

填写命令

  • 如何填写命令

为了防止Jenkins出错,最好是指定Python的目录

语法:
python的安装路径\python 要执行的py文件路径

  1. 比如我的python安装在 C:\Python
  2. 我要执行的py文件的路径:G:\api_project\run_jmeter.py

那么我的命令为:
C:\Python\python G:\api_project\run_jmeter.py

然后保存即可

性能测试

什么是系统的性能

一个系统做出来了,客户需求说明书上的功能都已经完全且准确无误地实现了,这只表明系统能做事了,但是做得怎么样还有待验证,这里所说的,“做得怎么样”,就可以简单地理解为系统的性能。

什么是系统的性能测试?

性能测试,是指在一定的软件、硬件及网络条件下,通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试,从而发现系统的性能瓶颈。
也就是说,通过各种测试策略,模拟真实的用户使用场景,验证系统能“做得怎么样”。

性能测试的常用术语

  • 并发用户

并发用户,一般分为2种情况。

一种是绝对并发,即所有的用户在同一时刻做同一件事情或者操作,这种操作一般指做同一类型的业务。

一种是相对并发。多个用户对系统发出了请求或者进行了操作,但是这些请求或者操作可以是相同的,也可以是不同的。对整个系统而言,仍然是有很多用户同时对系统进行操作,因此也属于并发的范畴。

并发用户数的误解:关于用户并发的数量,有2种常见的错误观点。 一种错误观点是把并发用户数量理解为使用系统的全部用户的数量或者是系统的注册用户,理由是这些用户可能同时使用系统;还有一种比较接近正确的观点是把在线用户数量理解为并发用户数量。实际上在线用户也不一定会和其他用户发生并发,例如正在浏览网页的用户,对服务器没有任何影响。

  • 点击率(Hits)

单位时间用户向WEB服务器提交的HTTP请求数。点击率和TPS就是一个概念。需要注意的是,这里的点击并非指鼠标的一次单击操作,因为在一次单击操作中,客户端可能向服务器发出多个HTTP请求。

  • 事务响应时间

事务响应时间指的是从客户端发起请求开始,到客户端接收到从服务器端返回的响应结束

标准可参考业界的3/5/10原则:

  1. 在3秒钟之内,页面给予用户响应并有所显示,可认为是“很不错的”;
  2. 在3~5秒钟内,页面给予用户响应并有所显示,可认为是“好的”;
  3. 在5~10秒钟内,页面给予用户响应并有所显示,可认为是“勉强接受的”;
  4. 超过10秒就让人有点不耐烦了,用户很可能不会继续等待下去。
  • 90%的事务响应时间

90%的响应时间,是指在一次完整的测试过程中,所有事务的请求时间,按从小到大顺序排序,90%的事物所消耗的时间范围。

  • 吞吐量(TPS)

吞吐量是我们常见的一个软件性能指标,对于软件系统来说,就是指软件系统在每单位时间内能处理多少个事务/请求等。

  • 集合点

用来实现绝对并发

  • 资源利用率(内存、CPU、网络、I/O的利用率等 Resource utilization)

资源利用率指的是对不同系统资源的使用程度,例如服务器的CPU(s),内存,网络带宽等。资源利用率通常以占用最大值的百分比n%来衡量。

性能测试策略

  • 负载测试

在一定的软件、硬件及网络条件下,通过运行一种或多种业务在不同虚拟用户数量情况下,测试系统的性能指标是否在用户的要求范围内,用于确定系统所能承受的最大有效用户数以及不同用户数下的系统响应时间及服务器的资源利用率。
负载测试强调的是在一定的环境下系统能够达到的峰值指标,大多数的性能测试都是负载测试。这种方法的目的是找到系统处理能力的极限,通过模拟不同数量级的用户,找到如“响应时间不超过10秒”,“服务器平均CPU利用率低于65%”时的用户数。

负载测试场景:

50个用户同时下单请求      响应时间         消耗资源
100个用户同时下单请求        响应时间         消耗资源
150个用户同时下单请求        响应时间         消耗资源
200个用户同时下单请求        响应时间         消耗资源
  • 压力测试

在一定的软件、硬件及网络条件下,通过模拟大量的虚拟用户向服务器产生负载,使服务器的资源处于极限状态下并长时间连续运行,以测试服务器在高负载情况下是否能够稳定工作。

  • 绝对并发测试

通过模拟多个用户并发访问一个应用或一个应用的某个功能,同一个存储过程,或接口以及其他并发操作,测试程序是否支持多用户访问,是否存在死锁,线程同步的问题。

  • 疲劳测试

疲劳测试,有些公司也叫可靠性测试,是软件系统长时间(8小时,7*24小时)运行系统,检查系统是否能稳定运行,有没有内存泄漏等。

内存溢出–需要占用的内存超过系统的可用内存 (OOM:OutOfMemory)
内存泄漏–内存被长期占用,无法被回收。
程序没有做多线程处理:程序在单用户场景下运行成功,多用户运行则失败,提示连不上服务器。
线程同步的问题:程序实现的功能是,随机给用户分配不同的任务,单用户运行时,能成功分配;多用户并发申请任务时,所有用户得到的任务都是一样的。

性能测试指标

一般来说,性能测试关注的指标有这些:
1、事务成功率
2、事务平均响应时间和90%的事务响应时间
3、吞吐量(TPS)
4、CPU,内存,IO使用率

性能测试流程

  1. 熟悉性能测试需求,确定性能测试点和测试指标;
  2. 开发性能测试脚本并调优;
  3. 准备性能测试环境,性能测试数据,设计性能测试场景;
  4. 监控性能测试环境;
  5. 运行性能测试;
  6. 分析性能测试结果,提交性能测试bug单,跟踪问题单直到问题被解决;
  7. 输出性能测试报告。

Jmeter简介

Jmeter是一种预测系统行为和性能的负载测试工具。它通过模拟实际用户的操作行为和实行实时性能监测,来帮助测试人员更快的查找和发现问题。

  • Jmeter工作原理图:

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iIev2zEa-1617696547111)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230174708375.png)]

  • Jmeter环境的搭建:

  1. 因为JMeter是JAVA程序开发的,所以要先安装JDK;

  2. 配置JAVA环境变量,包括:JAVA_HOME,PATH,CLASSPATH;

  3. 双击jmeter的bin目录里面的jmeter.bat文件,就可以启动Jmeter。

    Nmon监控LInux系统

    安装

    首先现在根目录创建一个文件夹mkdir /nmon

    然后再 /nmon下创建一个log文件夹

    cd /nmon 然后 mkdir ./log

    • 上传Nmon文件
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8KL3ghgG-1617696547112)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175254936.png)]

    给予执行权限
    chmod -R a+x ./nmon_x86_rhel5

    使用Nmon监控

    为了配合性能测试,我们往往需要将一个时间段内系统资源消耗情况记录下来,这时可以使用命令在远程窗口执行命令

    cd /nmon
    ./nmon_x86_rhel5 -f -N -t -m 监控数据存放路径 -s 间隔时间 -c 监控次数-m 数据存放的路径
    -s 间隔时长(秒)
    -c 监控次数
    

    比如我将日志的存放路径放在/nmon/log,总共监控80次,每次间隔5秒
    ./nmon_x86_rhel5 -f -N -t -m /nmon/log -s 5 -c 80

    监控完成后,进入到/nmon/log目录中,可以看到产生的日志文件,将其导出到本地
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HzPDLYEb-1617696547113)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175316641.png)]

    安全警告,选项,启用此内容
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-arNzNhIR-1617696547113)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175337923.png)]

    点击分析nmon数据,选择刚刚导出的nmon文件
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cbKNtPVm-1617696547114)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175409150.png)]

    他会转换成excel表格的形式
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0ZIFrIbv-1617696547115)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175419678.png)]

    查看CPU

    CPU主要在CPU_ALL这一个表中

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XBHsg5nO-1617696547115)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175430296.png)]

    其中CPU%就是CPU的使用率

    首先先截取出自己在执行性能测试这段时间的资源的使用情况

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nWkf5gQG-1617696547116)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175443426.png)]

    再生成折线图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ubVYR6Nq-1617696547116)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175523242.png)]

    查看内存

    内存的使用情况主要在MEM这一个表中

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mZxqFgHx-1617696547117)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175550631.png)]

    内存占用率 = (总内存-可用内存)/总内存

    可用内存 = 空闲内存 + 缓存 + 缓冲区

    ​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ejb3kGIl-1617696547118)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175623659.png)]

    删除多余表格
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4ecyBJyq-1617696547118)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175644067.png)]

    使用 公式生成,设置以百分比展示

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i6HCB3y8-1617696547119)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175704806.png)]

    Jmeter分布式

    修改配置文件

    1. 允许分布式压力

    先将jmeter的bin目录中的jmeter.properties文件

    找到这一行#server.rmi.ssl.disable=false

    在这一行下面添加一行server.rmi.ssl.disable=true

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ROqvjWK7-1617696547119)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175744814.png)]

    1. 大脑还需要查找如下内容,来添加自己预计需要控制的压力机remote_hosts

    找到如下内容

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M4dDXFAk-1617696547120)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175805447.png)]

    在remote_hosts=IP地址1,IP地址2
    
    1. 查看返回内容

    查找关键字#mode=Standard,把前面的#号去掉,保存退出,重启jmeter,就可以

    1. 确保压力机与大脑(主机)的参数化文件路径一致

    比如脚本中参数化文件的路径是D:\ecshop_pf\username.txt

    那么就必须确保所有的主机与压力机都拥有此文件D:\ecshop_pf\username.txt

    其次,所有的压力机需要平分所有的数据,比如,原本参数化文件有120条数据,
    我使用了3台压力机,那么所有压力机就一台40条数据

    1. 最后压力机需要开启被控制的模式

    在Jmeter的bin 目录中,双击jmeter-server.bat文件,运行后,可被远程 控制

    1. 大脑控制其余压力机运行

    打开jmeter.bat文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-myVYAANJ-1617696547121)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175820308.png)]

    若没有返回数据

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6uccVlD9-1617696547121)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175835689.png)]

    如果开启不了Jmeter-server.bat

    1. 检查配置文件的修改是否有问题
    2. 关闭oracle服务

    关闭oracle服务

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LOmlaAts-1617696547122)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175846958.png)]

    找到这两个
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BegoOpIz-1617696547123)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230175856201.png)]

Monkey

安装

下载百度云地址
提取码:46a0

下载后解压到当前文件夹会得到一个adt文件夹

将adt中的sdk\platform-tools目录加入到环境变量

然后在dos界面就可以使用adb命令

比如adb version

使用

ADB命令使用详解

ADB是一个 客户端-服务器端 程序, 其中客户端是你用来操作的电脑, 服务器端是android设备.我们后期将会使用adb+monkey对app进行性能测试。

安卓设备以夜神模拟器为例子,夜神模拟器默认IP: 127.0.0.1:62001

常见adb命令

  • 连接安卓设备
adb connect 设备ip地址
  • 查看已经连接上的设备
adb devices
  • 安装软件
adb install 需要安装的apk路径

比如我要安装的apk:D:\apk\dr.fone3.2.0.apk
那么我的命令是:adb install D:\apk\dr.fone3.2.0.apk

  • 查看手机日志
adb logcat 查看手机日志
adb logcat -v time 查看手机日志(带上时间)
  • 清除历史日志
adb logcat -c
  • 获取app的包名

包名,在手机中表示app的标识。

  1. 先清空历史日志
adb logcat -c
  1. 先监控日志中关于START关键字的日志
adb logcat -v time | findstr START
  1. 启动被测app
  2. 待日志产生后,ctrl+c终止日志的获取
  3. 查看获取的日志,cmp等于号后面的就是包名,包名到/终止,cmp=包名/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NiuabGak-1617696547123)(https://www.kancloud.cn/samwang/daily/images/screenshot_1574662679605.png)]

  • 卸载app
adb uninstall 包名
  • 上传下载文件
adb push 本地路径 android路径
adb pull android路径 本地路径

比如将D:\a.txt 文件上传到 安卓/data目录下
adb push D:\a.txt /data

比如将 安卓/data目录下a.txt文件 下载到D:\test中
adb pull /data/a.txt D:\test

  • monkey命令
adb shell monkey -p 包名 -v 事件数/次数
  • 使用monkey做回归测试

monkey命令后面可以带很多参数,常见的除了-v、-p还有-s,-s 后面加上monkey上一次运行时候的产生seed值,就可以让monkey重复上一次运行时的操作路径,从而实现回归测试。

adb shell monkey -p 包名 -s seed值 -v 次数
  • 测试期间收集monkey日志
adb shell monkey -p 包名 -v 事件数/次数 > D:\monkey.log
  • 收集logcat日志(logcat日志,记录了用户的在系统上的所有操作)
adb logcat -v time > E:\share\logcat.log

把logcat日志导入到E盘的share目录下。

使用monkey进行性能测试

步骤如下

  1. 清空历史日志adb logcat -c
  2. 使用iTest监控被测app
  3. 收集手机logcat日志adb logcat -v time > D:\logcat.txt
  4. 新开一个dos窗口,执行monkey命令并收集日志adb shell monkey -p 包名 -v 次数 > D:\monkey.txt
  5. 待monkey命令结束后,停止logcat日志获取

adb 连接真机

  1. 有线连接

数据线连接上手机与电脑,安装好驱动即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BZseFApk-1617696547124)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180217584.png)]

  1. 无线连接,方法一

数据线连接上手机与电脑,安装好驱动

输入命令`adb tcpip 5555

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ki0bjTm-1617696547125)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180201308.png)]

手机与电脑处于同一网络之下,并且查询到手机的wifi的ip地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sMbAdcKF-1617696547126)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180151317.png)]

输入命令`adb connect 手机IP地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QEyr72UF-1617696547127)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180104153.png)]

  1. 无线连接,方法二(需要获取root权限)

手机与电脑处于同一网络下
安装adbwireless应用即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bg0r6RGf-1617696547127)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180052290.png)]

下载百度云

提取码`:`sfu6

appium自动化

appium的安装

前提条件:1.安装selenium,2.安装JDK

  • 安装 Nodejs

下载并安装nodejs官网根据你电脑的位数来下载

下载好后,傻瓜式默认安装。

安装完后输入:npm -v ,出现以下信息,表示安装成功。

  • 安装appium

通过官网下载,下载后双击安装

  • 安装Android SDK 环境安装

Android SDK 可以看做用于开发和运行Android 应用的一个软件
官方下载地址
国内镜像地址

官网最底部下载对应的SDK 工具包就可以了

环境变量配置

变量名:ANDROID_HOME
变量值:SDK的路径
变量名:PATH
变量值:;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools;

  • 安装Appium-Python-Client

在dos界面输入命令 python -m pip install Appium-Python-Client

至此安装结束

appium基本使用

  • 夜神模拟器win7系统下的连接方法: adb connect 127.0.0.1:62001

  • 夜神模拟器win10系统下的连接方法: adb connect 127.0.0.1:62025

  • 查看当前运行的APP的包名和打开的Activity
    adb shell "dumpsys window | grep mCurrentFocus"

    • 定位元素
    • 基本定位
    • UIAutomator定位
    • 定位一组元素
    • Swipe 两点之间的滑动操作
    • 连续滑动
    • H5元素的定位

配置Python连接手机app

desired  = {"platformName": "Android","platformVersion": "设备版本","deviceName": "设备名称","appPackage": "包名","appActivity": "activity名称","unicodeKeyboard": "True","restKeyboard": "True"
}

首先需要现在appium中开启服务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eIICMKuY-1617696547128)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180350898.png)]

点击后如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xywl2pa4-1617696547129)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180400183.png)]

在appium中配置json文件

{"platformName": "Android","platformVersion": "设备版本","deviceName": "设备名称","appPackage": "包名","appActivity": "activity名称","unicodeKeyboard": "True","restKeyboard": "True"
}

然后点击

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AqChDFXe-1617696547130)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180430762.png)]

填写json内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rOn5fg3L-1617696547130)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180457706.png)]

填写完成后,点击保存

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bs0O3yW3-1617696547131)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180523021.png)]

当然你也可以保存该配置至电脑中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3DDYvfSK-1617696547131)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180535278.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mHAa6e1c-1617696547132)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180544582.png)]

定位元素

start_session就可以开始定位元素了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EBLZLcVo-1617696547132)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180600883.png)]

基本使用[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kXu9jhJw-1617696547133)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180620074.png)]

判断属性是否唯一[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-irzm8mnD-1617696547133)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180634553.png)]

基本定位

from appium import webdriver
from time import sleep# 配置需要操作的手机以及app
desired = {"platformName": "Android","platformVersion": "5.1.1","deviceName": "127.0.0.1:62001","appPackage": "com.mymoney","appActivity": "com.mymoney.biz.splash.newguide.NewGuideActivity","unicodeKeyboard": "True","restKeyboard": "True"
}# 连接appium,打开app
d = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired)
sleep(5)# 点击下一步,使用id定位
d.find_element_by_id('com.mymoney:id/next_btn').click()
sleep(3)# 再次点击下一步,使用class定位
d.find_element_by_class_name('android.widget.Button').click()
sleep(3)
# 点击开始随手记
d.find_element_by_xpath('/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.support.v4.view.ViewPager/android.widget.LinearLayout[2]/android.widget.LinearLayout[2]/android.widget.Button[1]').click()
sleep(10)# 关闭app
d.close_app()

UIAutomator定位

使用方法 find_element_by_android_uiautomator() 可以运用UiAutomator元素定位。
UiAutomator提供一下三种方式来定位:
•id定位d.find_element_by_android_uiautomator('new UiSelector().resourceId("id的值")')
•text定位d.find_element_by_android_uiautomator('new UiSelector().text("text的内容")')
•class name定位d.find_element_by_android_uiautomator('new UiSelector().className("className的值")')

定位一组元素

Swipe 两点之间的滑动操作

我们在使用App的过程中,经常会在屏幕上进行滑动的操作,如,刷新新闻,刷朋友圈等,会做上下滑动的动作;如果是看图片,就会左右移动。在Appium里面,我们是用swipe()这个方法来实现这个操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SO4stZmo-1617696547134)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201230180652163.png)]

语法:
swipe(起始横坐标,起始纵坐标,目标横坐标,目标纵坐标)

获取屏幕尺寸d.get_window_size()获取屏幕大小,以词典的方式返回

想右滑动,y轴不变,x轴由小到大即可

# 获取屏幕大小,以词典的方式返回
size = d.get_window_size()
width = size['width']
height = size['height']
x1 = 0.2 * width
x2 = 0.9 * width
y = 0.5*height
d.swipe(x1,y,x2,y)

连续滑动

swipe滑动操作,一般是两点之间的滑动,而实际使用过程中用户可能要进行一些多点连续滑动操作。如手势密码操作,切西瓜等场景。那么在Appium中该如何模拟这类操作呢?
TouchAction
TouchAction包含一些列操作,比如按压、长按、点击、移动、暂停。由这些不同操作可以组成一套动作。使用TochAction需要先导入对应的模块:
from appium.webdriver.common.touch_action import TouchAction

连续滑动需要导入from appium.webdriver.common.touch_action import TouchAction

  • 按压

方法:press() 按压一个元素或坐标点(x,y)。

press(element)
press(x,y)
  • 长按

方法:相比press()方法,long_press()多了一个入参,就是长按的时间。duration以毫秒为单位。1000表示按一秒钟。其用法与press()方法相同。

long_press(element,duration=1000)
long_press(x,y,duration=1000)
  • 点击

方法:tap() 对一个元素或控件执行点击操作。用法参考press()。

tap(element)
tap(x,y)
  • 移动

方法:move_to() 将指针从上一个点移动到指定的元素或点。

move_to(element)
move_to(x,y)
  • 暂停

方法:wait()暂停脚本的执行,单位为毫秒。

wait(ms)
  • 释放

方法release() ,我们滑动总要停止吧?怎么停止?就是用这个方法停止。

release()
  • 执行

方法:perform() 把要执行的操作发送到Appium服务器,即让要执行的操作生效。

perform()

示例代码

from appium import webdriver
from time import sleep
from appium.webdriver.common.touch_action import TouchAction# 配置需要操作的手机以及app
desired = {"platformName": "Android","platformVersion": "5.1.1","deviceName": "127.0.0.1:62001","appPackage": "com.mymoney","appActivity": "com.mymoney.biz.splash.newguide.NewGuideActivity","unicodeKeyboard": True,"restKeyboard": True
}# 连接appium,打开app
d = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired)sleep(5)# UIAutomator定位之id定位
d.find_element_by_android_uiautomator('new UiSelector().resourceId("com.mymoney:id/next_btn")').click()
sleep(2)# 再次点击下一步,使用class定位
d.find_element_by_android_uiautomator('new UiSelector().className("android.widget.Button")').click()
sleep(2)
# 通过text定位,进入首页
d.find_element_by_android_uiautomator('new UiSelector().text("开始随手记")').click()
sleep(10)# 点击更多
d.find_element_by_id('com.mymoney:id/nav_setting_btn').click()
sleep(2)# 往上滑动# # 获取屏幕大小,以词典的方式返回
size = d.get_window_size()
width = size['width']
height = size['height']
x = 0.5 * width
y1 = 0.2 * height
y2 = 0.9 * height
d.swipe(x,y2,x,y1)
sleep(2)# 点击高级
d.find_element_by_android_uiautomator('new UiSelector().text("高级")').click()
sleep(2)
d.find_element_by_android_uiautomator('new UiSelector().text("密码与手势密码")').click()
sleep(2)
d.find_element_by_android_uiautomator('new UiSelector().text("手势密码保护")').click()
sleep(2)print('连续滑动')
TouchAction(d).press(x=169,y=190).wait(1000).move_to(x=274,y=190).move_to(x=270,y=293).move_to(x=170,y=382).release().perform()
sleep(3)d.close_app()

H5元素的定位

在混合开发的App中,经常会有内嵌的H5页面。针对这种场景直接使用前面所讲的方法来进行定位是行不通的,因为前面的都是基于Andriod原生控件进行元素定位,而Web网页是单独的B/S架构,两者的运行环境不同因此需要进行上下文(context)切换,然后对H5页面元素进行定位操作。
什么是context呢?在程序中context我们可以理解为当前对象在程序中所处的一个环境。 比如前面提到的App一个界面是属于Activity类型,也就是Android界面环境,但是当访问内嵌的网页是属于另外一个环境(网页环境),两者处于不同的一个环境。

  • 获取所有的上下文contexts,以列表的形式返回
all_context = d.contexts
print(all_context)
  • 切换上下文switch_to.context()
all_context = d.contexts
d.switch_to.context(all_context[1])
  • H5操作的环境搭建
  1. 手机与电脑连接,通过adb devices可查看到此设备。
  2. 电脑端必须安装chrome浏览器(selenium环境搭建好即可)。
  3. App Webview开启debug模式(注:此步骤,一般需要App开发人员开启。)
  4. 在电脑端Chrome浏览器地址栏输入chrome://inspect/#devices,进入调试模式
  5. 打开app对应的h5页面,在 chrome://inspect/#devices 地址中,检查是否显示对应的webview,如没有,则当前未开启调试模式。

上图App已经开启了开启调试模式。

  1. 下载与手机系统浏览器的版本相对应的驱动

比如我的版本是74.0.3729.136,我就需要下载相对应版本的谷歌浏览器驱动

下载下来之后创建一个文件夹存放该驱动,并且解压

比如,我在D盘创建了一个app_chromederiver目录,将驱动移动进去并解压

另外在脚本中的desired中增加一项chromedriverExecutable指定驱动位置即可

比如我的:

# 配置需要操作的手机以及app
desired = {"platformName": "Android","platformVersion": "5.1.1","deviceName": "127.0.0.1:62001","appPackage": "com.wondershare.drfone","appActivity": "com.wondershare.drfone.ui.activity.Main2Activity","unicodeKeyboard": True,"restKeyboard": True
}# 由于appium自带了一个chromedriver,所以我们需要指定appium使用我们下载下来的对应版本的驱动
# 在desired中,增加一个key>>> chromedriverExecutable,它的值就是指定的驱动位置
desired['chromedriverExecutable'] = R"D:\app_chromederiver\chromedriver.exe"

完整H5页面代码演示

from appium import webdriver
from base import desired
from time import sleepdesired['appPackage'] = 'com.wondershare.drfone'
desired['appActivity'] = 'com.wondershare.drfone.ui.activity.WebViewActivity'# 指定appium使用chromedriver.exe
desired['chromedriverExecutable'] = R'D:\chromedriver.exe'd = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired)
print('开始等待20s')
sleep(20)# contexts 获取所有的上下文
all_contexts = d.contexts
print(all_contexts)
sleep(1)
# 切换上下文
d.switch_to.context(all_contexts[1])
print('切换上下文')
sleep(2)
d.find_element_by_id('email').send_keys('sam@imsam.cn')
sleep(2)
d.find_element_by_class_name('btn_send').click()
sleep(2)

面试题总结(测试理论)相关推荐

  1. 2023软件测试金三银四常见的软件测试面试题-【测试理论篇】

    三.测试理论 3.1 你们原来项目的测试流程是怎么样的? 我们的测试流程主要有三个阶段:需求了解分析.测试准备.测试执行. 1.需求了解分析阶段 我们的SE会把需求文档给我们自己先去了解一到两天这样, ...

  2. Computer:计算机测试理论(开发/测试/上线)之DEV、SIT、UAT、PRD四套环境详细介绍之详细攻略

    Computer:计算机测试理论之DEV.SIT.UAT.PRD四套环境详细介绍之详细攻略 目录 测试理论 1.DEV.SIT.UAT.PRD四套环境的简介 SIT测试 和UAT测试对比

  3. 计算机专业对口升学模拟试题,2010对口升学模拟试题计算机专理论综合

    对口升学模拟试题计算机专理论综合 专业 计 算 机 学号 姓名 班级________________ 密 封 线 2010年隆回九中计算机专业对口升学模拟试题 计算机专业综合 试题分第Ⅰ卷(选择题)和 ...

  4. 软件测试知识点和面试题--app测试篇

    软件测试知识点和面试题--接口测试篇 软件测试知识点和面试题--性能测试篇 软件测试知识点和面试题--手工测试篇(功能测试) APP发布流程 内部发布平台蒲公英.Testlink等发布步骤1.开发打包 ...

  5. 【面试宝典】软件测试工程师2021烫手精华版(第一章测试理论篇)

    前言: 翻了很多论坛博客关于面试的文章,很多都是不完整的,还都是比较常见规规矩矩的,那大家刷过的基本都不拿出来了,都是一些大家平时见得不多,但是面试官很看中的一些题. 第一章 测试理论 一. 软件工程 ...

  6. Computer:计算机测试理论(开发/测试/上线)之DEV、SIT、UAT、PRD四套环境(测试环境/开发环境/生产环境)详细介绍之详细攻略

    Computer:计算机测试理论(开发/测试/上线)之DEV.SIT.UAT.PRD四套环境(测试环境/开发环境/生产环境)详细介绍之详细攻略 目录 测试理论 1.DEV.SIT.UAT.PRD四套环 ...

  7. 山东省计算机等级考试初级试题,2013山东省计算机等级考试试题 二级ACCESS理论考试试题及答案...

    2013山东省计算机等级考试试题 二级ACCESS理论考试试题及答案 1.化工厂中用计算机系统控制物料配比.温度调节.阀门开关的应用属于( A ) A.过程控制 B.数据处理 C.科学计算 D.CAD ...

  8. 江苏省计算机等级考试理论试题,2015江苏省计算机等级考试试题 二级ACCESS理论考试试题及答案...

    2015江苏省计算机等级考试试题 二级ACCESS理论考试试题及答案 1.一般情况下,1KB内在最多能存储( B )个ASCII码字符,或( B )个汉字内码. A.1024.1024 B.1024, ...

  9. 2011百度实习生招聘笔试试题---软件测试—测试方向(BJ)

    2011百度实习生招聘笔试试题---软件测试-测试方向(BJ) 来源: 周广陵的日志 第一大题  简答题 1.extern"C"{}是什么,它能起到什么作用? 2.介绍两种经典设计 ...

最新文章

  1. 数据智能是大数据的未来
  2. SQL Server游标的使用【转】
  3. ios开发Base64编码以及加密相关学习
  4. Android开发之约束布局平均分布|ConstraintLayout平均分布|约束布局均匀分布|ConstraintLayout均匀分布
  5. 他们调查了3.9万名程序员,制作了这份开发者技能报告
  6. 搭建Cent OS7服务器时需要注意的一些问题
  7. OpenCv之Canny边界检测(笔记13)
  8. IT人终于把自己熬成了民工
  9. ligerui php mysql_ligerui中3级联动的数据库例子
  10. 【转】在唯一密钥属性“value”设置为“***”时,无法添加类型为“add”的重复集合项解决方法
  11. 神经结构化学习 4 图像分类的对抗性学习Adversarial learning for image classification
  12. Alook浏览器获取Cookie教程
  13. Python爬虫进阶教程(五):数据存储
  14. 二等水准测量记录数据_2等水准测量原始记录表
  15. 网易有道的面试也太难了吧,这都堪比我朋友三面的阿里了!
  16. 【无标题】sap-ecc6.0 ides 安装过程记录
  17. IDEA2020安装教程
  18. unity 蒙皮混合权重
  19. 触屏计算机显示器CDU,触摸屏显示器是什么 触摸屏显示器怎么样【详解】
  20. Android AccountManager帐号管理(二)

热门文章

  1. 跨专业考研学生的三个问题
  2. macOS - afconvert 命令(音频格式转换)
  3. 【笔记】reko 0.10.2 反编译工具安装和使用记录|(2) 翻译 user‘s guide
  4. ETHEREUM PET SHOP
  5. allure如何设置新logo
  6. 《梵高》-孤独的天才
  7. 关于工程导论的读书计划表
  8. 如何恢复计算机系统,电脑系统还原,手把手教你电脑系统怎么还原
  9. 一键重装系统后电脑黑屏怎么办,电脑系统重装黑屏
  10. leetcode1567. 乘积为正数的最长子数组长度(Python3、c++)