自动化测试工具
原文地址:自动化测试工具
-
Instrumenttation
-
UIAutomator +uiautomatorviewer
-
Selendroid
-
Robotism
-
Appium
-
selenium
自动化框架
- Unittest框架
单元测试
- 数据驱动DDT
python的第三方库
一般进行接口测试时,每个接口的传参都不止一种情况,一般会考虑正向、逆向等多种组合,所以在测试一个接口时,通常会编写多条case,而这些除了传参不同外,并没有什么区别。这个时候就可以利用ddt来管理测试数据,提高代码复用率。
- 行为驱动Lettuce
基本python语言的lettuce框架
什么是BDD
行为驱动开发是一种敏捷软件开发技术,它鼓励软件项目开发者、QA和非技术人员或商业参与者之间的协作。主要是从用户的需求出发,强调系统行为。BDD包括验收测试和客户测试驱动等的极限编程的实践,作为对测试驱动开发的回应。
- 关键字驱动Robot Framework
Robot Framework是一款python编写的功能自动化测试框架。具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式测试执行。主要用于轮次很多的验收测试和验收测试驱动开发(ATDD)。
-
测试报告管理(HTMLTestRunner)
-
邮件服务管理
接口自动化
-
postman
-
python requests
压力工具
-
Load-runner
-
Jmeter
结构化思维
功能性
- 关于功能性测试
-
常规可输入的内容、数字、字符串、特殊字符、转义字符等。
-
非常规有一定含义的,html标签、css、javascript代码、url等
-
输入内容的边界、空字符、超长文本(边界值+1,-1)
兼容性
- 关于兼容性测试
-
根据产品的用户分布、手机品牌、分辨率、选择topN机型
-
根据产品在不同浏览器上的占有率,选择主要的浏览器测试
-
关注的问题,页面渲染、页面布局等,借助firebug调试
稳定性
- 关于稳定性测试
- 在某一压力下,搜索时,结果可以正常返回
性能
- 关心性能测试
-
GPS(每秒查询率),Query Per Second,每秒钟能处理的请求数
-
从点击开始到页面完全加载,平均耗时情况
-
加载的页面大小,资源(JS,CSS文件)的数量等
安全
- 关于安全测试
-
JS注入
-
SQL注入
接口
- 关于接口测试
-
查询接口的正确性验证
-
查询接口对一些异常数据的容错情况
-
查询接口在非浏览器环境下的处理情况
线上监控
- 关于线上监控
-
保证线上服务的质量,建立实时监控
-
及时发现异常情况,降低对用户的影响
自动化
- 关于自动化
-
基于Selenium实现UI自动化
-
例行回归验证,提高效率
-
Android使用Appium基于UIAutomator,IOS使用WDA
了解测试流程
了解bug处理流程
- bug分级,优先级(中高低)、严重程度(高中低)
- bug分类,UI、系统、接口
- bug状态 ,新建、待修改,待验证、已验证
常用的测试工具
- 网络调试工具:fiddler
- 页面调试工具:Chrome Inspector firebug
- Web自动化工具:QuickTestProfessional ,selenium
- 移动端工具:ADB、Monkey、MonkeyRunner
- 移动端自动化框架:appium、 Robotium、UIAutomator、 Selendroid
- 服务端压力工具:loadrunner、JMeter
测试分为哪几个阶段
- 单元测试
- 集成测试
- 系统测试
- 验收测试
如何做好测试计划
- 5w原则
- WHAT(明确测试什么)
- WHY(明确测试目标)
- WHEN(明确项目开始、结束时间)
- HOW(明确测试方案)
- WHERE(明确资料的位置)
常见的测试用例设计方法有哪些
- 等价类划分法
- 边界值分析法
- 错误推测法
- 正交表分析法
- 场景分析法
- 因果图法
一条bug记录都包含哪些内容
- bug所属模块
- bug状态(新建、已修复、已验证、遗留等)
- bug出路记录
如何分层自动化测试
- UI自动化回归
- 接口自动化
- 单元测试-白盒测试
如何保证脚本有效性
- 保证定位有效性,封装处理异常
- 保证流程有效性,封装独立方法
- 保证数据有效性,数据备份与恢复
如何降低自动化维护成本
- UI自动化,针对不常态的页面
- 接口自动化,周期短,变动频繁
- 框架分层,用例与框架分离
常见测试覆盖类型
- 语句覆盖
- 判定覆盖
- 条件覆盖
- 判定/条件覆盖
- 条件组合覆盖
- 路径覆盖
B/S和C/S架构什么区别
- c/s是Client/Server或客户/服务器模式.,如:杀毒软件
- b/s是Brower/Server的缩写,如:百度
安全性测试都包含哪些内容
- 用户访问认证
- 传输数据加密
- 安全防护策略:如安全日志、入侵检测、隔离防护、漏洞扫描
- 数据备份与恢复
- 防病毒系统
- SQL注入、JS注入
测试报告都包含哪些内容
- 测试背景说明
- 测试范围说明
- 测试环境说明
- 测试方法说明
- 测试结果结论
- 质量或分险评估
Alpha测试与Beta测试的区别
- Alpha测试是由一个用户在开发环境下进行的测试
- Beta测试在用户真实环境测试,通过后进入发布阶段
bug的类型都有哪些
- Bug,有代码编写错误导致的功能问题
- Defect即缺陷,实现与需求不一致
- Fault即故障,由于环境系统问题引起运行失败
- Error即错误,语法错误,逻辑错误,不易发现
说一下面向对象的概念
- 面向对象编程:简称oop,是一种程序设计思想
- 主要包括:类、继承、多态、实例、属性、方法
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
# Animal是类,相同事物的统称
class Animal(object):
def run(self):
print('Animal is running...')
# Dog类,继承于Animal
class Dog(Animal):
pass
puppy = Dog()
puppy.run()
# 多态,子类方法覆盖父类方法
class Cat(Animal):
def __init__(self, name):
# __name是属性
self.__name = name
def getName(self):
print(self.__name)
def run(self):
print('Cat is running....')
# limi是一个猫类的实例
limi = Cat("limi")
# run是实例的一个方法
limi.run()
# getName方法
limi.getName()
输出:
Animal is running...
Cat is running....
limi
什么是进程、线程、协程
- 进程:独立数据空间。进程间不共享数据,系统调度
- 线程:执行程序的最小单元,进程内线程间共享资源,系统调度
- 协程:程序员调度,分解一个线程成为多个“微线程”
进程
# 进程
from multiprocessing import Process
def foo(i):
print("This is Process", i)
for i in range(5):
p = Process(target=foo, args=(i,))
p.start()
输出:
This is Process 0
This is Process 1
This is Process 2
This is Process 3
This is Process 4
线程
# 线程
import threading
def show(i):
print('This is Thread', i)
for i in range(5):
t = threading.Thread(target=show, args=(i,))
t.start()
输出:
This is Thread 0
This is Thread 1
This is Thread 2
This is Thread 3
This is Thread 4
协程
# 协程
import gevent
def foo():
print("start_foo")
gevent.sleep(2)
print("end_foo")
def bar():
print("start_bar")
gevent.sleep(0)
print("end_bar")
gevent.joinall({
gevent.spawn(foo),
gevent.spawn(bar),
})
如何使用python实现socket编程
- Socket又称套接字,应用程序通过套接字向网络发出请求
- 应用程序通过套接字应答网络请求
- 使主机间或者一台计算机上的进程间可以通讯
socket-server.py
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
# 服务端
# 导入socket模块
import socket
# 创建socket对象
s = socket.socket()
# 绑定端口
s.bind(("127.0.0.1", 6666))
# 等待客户端连接
s.listen(5)
while True:
# 建立客户端连接
c, addr = s.accept()
print('连接地址:', addr)
c.send("Welcome")
# 关闭连接
c.close()
socket-client.py
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
# 导入模块
import socket
s = socket.socket()
s.connect(("127.0.0.1", 6666))
server_reply = s.recv(1024)
print(server_reply)
s.close()
什么是lambda函数
- 匿名函数,即没有函数名的函数
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
# 计算平方
def square(x):
return x ** 2
print(square(10))
# lambda表达式
r = lambda x: x ** 2
print(r(10))
输出:
100
100
tuple和list什么区别
- tuple为元组,list为列表
- tuple的元素不可改
- list的元素可修改
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
tuple_a = (1, 2, 3, 4, 5)
list_b = [1, 2, 3, 4, 5]
tuple_a[0] = 10
list_b[0] = 10
print(tuple_a)
print(list_b)
range函数的用法
- 返回一系列连续增加的整数
- 工作方式类似于分片
- 可以生成一个列表对象
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
# range生成从0到100的列表
alist = range(0, 100)
print(alist)
# 设置步长为2
blist = range(2, 101, 2)
print(blist)
字符串的拆分方法有哪些
- string对象的split方法,不允许有多个分隔符
- 函数re.split(),允许为分隔符指定多个正则模式
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
line = "I am super man!"
# string的split方法
print(line.split(" "))
# re的split方法
import re
print(re.split("[m]", line))
输出:
['I', 'am', 'super', 'man!']
['I a', ' super ', 'an!']
单引号、双引号、三引号的区别
- 单引号,双引号没有区别,都可以用来表示字符串
- 三引号,字符串可以直接换行
*args,**kwargs什么作用?
- *args,可变的参数列表
- **kwargs,键值对参数列表
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
# args
# def test_args(first, *args):
# print(first)
# for v in args:
# print("args %s" % v)
#
#
# test_args(1, 2, 3, 4, 5)
# kwargs
def test_kwargs(first, *args, **kwargs):
print(first)
for v in args:
print("args %s" % v)
for k, v in kwargs.items():
print("kwargs", (k, v))
test_kwargs(1, 2, 3, 4, 5, k0=4, k1=5, k2=6)
输出:
1
args 2
args 3
args 4
args 5
kwargs ('k0', 4)
kwargs ('k1', 5)
kwargs ('k2', 6)
python中pass语句的作用
- 占位符,实现一个空函数
re模块中match和search方法的不同
- search,扫描整个字符串查找匹配
- match,只在字符串的开始位置匹配
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
import re
s1 = "helloworld,helloworld"
w1 = "hello"
w2 = "world"
# search扫描整个字符串
print(re.search(w1, s1))
# print(re.search(w1, s1).group())
# match只在字符串开始位置匹配
print(re.match(w1, s1))
# print(re.match(w1, s1).group())
解释一下WSGI和FastCGI的关系
- CGI:公共网关接口(CommonGateway Interface)
- HTTP服务器与机器上的程序进行交互的一种工具
- 程序须运行在网络服务器上,和语言无关
解释一下WSGI和FastCGI的关系
- WSGI:Python Web Server Gateway Interface
- Python 应用程序和WEB服务器之间的一种接口
- FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着
python是如何操作文件
- 打开文件
- 写入或读取数据
- 关闭文件
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
# 写文件
f = open('test.txt', 'wt')
f.write("hello world")
f.close()
# 使用with,追加内容,不用关系文件关闭问题
with open("test.txt", 'at') as f:
f.write("\nhello mook")
# 读取文件
with open("test.txt", 'rt') as f:
print(f.read())
python的内存管理机制
- 引用计数
- 垃圾回收
- 内存池
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
from sys import getrefcount
# 引用计数
a1 = 1000000
a2 = 1000000
del a1
del a2
print(id(a1))
print(id(a2))
# 检验a1和a2是同一个东西
print(a1 is a2)
# 获取a2的引用计数
print(getrefcount(a1))
dict的items与iteritems区别
- itmes方法以列表方法返回,返回时没有特殊顺序
- iteritems方法类似,但返回的是一个佚代器对象
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
test1 = {'key1': 2, 'key1': 3, 'key1': 4}
kv1 = test1.items()
# print(next(kv1))
kv2 = test1.iteritems()
print(next(kv2))
print(next(kv2))
print(next(kv2))
基于python常问算法有哪些?
- 排序
从小到大排序:sorted(list)
从大到小排序:sorted(list,reverse=True)
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
alist = [0, 10, 88, 19, 9, 1]
print(sorted(alist))
print(sorted(alist, reverse=True))
alist.sort()
print(alist)
alist.sort(reverse=True)
print(alist)
输出:
[0, 1, 9, 10, 19, 88]
[88, 19, 10, 9, 1, 0]
[0, 1, 9, 10, 19, 88]
[88, 19, 10, 9, 1, 0]
- 冒泡
比较相邻的元素,如果第一个比第二个大,就交换
一轮遍历,每两相邻元素,重复1,最大放队尾
不包括已经排队尾,重复2
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
# 冒泡排序
def bubble_sort(list):
# 获取数组长度
count = len(list) - 1
# N个元素遍历N次
for index in range(count, 0, -1):
# 第一个和第i+1个依次对比
for sub_index in range(index):
# 最大的元素冒上去
if list[sub_index] > list[sub_index + 1]:
list[sub_index], list[sub_index + 1] = list[sub_index + 1], list[sub_index]
return list
alist = [0, 10, 88, 19, 9, 1]
print(bubble_sort(alist))
输出:
[0, 1, 9, 10, 19, 88]
- 快排
从列表中挑出一个元素,作为基准值key
所有小于key的元素放左边,所有大于key的元素放右边
分别递归左侧列表,右侧列表
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
# 快速排序
def quick_sort(lists, left, right):
# 递归过程中,发现left和right一致时,停止递归,直接返回列表
if left >= right:
return lists
# 定义游标
low = left
high = right
# 取参考标志,最左边的元素
key = lists[low]
while low < high:
# 从最右侧向左,依次和标志元素对比,如果右侧的元素大于标志元素
while low < high and lists[high] >= key:
# 右侧减1
high = 1
# 否则low赋high值
lists[low] = lists[high]
# 从最左侧向右,依次和标志元素对比,如果左侧的元素小于标志元素
while low < high and lists[low] <= key:
# 右侧加1
low += 1
# 否则high赋low值
lists[high] = lists[low]
# 最后给high位置符值
lists[high] = key
# 处理左侧元素
quick_sort(lists, left, low - 1)
# 处理右侧元素
quick_sort(lists, low + 1, right)
return lists
alist = [0, 10, 88, 19, 1, 7]
print(quick_sort(alist, 0, 6))
- 堆排序
堆排序指利用的数据结构设计的一种排序算法
堆近似一个完全二叉树结构
子结点的键值小于(或者大于)它的父节点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b7KC5K4a-1633789899133)(/static/upload/bigpic/20210629/1624975894689377409.png)]
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
def heap_sort(lst):
def sift_down(start, end):
"""最大堆调整"""
root = start
print("root %d start %d end %d" % (root, start, end))
while True:
child = 2 * root + 1
print("child index: %d" % child)
# 终止条件,孩子的索引值超过数组最大长度
if child > end:
break
print("lst child value:%d" % lst[child])
# 确定最大的孩子节点的索引值
if child + 1 <= end and lst[child] < lst[child + 1]:
child += 1
print("child+1 index: %d" % child)
# 孩子节点最大值和根节点交换
if lst[root] < lst[child]:
lst[root], list[child] = lst[child], lst[root]
print("lst root %d" % lst[root], "lst child %d" % lst[child])
root = child
print("root %d" % root)
else:
break
print("--------创建最大值--------")
# 创建最大堆
print(xrange((len(lst) - 2) // 2, -1, -1))
for start in xrange((len(lst) - 2) // 2, -1, -1):
print("---->Loop start %d" % start)
sift_down(start, len(lst) - 1)
print(lst)
print("--------排序过程----------")
# 堆排序
for end in xrange(len(lst) - 1, 0, -1):
# 首尾交换
lst[0], lst[end] = lst[end], lst[0]
# 剩余重新堆排序
sift_down(0, end - 1)
print(lst)
return lst
alist = [70, 60, 12, 40, 30, 8, 10]
print(heap_sort(alist))
- 二分查找
二分查找又称折半查找
必须采用顺序存储结构
必须按关键字大小有序排列
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
alist = [0, 1, 10, 88, 19, 9, 1]
def binary_search(arr, start, end, hkey):
if start > end:
return -1
mid = start + (end - start) / 2
if arr[mid] > hkey:
return binary_search(arr, start, mid - 1, hkey)
if arr[mid] < hkey:
return binary_search(arr, mid + 1, end, hkey)
return mid
alist = sorted(alist)
print(alist)
print(binary_search(alist, 0, 6, 9))
- 素数
素数又称质数
0,1不是素数
除了1和它自身外,不能被其他自然数整除的数
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
# 0,1不是素数
# 除了1和它自身外,不能被其他自然数整除的数
def is_prime(n):
if n <= 1:
return False
for i in range(2, n - 1):
if n % i == 0:
return False
return True
for i in range(0, 100):
if is_prime(i):
print(i)
基础命令
- cd 切换目录
- ls -l 列出文件详细信息;ls -a 列出当前目录下所有文件
- touch 创建文件;mkdir 创建目录
- echo 创建带有内容的文件
- cat 查看文件内容
- cp 拷贝
- mv 移动或重命名
- rm -r 递归删除;rm -f 强制删除
- wc统计文本中行数、字数、字符数
- grep 在文本文件中查找某个字符串
- tree 显示目录结构
- ln 创建软链
- more、less 分页显示文本内容
- head、tail显示文件头尾内容
网络命令
- curl 利用URL规则在命令下工作的文件传输工具
- netstat 显示网络状态信息
- telnet 用于登录主机
系统命令
- ping 测试网络连通
- man 查看帮助
- kill 杀死进程
- top 动态显示当前耗费资源最多进程信息
- ps 显示瞬间进程状态
- df 查看磁盘大小 df -h 带有单位显示磁盘信息
OSI七层模型指的是哪些内容
- 物理层,建立、维护、断开物理连接
- 数据链路层,逻辑链接、硬件地址寻址、差错校验
- 网络层,逻辑地址寻址,不同网络之间的路径选择,IP
- 传输层,传输数据的协议,TCP、UDP
- 会话层,建立、管理、终止会话,本地与远程主机的会话
- 表示层,数据的标示、安全、压缩、JPEG、ASCII等
- 应用层,与最终用户的接口,HTTP、HTTPS、SMTP等
http协议中get、post的区别
- 功能差异
- 数据传输
- 安全性
tcp和udp的区别
[image:C0E62692-F54F-4E32-AAD0-DC732B83FBBF-275-00022443262E7424/95E38541-6E13-492C-B105-F0E2CE67127C.png][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UF7CP2KT-1633789899136)(/static/upload/bigpic/20210629/1624975957710395955.png)]
TCP连接三次握手具体过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fm0MRxQ9-1633789899138)(/static/upload/bigpic/20210629/1624975975490471642.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jrLnGsXp-1633789899141)(/static/upload/bigpic/20210629/1624975991419512239.png)]
socket建立连接的过程
- 服务器建立监听,socket,bind,listen
- 客户端发送请求,connect,send
- 连接确认,accept, response
操作系统相关问题
- 进程与线程的区别?
进程:独立数据空间。进程间不共享数据,系统调度
线程:执行程序的最小单元,进程内线程间共享资源,系统调度
一个进程可以有多个线程,多个线程也可以并发执行
- 进程都有哪些状态?
就绪状态:已获除处理以外所需资源,等待分配处理机资源
运行状态:占用处理机资源运行,此状态进程数<=CPU数
阻塞状态:进程等待某种条件,在条件满足之前无法执行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Ew7TpuZ-1633789899142)(/static/upload/bigpic/20210629/1624976019551169281.png)]
- 进程同步与互斥的区别?
互斥:某一资源同时只允许一个访问者对其进行访问
具有唯一性和排他性
互斥无法限制访问者对资源的访问顺序,即访问是无序的
同步:基于互斥,经其他机制实现访问者对资源的有序访问
大多数情况下,同步已经实现了互斥,写入资源是互斥的
少数情况下,可以允许多个访问者同时访问资源
- 进程间通信都包括哪些?
管道:半双工通方式,数据单项流动,父子进程间
命名管道:半双工通信方式,无亲缘关系进程间通信
信号量:是计数器,锁机制,控制多进程对资源访问
消息队列:消息链表,存放在内核中消息队列标识符标识
信号:比较复杂的通信方式,通知进程某个事件已经发生
共享内存:映射一段能被多个进程可访问的内存
- 进程的调度算法都有哪些?
先来先服务
短作业服务优先
时间片轮转调度算法
高响应优先
优先权调度算法
多级队列调度算法
- 死锁产生的原因?
资源竞争;进程推进顺序不当
必要条件:互斥,不剥夺,请求与保持,环路等待
预防死锁:破坏四个必要条件之一
- 页面的置换算法都有哪些?
最佳置换算法
先进先出置换算法
最近最久未使用置换算法
Clock置换算法,也叫最近未使用算法
最少使用置换算法
- makefile的作用是什么?
定义规则,指定哪些文件先翻译、后编译、重新编译
Makefile的好处,自动化编译
makefile需要make工具解释执行
- 什么是虚存、实存、共享内容?
虚存(VIRT=SWAP+RES):进程“需要的”虚拟内存大小
包括进程使用的库、代码、数据,以及malloc、new分配的堆空间和分配的栈空间等
申请10MB,使用1MB,增长10MB
实存(RES=CODE+DATA):
包括使用中的malloc、new分配的堆空间和分配的栈空间,但不包括swap out量
申请10MB,使用1MB,增长1MB
共享内存(SHR):自身,也包括其他进程的共享内容
进程只使用了几个共享库的函数,但包含真个共享库大小
某个进程所占的物理内存大小:RES - SHR
Fiddler工具都有哪些功能
- 如何抓取手机包
- 如何配置fake response、fake request
- 数据包request、response中的字段含义
- 如何实现慢网速
- 如果抓取的数据过多怎么处理
- 模拟不同的状态吗,200、302、404、502
Android系统相关的问题
- Android的四大组件是什么?
Activity:程序与用户的交互窗口
Service:在程序后台,完成用户的操作
ContentProvider:提供数据的统一访问格式
BroadcastReceiver:应用程序之间传输信息的机制
- Activity的生命周期是什么?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-010j6TPI-1633789899144)(/static/upload/bigpic/20210629/1624976039543254725.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Y8sEjQY-1633789899145)(/static/upload/bigpic/20210629/1624976053908291096.png)]
- 什么是ANR?
ANR:Application Not Responding
Actiivity的最长执行时间是5秒
用户可以选择“等待”让程序继续运行,或“强制关闭”
- Android常见的五种布局是什么?
FrameLayout(框架布局)
LinearLayout(线性布局)
AbsoluteLayout(绝对布局)
RelativeLayout(相对布局)
TableLayout(表格布局)
- Android中动画有哪几种类型?
Tween动画,组件移动、缩放、透明度的变化
Frame动画,通过顺序播放来实现,类似电影
ADB相关的问题?
- 如何重启adb服务?
adb kill-server # 停止服务
adb start-server # 启动服务
- App的安装与卸载
adb -s <devicename> install <path-to-apk> # 安装
adb -s <devicename> install -r <path-to-apk> # 安装
adb -s <devicename> uninstall <packagename> # 卸载
- 如何在电脑和手机之间传输数据?
adb push *.apk /data/local/tmp/*.apk
adb pull /data/local/tmp/*.apk *.apk
- 如何静默安装App?
adb push *.apk /data/local/tmp/*.apk
adb shell pm install -f /data/local/tmp/*.apk
- 如何使用adb启停一个App?
adb shell am start -W -S package/activiy
adb shell am force-stop package
- 如何通过某个关键词查找已安装的包?
adb shell pm list package -f keyword
adb shell pm list package -3 keyword
adb shell pm list package -i keyword
- 如何截屏、录屏?
adb shell screencap /data/local/tmp/screen.png
adb shell screenrecord /data/local/tmp/demo.mp4
- 如何抓取logcat日志?
adb logcat
adb shell logcat
- 如何获取当前的cpu、内存状态?
adb shell dumpsys meminfo package
adb shell dumpsys cpuinfo | findstr package
Monkey相关的问题?
- Monkey进行压力测试的命令?
adb shell monkey -p <packagename> <count>
- 如何重现Crash、ANR过程?
添加参数 -s seed
- 如何提取Crash、ANR的信息?
将monkey执行过程中的日志重定向到文件
测试版App连接第三方统计平台
- 如何设置monkey运行8个小时?
添加参数 --throttle
- 在Crash/ANR后,如何继续执行?
添加忽略Crash参数 --ignore-crashes
添加忽略ANR参数 --ignore-timeouts
- 如何让monkey执行指定的事件?
触摸事件—pct-touch
动作事件—pct-motion
轨迹球事件—pct-trackball
基本导航事件—pct-nav
主要导航事件—pct-majornav
系统导航事件—pct-syskeys
应用启动事件—pct-appswitch
其他类型事件—pct-anyevent
Instrumentation
- Instrumentation原理是什么?
[image:40185C44-D79C-4C13-A9BA-38B7027D780C-275-0002541F1D5DB1C5/3D642E82-B0EA-48D5-BF0B-920C1EDEF971.png][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JN0E4RVu-1633789899147)(/static/upload/bigpic/20210629/1624976313744973130.png)] - Instrumentation测试是什么?
功能性测试
Activity生命周期的测试
模拟数据库操作的测试和兼容性测试
- 什么情况使用Instrumentation?
使用Java JUnit框架
需要进行白盒测试时
需要使用mock技术模拟系统对象时
UIAutomator
- UIAutomator原理是什么?
UIAutomator是Android UI自动化测试工具
不需要源码,基于Java开发语言
UiDevice,UiSelector,UiScrollable,UiObject,UiCollection
- UIAutomator可以测试什么?
APP UI层的交互操作
不需要源码,可以模拟跨进程过程
基于Java JUnit框架,黑盒UI自动化
- 如何识别App视图内的元素?
UiAutomatorViewer
可以识别元素的id、classname、bounds等
Selendroid&Robotium
- Selendroid的原理是什么?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j67Yy2Yo-1633789899148)(/static/upload/bigpic/20210629/1624976294909294703.png)] - Selendroid四大组件:
Selendroid Client:Webdriver + 移动特性的实现
Selendroid Server:一个Instrumentation APK
AndroidDriver-App:一个WebViewActivity,即浏览器
Selendroid-Standalone:大总管,负责准备环境
- Robotium的原理是什么?
基于Instrumentation进行封装,实现的Android测试框架
封装了一个Solo类库,提供自动化测试API
由于是基于Instrumentation,测试时需要源码
Appium
- 什么是Appium?
一个开源的移动端UI自动化测试框架
- Appium的理念是什么?
不需要App源码
不局限于语言或者框架
接口统一,不需要重复开发
必须是开源的
- Appium相关的概念都有哪些?
C/S架构,Appium核心是一个web服务器
Session,客户端初始化session与服务端交互
Desired Capabilites,初始化时的键值对组合
Appium Server,操作与驱动手机的
Appium Client,支持多语言调用
- Appium环境都包括哪些内容?
Android SDK、JDK、Appium
Pycharm、Python环境
库:Selenium、Appium-Python-Client
- Appium都支持哪些开发语言?
Java、Javascript、PHP、Python
Ruby、C#、Perl、Object C
- Appium初始化时都需要配置哪些内容?
platformName,目标设备平台Android/iOS
platformVersion,目标设备的平台版本
appPackage,App包名(Android)
AppActivity,App Activity名称(Android)
automationName,自动化启动类型Selendroid/Appium
unicodeKeyboard,是否使用Appium输入法
resetKeyboard,是否恢复默认键盘
- Appium测试Native App的原理是什么?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-49uX29H9-1633789899149)(/static/upload/bigpic/20210629/1624976113411971708.png)] - 如何自动化测试Native App?
- 元素的定位、识别工具?
第一个选择,使用UIAutomatorViewer
第二个选择,使用Appium的Inspector
- 定位元素的API都有哪些?
find_element_by_accessibility_id
find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_class_name
- 脚本的编写规则
LOVE规则
L:Locate定位
O:Operate操作
V:Verify验证
E:Exception异常的处理
- 初始化注意事项
不需要指定App的包路径
默认使用Appium驱动
如果需要输入中文,需要添加输入法相关的配置
- Appium测试Hybrid App的原理是什么?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DAmCXebJ-1633789899150)(/static/upload/bigpic/20210629/1624976138613678463.png)] - 如何自动化测试Hybrid App?
- 元素的定位、识别工具?
Native部分,UIAutomator或者Appium Inspector
WebView部分,Chrome浏览器的调试模式
- 定位元素的API都有哪些?
find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_tag_name
find_element_by_class_name
find_elements_by_id
find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_tag_name
find_elements_by_class_name
- 脚本的编写规则
S-LOVE规则
S:Switch
L:Locate定位
O:Operate操作
V:Verify验证
E:Exception异常的处理
- 初始化注意事项
需要明确指定驱动名称为:Selendroid
需要明确指定App的路径,因为需要重签名
- Appium测试iOS App的原理是什么?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w7UtZmk7-1633789899151)(/static/upload/bigpic/20210629/1624976161276332783.png)]
如何使用selenium测试WEB页面?
- 都需要准备哪些环境?
工具:Pycharm、chrome
包:selenium、Python
webdriver:chrome driver/firefox driver/ie driver等
- 元素识别工具是什么?
firefox或者chrome的调试工具
- 元素定位的方法都有哪些?
find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_tag_name
find_element_by_class_name
find_elements_by_id
find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_tag_name
find_elements_by_class_name
如何使用Appium测试WAP页面?
- 都需要准备哪些环境?
IDE:PyCharm
包:Python、Selenium、Appium-python-client
工具:Appium、Chrome
- 元素的识别
chrome浏览器调试wap页面
- 脚本的编写
初始化时,指定browsername为:Browser
自动化测试代码和selenium代码相同
unittest原理
- unittest框架都包含哪些内容?
TestFirxture:setUp、TestCase、TearDown
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
import unittest
class MyTestCase(unittest.TestCase):
# 每条用例初始化
def setUp(self) -> None:
self.initdata = "hello imooc"
# 测试用例、以test开头
def test_something(self):
self.assertEqual("hello imooc", self.initdata)
# 每条用例执行完后释放资源
def tearDown(self) -> None:
pass
if __name__ == '__main__':
# 声明一个suite
suite = unittest.TestSuite()
# 从类加载用例集
cases = unittest.TestLoader().loadTestsFromTestCase(MyTestCase)
# 添加用例到suite
suite.addTests(cases)
# 声明TestRunner
myTestRunner = unittest.TextTestRunner(verbosity=2)
# 执行Runner
myTestRunner.run(suite)
TestCase
TestSuite
TestRunner
DDT-数据驱动
- 什么是数据驱动?
数据驱动测试,即黑盒测试,又称为功能测试
数据驱动单元测试为数据源中的每行重复进行一种单元测试
数据驱动单元测试,常用情况是使用多个输入值测试API
- DDT的原理是什么?
Python下的数据驱动框架名称也叫DDT(Data-Driven Tests)
效果:使用多个数据运行一条用例,使其表现为多条用例
原理:通过Python的装饰器、装饰每条用例
- 如何使用DDT测试搜索功能?
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# author by : yuxiangShi
# tell by: 18538187569
import unittest
from appium import webdriver
from ddt import ddt, data
import time
@ddt
class MyTestCase(unittest.TestCase):
# 初始化
def setUp(self) -> None:
desired_caps = {'platformName': 'Android', 'platformVersion': '5.1', 'deviceName': '192.168.56.102:5555',
'browerName': 'Browser', 'unicodekeyboard': 'True', 'resetKeyboard': 'True'}
self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
# 释放资源
def tearDown(self) -> None:
self.driver.quit()
@data(u"Android 专项测试 Python篇", u"Javascript")
def test_searchkeyword(self, keyword):
# 打开首页
self.driver.get('http://www.imooc')
# 等待加载完成
time.sleep(3)
# 定位输入框
input = self.driver.find_element_by_xpath("/html/body/header/div/input")
# 定位搜索按钮
button = self.driver.find_element_by_xpath("/html/body/header/div/form/div/div/button")
# 点击搜索
button.click()
# 等待页面加载完成
time.sleep(3)
# 定位搜索结果的首条
result0 = self.driver.find_element_by_xpath('//*[@id="pages-container"]/div/div[1]/dl/dd[1]/a/div/p[1]')
# 验证包含关键词
self.assertTrue(keyword in result0.text)
if __name__ == '__main__':
suite = unittest.TestSuite()
cases = unittest.TestLoader().loadTestsFromTestCase(MyTestCase)
suite.addTest(cases)
myTestRunner = unittest.TextTestRunner(verbosity=2)
myTestRunner.run(suite)
- 数据驱动测试的意义?
代码复用率高,一次编写多条数据复用逻辑
异常排查效率高,测试执行隔离,数据间无影响
代码可维护性高,提高代码的易读性
Lettuce-行为驱动
- 什么是行为驱动?
行为驱动开发,Behavior-Driven Development,简写BDD
在软件工程中,BDD是一种敏捷开发的技术
- Lettuce的原理是什么?
Lettuce是基于Python语言的行为驱动测试框架
Lettuce将测试用例和自动化测试代码分离
Lettuce写测试用例就像写文本一样清晰
- 行为驱动的实现?
行为驱动测试实例
KDT-关键词驱动
- 什么是关键词驱动?
关键词驱动测试也称为表格驱动测试或行动驱动测试
它将创建测试程序的步骤分为规划及实现二个阶段
关键词驱动使不懂代码的人可以完成自动化过程
- Robot Framework的原理是什么?
基于RIDE可视化工具,导入AppiumLibrary
使用AppiumLibrary中提供的关键词,实现用例过程
使用RIDE完成用例的执行与结果的管理
- 关键词驱动的实现?
API测试框架
- 如何实现一个API测试框架
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Ey62wL7-1633789899152)(/static/upload/bigpic/20210629/1624976193871749078.png)]
Python Requests API自动化
- 如何使用Python Request发送Get请求?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3KmfKrYx-1633789899153)(/static/upload/bigpic/20210629/1624976207803766321.png)] - 如何使用Python Request发送Post请求?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qG4d7S2o-1633789899154)(/static/upload/bigpic/20210629/1624976223779743111.png)] - 如何实现一个API测试框架?
持续集成的理念
- 说一下什么是持续集成?
持续集成是指开发阶段,对项目进行持续性
自动化编译、测试,以达到控制代码质量的手段
持续集成是一种软件开发实践
- 持续集成都包括哪些内容?
开发人员、版本控制
CI服务器、构建脚本
反馈机制、集成构建
- 持续集成的意义是什么?
减少分险、减少重复过程
任何时间、任何地点生成可部署的软件
增强项目可见性、建立团队对开发产品的信心
持续集成工具配置
- 你都用过哪些持续集成的工具?
Jenkins、Buildbot
Travis CI、Strider
Go、Integrity
- 如何搭建Jenkins持续集成平台?
下载Jenkins.war
命令行运行:java -jar jenkins.war
在浏览器窗口打开:http://localhost:8080
- 使用Jenkins都需要做哪些配置?
系统级配置
工程级配置
持续集成工具应用
- 如何配置一个App打包的过程?
- 如何持续执行脚本?
- 如何使用持续集成工具执行Monkey?
服务端测试的工具
- 服务端的压力工具都包括哪些?
LoadRunner
JMeter
自主研发的工具
- 服务端的压力测试都需要监控哪些指标?
CPU
内存(虚存、实存)
QPS、平均相应时间
- 如何开展服务端的压力测试?
搭建服务端模块、并启动服务
监控进程相关指标,内存、CPU
监控模块的执行情况,QPS、平均相应时间
收集数据并进行分析,生成曲线图
根据分析结果,得出测试结论
App兼容性测试
- App兼容性测试都考虑哪些因素?
系统版本(Android&IOS平台,不同版本)
分辨率(小屏、大屏、全屏)
手机品牌(华为、小米、OPPO、VIVO等)
- WAP兼容性测试都考虑哪些因素?
不同平台的不同浏览器(safari、chrome等)
分辨率(小屏、大屏、全屏)
转发到QQ、微信、微博等第三方平台
- PC页面兼容性测试都考虑哪些因素?
操作系统(常用windows、Mac os、平板电脑)
浏览器(IE系列、firefox、chrome等)
分辨率(笔记本、台式机、窗口缩放等)
APP的bug调试
- 调试APP相关的bug常用哪些工具?
网络相关工具,fiddler、wareshark、Charles
adb、am、logcat等
云平台,bug复现
WAP网页的bug调试
- 调试WAP页面相关工具有哪些?
Chrome调试工具,可设置移动App UA
WINRE,Web Inspector Remote
PC网页的bug调试
- 调试PC页面相关工具有哪些?
Chrome调试工具
火狐的firebug
博客来源:雨夜的博客