json.dump()、json.dumps()、json.load()、json.loads()说明:
1.json.dump():将python对象以json字符串格式写入文件
2.json.dumps():将python对象转化成json字符串
3.json.load():获取文件里的json字符串内容为dict
4.json.loads():将json字符串转化为dict
Git
工作区 暂存区 本地仓库 远程仓库
红色 绿色(已添加到暂存区,未提交)
蓝色(提交过有修改)
git add git commit git push
Jenkins
定时:五星大法 分 时 年 月 日 30 18 * * 1-5
pipeline steps:pipeline syntax
pipeline{
agent{
node{}
}
paremeters{}
environment{}
stages{
stage(){
options{timeout(time: 100, unit: 'MINUTES')}
when{}
steps{
script{}
}
}
}
post{
always{
script{}
}
}
}
正则
https://regex101.com/
.:除了换行\n之外的任意单个字符
+:匹配前面的表达式一次或多次
*:匹配前面的表达式0次或多次
?:匹配前面的表达式0次或一次,非贪婪模式
():分组
[0-9]:数字
[a-zA-Z]:字母
\w:匹配字母、数字、下划线,等价于 [A-Za-z0-9_]
\S:非空字符
\s:空字符
$:结尾
^:开始
闭包函数
1.什么是闭包函数:一个函数的返回值是另外一个函数,返回的函数调用父函数内部的变量,如果返回的函数在外部被执行,就产生了闭包
2.闭包函数的作用:使函数外部能够调用函数内部放入属性和方法
3.闭包函数的优缺点:
优点:使函数外部能够调用函数内部放入属性和方法
缺点:闭包操作导致整个函数的内部环境被长久保存,占用大量内存
1.什么是反射:
把字符映射到实例的变量或实例的方法,然后可以去执行调用、修改
反射的本质(核心):基于字符串的事件驱动,利用字符串的形式去操作对象/模块中成员(方法、属性)
2.反射的四个重要方法
1)getattr获取对象属性/对象方法
2)hasattr判断对象是否有对应的属性及方法
3)delattr删除指定的属性
4)setattr为对象设置内容
创建xlsx表格并写入数据
from openpyxl import Workbook
from openpyxl import load_workbook
1.创建excel
Workbook(excel_path).save(excel_path)
2.加载excel
work_book = load_workbook(excel_path)
3.创建sheet
work_book.create_sheet("sheet_name")
4.选择操作sheet
work_sheet = work_book["sheet_name"]
5.写入数据
for row in len():
for column in len():
work_sheet.cell(row,column).value = data[row,row]
6.work_book.save()
7.work_book.close()
数据类型
基本数据类型
1.数字
整数 int 相对精确
浮点数 float 不精确,from decimal import Decimal
复数
2.字符串 string
3.布尔
容器数据类型
4.列表 list 有序
5.元组 tuple 不可表的列表 有序
6.字典 dict key不可重复、不可变,有序
7.集合 set key_value一致的字典,不可重复,无序,放入可哈希内容(不可变数据类型)
基本数据类型和元组不可变
列表、字典、集合可变
浅拷贝和深拷贝只针对可变对象
浅拷贝:
1.效率高、开销小、数据不隔离
2.针对不可变数据类型
单层源对象:不会生成新的内存地址
多层源对象:
里面的元素不可变:不会生成新的内存地址
里面的元素可变:不会生成新的内存地址
3.可变数据类型
单层源对象:会生成新的内存地址
多层源对象:
里面的元素不可变:里面的元素不会生成新的内存空间
里面的元素可变:里面的元素不会生成新的内存空间
深拷贝:
1.效率低、开销大、数据隔离
2.针对不可变数据类型
单层源对象:不会生成新的内存地址
多层源对象:
里面的元素不可变:不会生成新的内存地址
里面的元素可变:会生成新的内存地址
3.可变数据类型
单层源对象:会生成新的内存地址
多层源对象:
里面的元素不可变:里面的元素不会生成新的内存空间
里面的元素可变:里面的元素会生成新的内存空间
遇到的异常
1.IndexError:索引异常,下标越界
2.TypeError:数据类型错误
3.no module:未安装库,未找到库
4.no key word:未找到关键字
5.Reference before assignment:未赋值就引用
6.value error:无效传参,需要int传入了string
7.Python base error:'Could not find special module parser.dll ,windows未安装nacap软件
8.maximum limit of started keywords exceeded:关键字名称重复
每个字符出现的次数:
d = {}
for i in a:
d[i] = d.get(i,0) + 1
快速排序和冒泡排序的复杂度都是一样的,但是快速排序优于冒泡,快排只是找出最大值交换索引,冒泡是值交换改变了内存地址
冒泡排序是进行2层循环每次循环找出最大的值放到最后位置
快速排序是找一个基准值,所有比基准值大的放到右边,比基准值小的放到左边,区分结束后该基准值到了中间位置,递归地把"基准值前面的子数列"和"基准值后面的子数列"进行排序
函数参数
1.位置参数
2.关键字参数
3.不定长参数
*args 不定长位置参数
**kwargs 不定长关键字参数
变量的作用域:
1.L:local 局部变量
2.E:enclosed 闭包作用域 nonlocal
3.G:global 全局作用域,文件
4.B:builtin 内置作用域
BG不需要创造
LE通过定义函数来创造,判断、循环、类都不能创造作用域
内置函数
不需要导入直接使用的函数
数学运算
abs:求数值的绝对值
divmod:返回两个数值的商和余数
max:返回可迭代对象中的元素中的最大值或者所有参数的最大值
min:返回可迭代对象中的元素中的最小值或者所有参数的最小值
pow:返回两个数值的幂运算值或其与指定整数的模值
round:对浮点数进行四舍五入求值
sum:对元素类型是数值的可迭代对象中的每个元素求和
类型转换
int float complex str bool tuple list dict set range super object
ord:返回Unicode字符对应的整数
chr:返回整数所对应的Unicode字符
oct:将整数转化成8进制数字符串
hex:将整数转换成16进制字符串
序列操作
all:判断可迭代对象的每个元素是否都为True值
any:判断可迭代对象的元素是否有为True值的元素
filter:使用指定方法过滤可迭代对象的元素
map:使用指定方法去作用传入的每个可迭代对象的元素,生成新的可迭代对象
next:返回可迭代对象中的下一个元素值
reversed:反转序列生成新的可迭代对象
sorted:对可迭代对象进行排序,返回一个新的列表
zip:聚合传入的每个迭代器中相同位置的元素,返回一个新的元组类型迭代器
对象操作
help:返回对象的帮助信息
dir:返回对象或者当前作用域内的属性列表
id:返回对象的唯一标识符
hash:获取对象的哈希值
type:返回对象的类型,或者根据传入的参数创建一个新的类型
len:返回对象的长度
dir:查看对象的成员
反射操作
import:动态导入模块
isinstance:判断对象是否是类或者类型元组中任意类元素的实例
issubclass:判断类是否是另外一个类或者类型元组中任意类元素的子类
hasattr:检查对象是否含有属性
getattr:获取对象的属性值
setattr:设置对象的属性值
delattr:删除对象的属性
callable:检测对象是否可被调用
变量操作
globals:返回当前作用域内的全局变量和其值组成的字典
locals:返回当前作用域内的局部变量和其值组成的字典
交互操作
print:向标准输出对象打印输出
input:读取用户输入值
文件操作
open()
装饰器
property:标示属性的装饰器
classmethod:标示方法为类方法的装饰器
staticmethod:标示方法为静态方法的装饰器
lambda
模块导入、包导入
文件名符合变量名要求的,以.py结尾的文件
文件存在于sys.path路径下
文件夹包含模块
导入包先导入__init__模块
文件操作
f = open("file_name",mode="",encoding="utf-8")
w r
w如果文件不存在自动创建文件
f.read() 读取全部内容,str
f.readline() 读取一行内容 str
f.readlines() 以行的形式去去内容 list
f.write() 写入全部内容,传入字符串
f.writelines([]) 写入内容,传入列表
时间
import time
now = time.time() 时间戳
stand_time = time.localtime(now) 标准时间对象
format_time = time.strftime("%Y-%m-%d %H:%M:%S",stand_time) 字符串时间
stand_time = time.strptime(format_time,"%Y-%m-%d %H:%M:%S") 字符串时间转标准时间
now = time.mktime(stand_time) 标准时间转时间戳
import datetime
now = datetime.datetime.now() 标准时间对象
str_time = now.strftime("%Y-%m-%d %H:%M:%S")
now.timestamp() 得到时间戳
datetime.datetime.strptime(now,"%Y-%m-%d %H:%M:%S")
类方法、实例方法、静态方法的区别
1.静态方法不会自动传递任何参数,实例方法会自动传递类的实例,类方法会自动传递类本身
2.实例方法没有装饰器,类方法@classmethod装饰,静态方法@staticmethod装饰
3.使用上,实例方法需要实例化类,静态方法和类方法使用类名点
封装
_:类内部使用,绕过直接 _
__:本类内部使用,绕过 _类名.__
super
super(A,self) 不包含A
装饰器:
定义:接收函数并返回函数的函数
作用:对函数功能的扩展
使用:使用@函数名装饰函数
原理:自动将被装饰的函数当作参数传给装饰器函数执行,然后返回新的函数覆盖被装饰函数
装饰器带参:
被装饰函数有参数:在装饰器的返回函数里接收参数,然后传递给被装饰函数
装饰器带参:创建一个新函数接收参数,返回原来的装饰器
def logs(level):
def wrap(func):
def f(*args,**kwargs):
print(f"{level}:{func.__name__}调用开始前")
func(*args,**kwargs)
print(f"{level}:{func.__name__}调用结束后")
return f
return wrap
@logs("debug")
def add(a,b):
print(f"add is calling,a={a},b={b}")
add(1, 2)
生成器:生成器属于迭代器
如果函数中有yield关键字,其调用结果则返回一个生成器
生成器是一个可迭代对象,可以被for循环遍历使用
在遍历是才进行计算返回
模块导入、包导入
文件名符合变量名要求的,以.py结尾的文件
文件存在于sys.path路径下
文件夹包含模块
导入包先导入__init__模块
类没有创建作用域,但是创建了命名空间将相同的变量名称隔离了
@property
def f(self):
pass
@f.setter
def f(self,value)
self._ = value
f相当于类的属性,调用时不用加括号,自动调用
PyMySQL
connect = PyMySQL.connect(host,port,user,password)
cursor = connect.cursor()
cursor.execute(sql)
value = cursor.fetchall()
什么是接口测试
测试项目和项目之间、模块和模块之间、前端和后端之间的数据交互以及权限鉴定
pytest+requests+allure+yaml
pytest插件
pytest-html
pytest-xdist
pytest-rerunfailures
pytest-ordering
allure-pytest
pytest-base-url
pyyaml
pytest用例规则
1.模块名必须是test_开头或_test结尾
2.类名必须是Test开头,不能有init方法
3.方法名必须是test开头
pytest初始化文件
[pytest]
addopts = -vs -m "smoke or product" --alluredir=./temps --clean-alluredir
testpaths = ./testcases
python_files = test_*.py
python_classes = Test*
python_functions = test_*
base_url =
markers =
smoke:冒烟用例(在方法上添加@pytest.mark.smoke)
product:商品管理
pytest运行参数
-vs 详细调试
-n=2 多线程
--reruns=2 失败用例冲跑2次
-maxfail=2 出现2次失败停止
-x 出现1次失败就停止
--html=./reports/report.html
-m "smoke" 执行指定标记的用例
跳过测试用例
无条件跳过
在方法上添加@pytest.mark.skip(resason="")
有条件跳过
@pytest.mark.skipif(判断条件,reason="")
用例执行顺序
默认按照文件夹、模块、方法从上到下执行
@pytest.mark.run(order=1)修改执行顺序
用例前后置
setup teardown
setup_class teardown_class
部分前后置fixture
定义:
coftest.py
使用@pytest.fixture(scope="",autouse=,params=[],ids=[],name="")修饰函数,函数就变成了固件,yield唤醒后置
使用:
scope="function":
autouse=True:所有函数自动使用
autouse=False:需要在函数传输这个fixture函数名
scope="class":
autouse=True:所有类自动使用
autouse=False:在类上添加@pytest.mark.usefixtures("fixture函数名")
scope="module"
autouse=True:自动对模块下的多个类起作用
scope="session"
sutouse=True:当前session,在整个会话最前和最后执行一次
params=[]:
列表里有几个元素用例就会执行几次
传值:在fixture函数里添加参数(request),然后yield返回request.param
@pytest.fixture(scope="function",autouse=False,arams=[])
def exec_sql(request):
yield request.param
ids=[],必须和params一起使用:
参数化时参数的别名
name="":
fixture的别名,如果添加了固件的别名,使用时一定要使用固件别名
pytest执行顺序
1.先找当前目录下的coftest.py里面的类级别夹具
2.再找pytest.ini下的用例目录
3.再找用例目录下的coftest.py里面的类级别夹具
4.setup类级别
5.当前目录、用例目录下coftest.py里的函数级别夹具
6.执行测试用例
7.teardown函数界别、coftest函数级别
8.teardown类级别、coftest类级别
pytest集成allure
1.下载allure-pytest库
2.现在allure zip包,解压后配置环境变量
3.生成allure临时文件--alluredir=./temps --clean-alluredir
4.生成allure报告os.system("allure generator ./temps -o ./reporet --clean")
修改allure logo
1.打开allure/config/allure.yml配置文件,添加-custom-logo-plugin/static
2.将logo放在plugins/custom-logo-plugin/static目录下
3.打开plugins/custom-logo-plugin/static/style.css,修改样式
用例描述:
import allure
@allure.epic("项目名称")
@allure.feature("模块名称")
class TestProduct(object):
@allure.story("接口名称")
@allure.severity(allure.severity_level.NORMAL) #优先级别
@allure.link("接口链接")
@allure.issue("bug链接")
@allure.testcase("测试用例链接")
def test_(self):
allure.dynamic.title("用例标题")
allure.dynamic.description("用例描述")
with allure.step("用例步骤描述"):
pass
allure.attach(body="截图内容",name="截图名称",attachment_type=allure.attachment_type.PNG)
print("test")
allure访问:
allure open ./reports生成新的报告地址
yaml
&:锚点,*:引用,<<:合并
标量,对象-字典,数组-列表
读取:yaml.load(f,yaml.full_load)
写入:yaml.dump(data,stream=f,allow_unicode=True)
清空:f.truncate()
数据驱动:
定义:
@pytest.mark.parametrize("caseinfo",[])
def test_(self,caseinfo):
print(caseinfo)
性能测试
目的:
1.评估系统的能力
2.识别系统中的弱点
3.系统调优
4.检测软件中的问题
5.验证稳定性和可靠性
ab -n 10 -c 10 -t 10 http://www.baidu.com
-n:请求次数 -c:并发数 -t:并发时间以秒为单位
如果使用了-n就没必要使用-t
jmeter录制脚本
1.创建线程组
2.创建http代理服务器
1.设置端口,未被占用
2.设置目标控制器,录制脚本的存放路径
3.分组,在组间添加间隔
4.设置脚本描述
5.rquestfilter,添加默认筛选
3.浏览器配置代理
python解析xml
from xml.dom.minidom import parse
dom_tree = parse("xml_path")
root_node = dom_tree.documentElement 获取根节点
root_node.hasAttribute("type") 判断根节点是否有type属性
book = root_node.getElementsByTagName("book") 获取book节点对象
web自动化测试
原理:
接口:
服务器-数据-用户
web:
服务器-数据-浏览器-处理数据-展示UI-用户
html、css、javascript
html:决定网页有哪些内容
css:样式,文字大小、字体、颜色、位置
js:交互效果、逻辑关系
常见的标签:
输入框:<input />
按钮:<button>登录</button>
链接:<a href="#"/>
段落:<p>段落内容</p>
换行:<br />
图片:<img src="" />
单选框:<input NAME="" type="radio"/>
多选框:<input type="checkbox"/>
下拉框:<select><option>湖南<option/></select>
selenium三大组件:
IDE:录制用例
WebDriver:执行用例
Grid:分布式
自动化环境
python->selenium->浏览器驱动->浏览器
1.pip install selenium
2.pip install webdriver-helper
3.from webdriver-helper.driver import get_webdriver
4.get_webdriver("chrome")
selenium原理:
selenium封装了对接口的调用,使用面向对象的方式,通过对webdriver实例方法和webelement实例方法调用
完成复杂的关联性的浏览器控制
selenium截图四种方法:
1.driver.get_screenshot_as_base64() 获取截屏的base64编码数据
2.driver.get_screenshot_as_png() 获取二进制数据流
3.driver.save_screenshot(filename/full_path)
4.driver.get_screenshot_as_file(filename/full_path) 获取截屏png图片,参数是文件的路径,截屏必须是.png图片。如果只给文件名,截屏会存在项目的根目录下
selenium等待的区别
1.强制等待:time.sleep()
2.显示等待:WebDriverWait(driver,5,0.5).until())提前指定等待条件和等待时间,在查找元素时,判断规定时间内是否满足条件,满足则继续执行,不满足或超出时间则抛出异常
3.隐式等待:driver.implicitly_wait(5)程序提前指定等待时间,在查找元素时,首先会在DOM中查找元素,如果找不到,就继续等待,在等待时间结束之后,再一次查找,如果找到元素则继续执行,没有找到则抛出异常
上线时间紧张,你应该如何安排测试
1.划分测试重点,设置测试优先级,首先保证业务核心功能
2.尽量提前介入,提前准备好测试数据,可以边开发边进行单元模块测试
3.优化用例,测试用例设置优先级,低优先级的用例往后排
4.加强沟通,当面沟通快速确认问题
5.加班