欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > 暂未整理啊

暂未整理啊

2025/2/12 11:19:07 来源:https://blog.csdn.net/MaoLingHao/article/details/145581063  浏览:    关键词:暂未整理啊

测码学院

python的数据类型

不可变数据类型:字符串/数字/元组/

type(变量名) 获得数据的类型
str:字符串
int:整数
float:浮点数
bool:true/false  布尔类型
list:列表
dict:字典
转化类型:float(被转型的变量名称)
*字符串格式化四种方式*
1.print('我的名字是{}').format("名字") {}占位符
2.print('我的名字是{0}年龄是{2}性别是{1}').format("姓名","男","15") 用索引的下标
3.print('我的名字是%s年龄是%s性别是%s'%("姓名","男","15"))
4.print(f'我的名字是{变量名1}年龄是{变量名1}性别是{变量名1}')
abs函数  取绝对值
abs(被取绝对值的数值)
ceil函数向上取整数  floor函数向下取整数
import math
math.ceil(被取值的变量)
math.floor(被取值的变量)
random随机数
import random
random.random() 0-1随便出
random.randict() 指定范围输出数字
切片:
反转:str[::-1]  最后一个 变成-1即可
常用函数:
"以什么分割就写什么".join("被链接的变量 可以是元组和列表")
split("。",1)以句号为分割进行分割一次  返回的列表
find() index() 字符串包含这个字符串没有
str.find("a") 查看a在没在str字符串中  不在返回-1,在返回索引
str.index("a")查看a在里面就返回索引,不在就报错
str.replace("老字符串","新字符串")
路径处理:
1.用//
2.在前面加r处理下
大写处理:str.upper()
小写处理:str.lower()
首字母大写:str.capitalize()
首字母每个都是大写:str.title()
判断是不是大写:str.isupper()
判断是不是小写:str.islower()
**元组**
1.元组数据只有一个,一定要写成(1,) 逗号必不可少
2.拼接的方式可以添加数据:元组1+元组2  生成新的元组数据 用变量名接收下就可id()查看内存地址
3.删除数据del 元组变量名  删除就没有数据了

可变数据类型:/列表/字典/集合

定义:[]
查询:list[0]  里面填写对应的索引
切片取数据list[:1]
增加:- append在末尾添加元素 insert(2,元素)指定位置添加 extent在末尾添加数据区别:append是把整个数据添加进去的;extend是一个一个数据加入的list.append(["q","q"])  ["1",["q","q"]]list.extend(["q","q"])  ["1","q","q"]
修改:list[3]="新数据"
删除:pop(索引)  返回删除的数据  索引默认是-1  remove("具体数据")  删除后不给返回的值 返回nonedel删除一个或者几个或则和整个  del list[1:]  del list
排序:list.sort()  升序list.sort(reverse=False) reverse 控制是否反转reversed()  反转list.reversed() 反转
数据类型转化: 列表转元组:tuple(list)  其余类型转化类似写法
字典:{"name":"maofafa"}键值对的格式
查询:dict["name"]/  dict.get("name")dict.keys()  获取所有的键dict.values() 获取所有的值dict.items() 获取所有的键值以元组形式获取
增加:dict["nage"]="18"
修改:dict["name"]="lilingling"dict.update(dict2)把dict2里面的值更新到dict中
创建新的字典:dict={}  list=["a","b","c"]
dict.fromkeys(list)  dict={"a":none...}
dict.fromkeys(list,10) dict={"a",10...}
集合:不能重复
新增集合:set() 一定是这种格式不然会出错的
新增数据:set.add(5,"7")set.update((5,7,8))  必须添加一系列数据才行,而且必须是集合
删除元素:remove()指定删除元素,不存在会报错  pop()随即删除  discard()删除不存在的不会报错  clear() 清空

条件判断与循环语句

逻辑运算符:and or not
and:两个为真才真
or:一个为真即真
not:取反
成员运算符:in /not in/
身份运算符:is / not is
值相等: ==
1.语法格式:
if 条件:做条件满足的动作
else:不满足的事情
注意:input输入的都是字符串,如果做数字比对记得转类型
2.多重条件格式:
if 条件:做满足条件的事情
elif 条件:做满足条件的事情
else:不满足的事情
3.嵌套if
if 条件:if 条件:满足的条件elif 条件:满足的条件else:不满足的条件
else:不满足的条件
循环
- while 条件循环:- 格式: while 条件:循环内容记住加上一个条件,避免死循环- 例子:i=0while i<=5:print(i)i+=1- 循环中的break continue退出循环- break :退出整个循环- continue:跳出当前循环
特殊:while  和else结合的时候,循环正常结束的会执行else,如果停止了,则不会打印else
- for  循环- 格式: for i in range(5):print(i)

函数与模块

函数:把一个功能或者常用的代码,封装起来,后面直接使用函数名
使用步骤:
1.封装函数  常用的代码封装成一个独立模块
2.调用函数  享受封装后的效果
作用:提高代码效率
语法格式:def 函数名():逻辑return 返回
调用: 函数名()
- def 函数名(a,b) | a和b是形参
pass的作用 是不让编译器报错位置参数,关键字参数,默认参数,不定长参数
- 位置参数:实参的顺序要和形参对应  函数名(a,b)
- 关键字参数:先定义形参,实参可以顺序不同,但是实参前面需要加上参数名称函数名(a=1,b=2)
- 默认参数:函数名(a=18)
- 不定长参数:函数名(*args) 这是放在元组中|函数名(**kwargs) 这是字典函数嵌套:
引入:
1.from   import  给出具体的工具
2.import   导入工具箱 自己选
main 函数入口
作用:可以自己运行函数,还不会被别的文件调用到
解包:pom
方法: *能解包元组|**解包字典

文件处理和os模块

匿名函数:lambda
语法:lambda 参数,参数1:表达式,逻辑功能
匿名函数不需要返回,本身就是函数的返回值
def sun(a,b):c=a+breturn c
c=lambda a,b:a+b
print(c(10,11))列表推导式:[表达式 for xx in range()]
字典推导式:{key:value for i in range()}
列表嵌套字典:[{key:value for i in range()}]if 语句的三目运算
格式:result1 if 条件 else result2
文件处理:
格式:f=open('文件名','模式','编码格式')写入数据: f.writer("内容")读取数据:f.read()关闭:f.close()
模式:w,写模式,没有文件闯将文件,会覆盖原有内容r,读模式,没有文件不会创建文件读取r+ 可读可写a,追加模式,没有就创建追加tell()指针位置seek(字节数,指针位置)偏移指针位置  0开头,1当前位置,2结尾位置read()读取所有readline()读取一行readlines()读取所有行放在列表中
文件路径:要注意你运行的文件路径在哪,围绕这个来写路径- 绝对路径:- 相对路径:建议使用的格式:with open() as f:f.read
创建文件夹:os.mkdir()
删除文件夹:os.rmdir(路径)
非空文件夹:import shutil shutil.rmtree(file)
重命名文件:os.rename(旧,新)
判断是不是文件夹:os.path.isdir(file)
判断是不是文件:os.path.isfile(file)
获取当前文件夹绝对路径路径:os.getcwd()
获取当前文件的绝对路径:os.path.abspath(__file__)
当前路径的父路径:os.path.dirname(os.path.abspath(__file__))
拼接路径:os.path.join(路径,路径)
1.txt文件读取with open("文件路径","模式","encoding文件编码格式") as f:f.read()f.readline()f.readlines()
2.yaml文件读取函数
语法格式:- 缩进表示层级关系 不能用tab键来缩进  直接用空格- # 表示注释- 字符串,要用引号,数字想要是字符串的必须要加引号- 可以创建列表 []  -表示列表- 可以创建字典 {key:value} :表示字典  冒号后面要加空格!!!
需要安装pyyaml第三方包
import yaml
f=open("文件路径","读写模式","编码格式")
data=yaml.load(f,Loader=yaml.FullLoader)
with open() as f:data=yaml.load(f,Loader=yaml.FullLoader)
3.读取excel数据
安装openpyxl
import openpyxl
打开excel
workbook=openpyxl.load_workbook("路径")
拿到所有的sheet页面
sheets=workbook.sheetnames拿到指定表单
sh3=workbook["sheet页名称"]读取excel里面的数据
for i in sheet.values:print(i)指定sheet页面的指定单元格的值
id=sh3['A1'].value指定单元格的值  行和列
id=sh3.cell(row=1,column=1).value写入数据
sh3.cell(row=1,column=1).value='预期结果'
sh3['A1'].value='预期结果'
workbook.save("路径 ")
4.csv文件
import csv
with open() as f:a=csv.reader(f)for i in a:print(a)
out=open('','a','encoding=',newline="")
writer=csv.writer(out)
writer.writerrow('写入的格式列表 ')

异常处理

异常处理:保证程序的健壮性和稳定性;忽略一些小问题,后面的程序依旧可以处理下去
语法格式:
try:要执行的代码raise Exception(len(pwd),8)
except Exception(包含了所有的错误信息):错误的处理
except 错误类型:出现的错误
except (错误类型,错误类型):出现错误的提示
else:没有异常才会执行的代码
finally:无论如何都会去执行
抛出异常 raise 自定义异常  特定的要求就会用自定义异常

时间和日期 打印日志

时间戳
time.time()
时间戳转时间元组
time.localtime(time.time())
时间元组转为日期  英文的日期
time.asctime(time.localtime(time.time()))
中文日期:time.strftime('%Y-%m-%d %H:%M:%S ')

面向对象

面向对象:编码的一种方式-  更灵活 可扩展- 冰箱是一个对象,有打开门,放入物品的方法
面向过程:编码的一种方式-  一步一步写
面向对象的语法格式:class 类名-第一个首字母大写:def __new__(self):return object.__new__(cls)类属性:事物的特征def __init__(self,a,b,c):self.name=aself.color=b实例化方法def open(self):passdef __str__(self):return f'这是一对象的描述信息:{self.name}{self.color}'def __del__(self):print(销毁)类方法@classmethoddef sport(cls):print("打羽毛球")静态方法  与类没有任何关系@staticemethoddef close():print("静态方法")
使用类的方法:类名(a,b,c)类名().属性类名.方法()类.方法名(对象)
self就是对象__str__魔法方法  定义类对象返回的内容  tom=类名()  print(tom)
__del__销毁对象,  只要写了,不管调用与否都会执行
__new__创建对象类方法:函数上面需要加上@classmethod装饰  本身就是cls
实例方法调用:类名().方法() 或者 类.方法名(对象)
类方法调用:类名.方法()
静态方法:@staticmethod装饰,参数没有self,也没有cls(和类没有关系才会用这个)
静态方法调用:类名.方法()
继承:继承封装类的所有方法和属性
单继承,多继承就是继承多个类  class 类名(类1,类2) 优先继承第一个类的所有
dog类继承anmial类
dog是子类  anmial是父类
dog是anmial的派生类 ;animal是dog的基类子类拥有和父类同样的方法和属性 会覆盖父类的想用父类的方法和属性且用自己的属性和方法
super().__init__
super().方法名
多态:看例子  传入不同的对象,产生不同的结果
class Dog:def eat(self):print("1")
class Cat:def eat(self):print("2")
def eat(a):a.eat()
eat(Dog())
eat(Cat())
这就加多态
class with:def with_dog(self,obj):obj.eat()
with().with_dog(Cat())
这个也叫多态

装饰器

装饰器:给已有的函数增加额外的功能,他的本质一个闭包函数
闭包函数:函数调用完之后,内部定义的变量直接销毁了,但是有时候我们需要保存函数内的这个变量,在这个变量进行一些其他操作,比如求和
闭包形成条件:
1.实现函数嵌套
2.内部函数使用外部函数的变量
3.外部函数返回内部函数,不要加括号
闭包的作用:百年量不会污染全局变量
例子:
def test01(a):b=1def test02():print(a,b)return test02
a=test01(6)
a()
函数从上往下执行的,没有函数名加括号是不会执行的
所以返回test02
a=test02
a()->test02()
global  全局变量
nonlocal 作用就是用外层的变量,就是用在闭包函数中装饰器的演示
def check(fc):print("装饰器函数执行")def inner():inner常用写法print('请先登录')fc()# return 也可以写返回值return inner
def comment():print("发表评论")a=check(comment)
a()
@check  相当于check(comment)做了一个这个
def comment():print("发表评论")comment()
怎么去运行的comment,先运行装饰器函数运行print函数,不会进入inner函数,返回inner给秘书commen

迭代器

特殊方法:__iter__()返回一个迭代器对象,迭代器对象俩面再用__next__()把里面的数据取出来
a=[1,2,3,4]
print(a.__iter__())  打印迭代器对象
list=a.__iter__()
print(list.__next__())  打印第一个1
print(list.__next__())  打印第二个2.。。

生成器

yield 再学

常见算法 学这个的意义

冒泡排序:
选择排序:
递归排序:
树结构:

数据库

第三方包:pymysql
import pymysql
1.连接数据库
conppymysql.connet(host='',port='',user='',password='',database='')
2.操作数据库
cur=con.cursor()
3.执行sql
cur.execute(sql语句)
查询所有数据
cur.fetchone()
cur.fetchmany() 默认全部查询,写123表示查询几个数据新增:就是sql语句是新增就行
cur.execute('commit')参考代码:
------------------------------------------------------------
import pymysql
import configparserclass MySqlDB:# 获取配置文件里面的数据 MySqlDB('db.ini','Test_db')  MySqlDB('db.ini','zs_db')# 封装这个部分# 类的作用:模板 后面可以实例化使用# init:连接了数据库  创建了游标  为什么init数据库  创建了游标:只要用到查询语句  修改语句# 读取配置文件里面的数据,在放到连接中连接数据库def __init__(self,configpath,db):config=configparser.ConfigParser()config.read(configpath)# 读取文件数据host=config[db]['host']port=int(config[db]['port'])user=config[db]['user']password=config[db]['password']database=config[db]['database']charset=config[db]['charset']self.con=pymysql.connect(host=host, port=port, user=user, password=password, database=database,charset=charset)self.cur = self.con.cursor()# 连接部分写在初始化函数里面# 初始化的作用是什么:调用就连接# 实例化类,里面进入到init初始化函数  a=MySqlDB('127.0.0.1',3306,'root','123456','vipdb','utf8')# 调用的时候传ip地址,端口号这类# def __init__(self,host,port,username,password,db,charset):#     try:#         self.con = pymysql.connect(host=host, port=port, user=username, password=password, database=db,#                               charset=charset)#     except Exception as  e:#         print('数据库连接有问题'%e)#     self.cur=self.con.cursor()def close(self):self.cur.close()self.con.close()# 1.连接  2.创建游标 3.写sql语句  4.执行sql  5.获得结果# 查询语句def get_all(self,sql):ret=Nonetry:self.cur.execute(sql)ret=self.cur.fetchall()self.close()except Exception as e:print(e)return retdef get_one(self,sql):ret=Nonetry:self.cur.execute(sql)ret=self.cur.fetchone()self.close()except Exception as e:print(e)return retdef edit(self,sql):try:self.cur.execute(sql)self.cur.execute('commit')self.close()except Exception as e:print(e)return True# 子查询  灵活运用
# 存储过程  函数去学 传参  有返回
# python 连接数据库
--------------------------------------------------------------
文件名:db.ini文件名
[Test_db]
host=127.0.0.1
port=3306
user=root
password=123456
database=vipdb
charset=utf8[zs_db]
host=127.0.0.1
port=3306
user=root
password=123456
db=vipdb
charset=utf8

日志使用

# 日志器封装
# 组件
# 学习日志:
# 几个组件:
# loggers:日志器 程序的入口 别的文件想要调用就用日志器
# handlers处理器:日志信息 输出到你想要的位置 控制台处理器 文本文件处理器
# formatter格式器:处理日志格式 格式比较好看
# filter过滤器# 两种封装 一个是basicConfig,一个是自己封装的
# 意思:使日志信息 格式是我们想要的,日志能保存在控制台 能保存在文本文件
import loggingdef test_log2():# 创建日志器  这个日志器就写入了日志信息logger=logging.getLogger()# 显示日志信息全面 设置日志级别logger.setLevel(logging.INFO)# 日志信息显示在控制台  你不加这句话if not logger.handlers:# 需要控制台处理器sh=logging.StreamHandler()# 日志信息放入控制台中logger.addHandler(sh)# 保存在文件中 文件处理器fh=logging.FileHandler('log1.txt',encoding='utf-8')# 把日志信息添加到文件中去logger.addHandler(fh)# 日志比较丑,设置格式  创建格式器fmt = '%(asctime)s %(filename)s %(funcName)s %(levelname)s %(message)s'formater1=logging.Formatter(fmt)# 给谁加格式# 给控制台加格式  控制台是哪个单词?sh.setFormatter(formater1)fh.setFormatter(formater1)return logger# 封装日志 有三种方式 1.baseConfig  2.自定义函数封装  3.ini文件
# 使用的话 拿到封装文件.info()或者拿到封装文件.error()
# 重要 重要 项目 加上日志  不重要 封装一次 后续只要使用即可
# 我们还是要会# 这种方式用的多# 要用的时候才调用info 封装一下# logger.debug('调试的日志信息')
# logger.info('正常日志信息')
# logger.warning('警告的日志信息')
# logger.error('错误的日志信息')
# logger.critical('严重的日志信息')
---------------------------------------------------------------
文件名log.ini  装逼用这个
[loggers]
keys=root[handlers]
keys=fh,sh[formatters]
keys=simpleFormatter1;具体应用  日志器里面有日志信息,设置日志级别 日志信息设置显示在哪
[logger_root]
level=INFO
handlers=fh,sh;控制台处理器 创建控制台处理  设置格式
[handler_sh]
class=StreamHandler
formatter=simpleFormatter;文本处理器 创建具体的文本处理器  设置格式
[handler_fh]
class=FileHandler
formatter=simpleFormatter
args=('log2.txt','a','utf-8');创建具体的格式
[formatter_simpleFormatter]
format=%(asctime)s %(filename)s %(funcName)s %(levelname)s %(message)s---------调用方法
import logging.config
# ini文件调用
logging.config.fileConfig('log.ini')
a=logging.getLogger()

邮件发送

1.发送文本文件
# 邮件
# 内容:1.用python代码发文本邮件  2.发送html邮件 发送附件  图片# smtp发送邮件   smtp邮件传输协议  smtplib库 :进行简单的封装  简单import smtplib# 1.连接邮箱服务器  邮局   smtplib.SMTP_SSL(邮箱连接地址,端口号)  smtp.xx.com
# 163邮箱:smtp.163.com  端口号
# qq邮箱:smtp.qq.com  端口号  465或587
from email.mime.text import MIMETextcon=smtplib.SMTP_SSL('smtp.qq.com',465)
print(con)# 登录邮箱  用户名和密码  密码用授权码  qq邮箱--设置--账户-POP3/SMTP服务开启 授权码
con.login(user='2804555260@qq.com',password='hhrotgwljdmqdfhh')# 发送者账号
sender='2804555260@qq.com'
# 接受者账号
receive='2804555260@qq.com'# 发送内容  _text 内容, _subtype='plain' 文本 , _charset=None  字符集
htmlContent="<a href='http://www.baidu.com'>我是html代码</a>  东风风神懂法守法大幅度的首付首付"
message=MIMEText(htmlContent,'html','utf-8')
# message=MIMEText('小幸运你好,我是渣渣秋','plain','utf-8')# 设置头部内容  标题  发件人 收件人
# 标题
message['Subject']='发送给小幸运的一封信'
# 发送人
message['from']=sender
# 收件人
message['to']=receive# 邮件有没有发送出去 有没有问题,担心发送的邮件有问题
try:# 发送邮件con.sendmail(sender,receive,message.as_string())print('邮件发送成功')
except Exception as e:print('没有办法发送邮件,报错了')# 发送文本文件
# html格式的邮件# 发送测试报告,发送html的测试报告  发送给测试相关人员怎么发送呢?
2.发送html测试报告
# 发送html测试报告给到相关测试人员import smtplib
from email.mime.text import MIMETextcon=smtplib.SMTP_SSL('smtp.qq.com',465)
con.login(user='2804555260@qq.com',password='hhrotgwljdmqdfhh')# 发送者账号
sender='2804555260@qq.com'
# 接受者账号
receive=['2804555260@qq.com','1106614821@qq.com']# 发送html文件里面的内容 读取出来
with open(r'./files/2020-11-16 21-15-18test_report.html','rb')as f:htmlContent=f.read()message=MIMEText(str(htmlContent,encoding='utf-8'),'html','utf-8')message['Subject']='发送给小幸运的一封信'
# 发送人
message['from']=sender
# 收件人
# message['to']=receive
message['to']=';'.join(receive)con.sendmail(sender,receive,message.as_string())# html这个附件怎么发送出去
--------------------------------------------------------------
3.发送附件
# 发送附件import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMETextcon=smtplib.SMTP_SSL('smtp.qq.com',465)
con.login(user='2804555260@qq.com',password='hhrotgwljdmqdfhh')
# 发送者账号
sender='2804555260@qq.com'
# 接受者账号
receive=['2804555260@qq.com','1106614821@qq.com']# 发送内容
# 附件实例  盒子
message=MIMEMultipart()
# 拿到内容
with open('./files/2020-11-16 21-15-18test_report.html','rb')as f:content=f.read()# 内容写在信纸上files2=MIMEText(content,'base64','utf-8')# 纸取个名字  不要用中文去写  用英文files2['Content-Disposition']='attachment;filename="2.html"'# 把家书放到盒子中寄出去message.attach(files2)msg=MIMEText('正文内容','plain','utf-8')message.attach(msg)message['Subject']='这是一封家书'
# 发送人
message['from']=sender
# 收件人
message['to']=';'.join(receive)con.sendmail(sender,receive,message.as_string())# 注意:在日常工作中,发送html的测试报告,要压缩成压缩文件之后在发送
# 手动压缩 代码压缩 zipfile
-----------------------------------------------------------
4.发送图片
# 发送图片
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
import smtplib
from email.mime.text import MIMETextcon=smtplib.SMTP_SSL('smtp.qq.com',465)
con.login(user='2804555260@qq.com',password='hhrotgwljdmqdfhh')# 发送者账号
sender='2804555260@qq.com'
# 接受者账号
receive=['2804555260@qq.com']
# 抄送者账号
cs=['1787326464@qq.com','1418404585@qq.com','7845684@qq.com']
# 发送图片
message=MIMEMultipart()
# 图片内容
with open('files/imgae.jpg','rb')as f:image1=f.read()# 放在纸上,图片image_data=MIMEImage(image1)image_data['Content-Disposition'] = 'attachment;filename="2.jpg"'message.attach(image_data)msg=MIMEText('图片','html','utf-8')message.attach(msg)message['Subject'] = '这是一封家书'
# 发送人
message['from'] = sender
# 收件人
message['to'] = ';'.join(receive)
# 抄送
message['Cc']= ';'.join(cs)con.sendmail(sender, receive+cs, message.as_string())
------------------------------------------------------------
5.zmail发送邮件
# 安装:pip install zmailimport zmail
# subject 标题
# Content_text:邮件文本内容
# Content_html:发送html格式内容
# Attachments:附件# 发送人
sender={'username':'2804555260@qq.com','password':'hhrotgwljdmqdfhh'}
# 登录邮箱
server=zmail.server(sender['username'],sender['password'])# 邮件内容
mail_content={'subject':'我是标题','Content_text':'我是邮件内容http://www.baidu.com',# 'Content_html':'<a href="http://www.baidu.com">嗨,你好</a>','Attachments':'./files/a.docx'
}# 收件人
receive=['1418404585@qq.com','7845684@qq.com','2804555260@qq.com']
# 发送邮件
server.send_mail(receive,mail_content,cc=['964197460@qq.com'])# 注意:
# Content_text和Content_html只能选择一个使用

selenium定位

'''八种元素定位法则:Id,Name,Link text,Partial Link Text,Tag Name,Class Name,Xpath,Css Selectorxpath与cssSelector在速度的区别上大概就是10ms左右自动化领域下,正确率和稳定性永远排在第一位。
'''
from selenium import webdriverdriver = webdriver.Chrome()driver.get('http://www.baidu.com')# ID定位:在元素具备有ID的属性时,可以通过ID去进行定位。ID就相当于身份证号码。一般而言是不会重复的。
# driver.find_element('id', 'su')
# Name定位:在元素具备有Name属性时,通过Name属性去定位。重复的概率相对而言还是可能存在的。类似于身份证上的名字
# driver.find_element('name', 'rn')
# Link Text:针对于a标签来实现的定位,定位条件是a标签的text内容
# driver.find_element('link text', '新闻').click()
# Partial Link Text: 针对于A标签来实现的定位,是基于a标签的text内容进行模糊查找。类似于sql中的like
# 如果定位的元素有多个,则默认返回第一个定位到的元素。
# els = driver.find_element('partial link text', '使用百度')
# for el in els:
#     print(el.text)
# print(els.text)
# TagName定位:测试用不上,一般是在爬虫的时候应用,基于标签名称来进行元素定位
# els = driver.find_elements('tag name', 'input')
# print(len(els))
# ClassName定位,基于元素的class属性去进行定位,不推荐使用,如果class值只有一个,可以考虑使用,但是要避免重复
# el = driver.find_element('class name', 'bg s_ipt_wr new-pmd quickdelete-wrap ipthover')
# print(el.get_attribute('class'))
# CSS Selector元素定位:万金油型的元素定位。原理就是基于css样式来对元素进行定位。也是传说中定位最快的方法。
# driver.find_element('css selector', '#kw').send_keys('#kw')
# Xpath元素定位:个人推荐常用款,定位界的万金油,原理是基于html结构来对元素进行定位,类似于操作系统下的文件管理系统
# 绝对路径:不到穷途末路之时,不要使用这个定位方法
# /html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input
# 相对路径:元素的查询功能,通过右键copy,copy xpath获取元素的相对路径(此方法不推荐),一般都是通过手写xpath的形式
# //*[@id="kw"]
driver.find_element('xpath', '//*[@id="su"]')---------------------------------------------------------------
特殊的定位方式
'''相对定位器进行元素定位,在selenium4 中所新增的内容基于人的方向来对元素进行定位,只需要定位一个元素,就可以把这个元素周围的所有元素都定位到。实际使用中,会出现定位不准确
'''
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_withdriver = webdriver.Chrome()
driver.get('http://www.baidu.com')
# 核心元素
el = driver.find_element('id', 'kw')
# 上
a = driver.find_elements(locate_with(By.TAG_NAME, 'div').above(el))
# 下
b = driver.find_elements(locate_with(By.TAG_NAME, 'div').below(el))
# 左
l = driver.find_elements(locate_with(By.TAG_NAME, 'div').to_left_of(el))
# 右
r = driver.find_elements(locate_with(By.TAG_NAME, 'div').to_right_of(el))
# 附近
n = driver.find_elements(locate_with(By.TAG_NAME, 'div').near(el))
print(a)
print(b)
print(l)
print(r)
print(n)
--------------------------------------------------------------
详细讲解xpath
xpath元素定位
语法规则://*[@id="kw"] 表示从根路径下开始查找任意一个
元素,该元素具备有id属性,且属性值为kw
// 表示从根路径下开始查找
*表示任意元素,也可以直接输入标签名称,用于指定
某一个类型的元素
[] 表示添加筛选条件
..表示上一层
@ 表示基于属性来进行查找
id 表示属性的名称
kw 表示属性的值
text() 表示基于文本来定位
[contains()] 表示调用contains函数,进行内容的模糊
查找  [contains(@id,'k')] 
/following-sibling::* 表示查找当前元素的所有弟弟妹
妹
xpath手写的方式,除去避免绝对路径以外,还可以避
免动态元素导致的元素定位失败
伪元素:正常定位即可
::before::
::after::  类似于这种  的叫伪元素;正常定位即可
-------------------------------------------------------------
# 句柄与frame
'''新页面的访问:selenium访问新页面的时候,默认停留在老页面中,每一个页面都有一个句柄,要操作哪个页面就切换哪个句柄句柄的切换业务下,需要时刻记住,标签页最多保留不超过2个。一般在访问新标签页之前,要close掉旧的标签页内嵌窗体的元素操作:有一种场景下,你元素定位是正确的,并且再三确认过的,但是运行到这里就是找不到元素,也等待了,也排查了,也让虚竹看了。这时候就需要思考一下,是不是有iframe呢?
'''
from time import sleepfrom selenium import webdriverdriver = webdriver.Chrome()
driver.implicitly_wait(5)
sleep(2)
driver.maximize_window()
# driver.get('http://www.baidu.com')
# driver.find_element('id', 'kw').send_keys('虚竹')
# driver.find_element('id', 'su').click()
# driver.close()
# # 访问新页面前
# # print(driver.window_handles)
# driver.find_element('xpath', '//*[@id="1"]/div/div[1]/h3/a').click()
# sleep(1)
# print(driver.title)
# 句柄获取
# handles = driver.window_handles
# # 关闭当前标签页
# driver.close()
# # 切换标签页
# driver.switch_to.window(handles[1])
# print(driver.title)
# 访问新页面后
# print(handles)# iframe处理
driver.get('https://music.163.com/')
driver.find_element('link text', '登录').click()
driver.find_element('link text', '选择其他登录模式').click()
driver.find_element('id', 'j-official-terms').click()
driver.find_element('partial link text', 'QQ登录').click()
sleep(1)
# 句柄获取
handles = driver.window_handles
# 关闭当前标签页
# driver.close()
# 切换标签页
driver.switch_to.window(handles[1])
# 如果元素在iframe标签中,需要先切换至iframe,再进行定位
driver.switch_to.frame('ptlogin_iframe')
driver.find_element('xpath', '//*[@id="qlogin_list"]/a[2]').click()
# 切换到默认窗体:只有切换回来以后才可以继续操作页面中iframe以外的内容
driver.switch_to.default_content()
--------------------------------------------------------------
# 常规元素操作行为:selenium本身就是用于模拟人的操作行为,遇到不知道怎么处理的,参考人类的使用习惯
from time import sleepfrom selenium import webdriver# chrome浏览器配置
from selenium.webdriver import ActionChains
from selenium.webdriver.support.select import Selectoptions = webdriver.ChromeOptions()
# options.add_argument('start-maximized')
driver = webdriver.Chrome(options=options)
sleep(3)
# 窗体最大化:不要用。在selenium2开始就存有一个bug,调用窗体最大化时会造成driver的超时异常
# driver.maximize_window()
# 设置窗体大小尺寸
# driver.set_window_size(200, 1000)
# 访问url以及文件
# driver.get('http://39.98.138.157/shopxo/index.php')
driver.get('https://www.baidu.com/')# 窗体最小化:不实用,不如不用
# driver.minimize_window()
# 浏览器操作,前进后退以及刷新
# driver.forward()
# driver.back()
# driver.refresh()
# 获取title:用于在调试的时候可以判断一下。仅此而已,不代表可以用于断言
# print(driver.title)
# 元素定位
# driver.find_element()   # 定位单个元素,如果同时有多个元素满足条件,定位第一个发现的元素并返回
# driver.find_elements()  # 定位符合条件的所有元素,最终以list的格式返回。如果要操作其中的元素,需要通过下标
# 获取到元素之后的操作行为
# 输入操作
# driver.find_element('name', 'wd').send_keys('虚竹')
# 文件上传:如果在系统操作中遇到文件上传的操作,如果是input标签则可以通过sendkeys直接操作,非input标签,弄死开发,或者用autoIT去解决
# driver.find_element('xpath', '//span[@class="soutu-btn"]').click()
# driver.find_element('xpath', '//input[@value="上传图片"]').send_keys(r'D:\测码\头像\1.jpg')
# 点击:如果有点击的需求,统一通过click()来实现
# driver.find_element().click()
# 操作下拉列表框
# 1. 悬停在设置元素上:悬停操作时,鼠标不要在driver的浏览器中进行移动。
ActionChains(driver).move_to_element(driver.find_element('xpath', '//span[text()="设置"]')).perform()
# 2. 点击高级搜索
driver.find_element('link text', '高级搜索').click()'''下拉列表框分为以下三种:1. 基于input标签实现的下拉列表框2. 基于Select标签实现的3. 基于其他标签实现的
'''# 常见的下拉列表框操作一:其他标签
sleep(1)
driver.find_element('xpath', '//span[text()="全部时间"]').click()
driver.find_element('xpath', '//p[text()="最近一月"]').click()
# 常见的下拉列表框操作二:input标签(一般input下拉列表框是具有只读属性,无法直接通过send_keys输入,输入前需要remove只读属性,此方法如果无效,则使用两次click解决)
# driver.find_element('xpath', '//input[text()="全部时间"]').send_keys("最近一月")
# Select标签下拉列表框:如果你的系统有这个东西,也就意味着他比你的工作年限还要长的多,最初的下拉列表框
# select = Select(driver.find_element('id', 'cityId'))
# # 选择值
# # 通过下标选择
# select.select_by_index(5)
# # 通过value选择
# select.select_by_value('12')
# # 通过文本选择
# select.select_by_visible_text('成都')
# 退出浏览器,需要把后端进程一同关闭
# driver.close()
driver.quit()
--------------------------------------------------------
'''
selenium4中新增的有用的操作行为:针对于浏览器与标签页的
'''
from time import sleepfrom selenium import webdriverdriver = webdriver.Chrome()
sleep(3)
# 自动生成新的标签页,并切换过去
# driver.switch_to.new_window('tab')
# 自动生成新的浏览器,并切换过去
driver.switch_to.new_window('window')
print(driver.window_handles)
driver.switch_to.window(driver.window_handles[0])
driver.get('http://www.baidu.com')
---------------------------------------------------------
等待
'''等待的示例
'''
import timefrom selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWaitoptions = webdriver.ChromeOptions()
# 设置页面加载策略
options.page_load_strategy = 'eager'
# options.add_argument('start-maximized')
options.add_experimental_option('useAutomationExtension', False)
options.add_experimental_option('excludeSwitches', ['enable-automation', 'enable-logging'])
# 去掉账号密码弹窗
prefs = dict()
prefs["credentials_enable_service"] = False
prefs['profile.password_manager_enable'] = False
options.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(options=options)driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": """Object.defineProperty(navigator, 'webdriver', {get: () => false})"""
})
# driver = webdriver.Chrome()
# 隐式等待:最大等待5秒的时间。
driver.implicitly_wait(5)
time.sleep(5)
driver.get('http://39.98.138.157/shopxo/index.php')driver.find_element('name', 'wd').send_keys('手机')
# driver.get('http://www.baidu.com')
# 显式等待,等待到kw的元素显示出来,再继续进行后续的操作。
# driver.find_element('id', 'kw').send_keys('虚竹')
# driver.find_element('id', 'su').click()
# 忽略所有的逻辑,运行到这一步就会强制等待5秒钟的时间。
# time.sleep(0.2)
# 显式等待指定元素,最大等待时间是10秒,每0.5秒执行一次,一直到元素被查找到为止,如果没找到,则显示Message的内容,抛出异常TimeoutException
el = WebDriverWait(driver, 2, 0.5).until(lambda el1: driver.find_element('xpath', '//*[@id="1"]/div/div/h3/asda'),message='显式等待失败')
temp = WebDriverWait(driver, 10, 0.5).until_not(lambda el: driver.find_element('xpath', '//*[@id="1"]/div/div/h3/a'),message='显式等待失败')# el.click()# print(temp)
# driver.quit()------------------------------------------------
弹窗
'''三种弹窗的处理方式
'''from selenium import webdriverdriver = webdriver.Chrome()# 切换到弹窗
alert = driver.switch_to.alert
# 确认
alert.accept()
# 取消
alert.dismiss()
# 输入文本
alert.send_keys('输入的文本')
# 获取alert弹窗中的文本信息
text = alert.text
-------------------------------------
设置页面加载策略
driver对象默认加载的页面,都是不加载本地缓存信息的。就
会导致有时候遇到资源加载比较多的页面,加载速度就会很
慢。
可以调节页面的加载策略,从而实现更快速度的访问。
Selenium提供有页面的加载策略,在ChromeOptions中进行
配置
Alert弹窗的操作
首先,搞清楚一个概念。不是所有的弹窗都是alert,只有浏览
器弹出的才是alert。
from selenium import webdriver
# 页面加载策略
'''
selenium带有三种不同的加载策略:
1. normal:是selenium默认的加载策略,不
需要定义。表示所有内容全部加载完成,包括静态资源、
css样式、js、dom树等一切内容。
2. eager:放弃加载css样式、静态资源等,提
升加载速度
3. none:只等初始页面加载完成就直接操作
所有的加载策略都在ChromeOptions中进行设置。
'''
options = webdriver.ChromeOptions()
# 设置加载策略为none
options.page_load_strategy = 'none

断言与js执行器

## 断言 
所有的自动化测试都需要有成功或结果,所以需要在流程自动化执行的末尾,有一个校验的功能。就像是需要有一个预期结果与实际结果对比的行为。 
UI自动化下断言的行为,只需要在流程的末尾来执行即可。一般就只有一次断言就足够解决流程的自动化了。 
**UI自动化中断言所选择的点,一定是具备有代表性的内容。要关键核心的点才可以作为断言的依据。** 
在自动化体系中,断言是一种固定的形态,流程就是获取指定的内容,对内容进行判断,是否与预期相符合。 ```python 
# 定义预期结果,并获取实际结果 
expected = '预期结果' 
reality = driver.find_element().text 
# 关键的断言关键字 
assert expected == reality,'断言失败' 

断言的本质其实就是if...else的结构。

JS执行器

能够提供Selenium以外的操作行为,来更好地满足我们自动化测试需求。因为selenium本身操作的是页面的前端内容。在特殊的场景下,selenium很可能会在使用上被限制。这个时候就可以通过js执行器来完成需要的操作行为。 所有的js执行器大体都是关联到document对象

''' Js执行器的应用中,如果需要获取返回结果,需要在JS语句前添加return关键字 
''' 
# 移除元素的属性 
js = "document.getElementById('kw').removeAttribute('name')" # 通过占位符来实现selenium与document的关联 
el = driver.find_element('link text', '新闻') 
# 定位元素,并修改元素的文本 
js = 'arguments[0].innerHTML="虚竹新闻"' 
# 获取指定元素的文本信息 
js = 'return arguments[0].innerHTML="虚竹新闻"'  # 意思就相当于是el.text 
# 用于执行js语句的函数 
a = driver.execute_script(js, el) 
print(a) el = driver.find_element('link text', '下一页 >') 
# 定位元素,并在页面中心显示 
js = 'arguments[0].scrollIntoView()' 
driver.execute_script(js, el) 

附加内容

get_attribute()函数的使用。

# 输入属性名称即可获取到元素对应属性值 
text = el.get_attribute('href') 

防反爬机制的策略

# 通过修改webdriver属性为False,一定是在访问系统之前,在启动浏览器后第一步就是运行这个。 
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", { "source": """ Object.defineProperty(navigator, 'webdriver', { get: () => false }) """ 
}) 

实战 from selenium import webdriver

driver = webdriver.Chrome() driver.implicitly_wait(50)

通过修改webdriver属性为False,一定是在访问系统之前,在启动浏览器后第一步就是运行这个。

driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", { "source": """ Object.defineProperty(navigator, 'webdriver', { get: () => false }) """ }) driver.set_window_size(800, 300) driver.get('百度一下,你就知道') ''' document对象执行的常见函数: 1. removeAttribute(attribute_name) 移除指定对象的指定属性 2. setAttribute(attribute_name,value) 设置指定对象的指定属性和值 arguments[0] 在js中可以理解为是占位符,有且只能这么写。 滚动条操作的核心在于元素的获取,不是在于玩弄滚动条: window.scrollTo(x,y) x表示横轴,横向滚动条;y表示纵轴,上下滚动条 arguments[0].scrollIntoView() 精确定位到元素,并聚焦在页面中显示 JS执行器在实际执行过程中,如果想要获取执行结果,便于后续的使用,就一定要在js中添加return关键字 '''

移除元素的属性

js = "document.getElementById('kw').removeAttribute('name')"

通过占位符来实现selenium与document的关联

el = driver.find_element('link text', '新闻')

# 定位元素,并修改元素的文本

js = 'arguments[0].innerHTML="虚竹新闻"'

# 获取指定元素的文本信息

js = 'return arguments[0].innerHTML="虚竹新闻"' # 意思就相当于是el.text

# 用于执行js语句的函数

a = driver.execute_script(js, el)

print(a)

driver.find_element('id', 'kw').send_keys('虚竹') driver.find_element('id', 'su').click() el = driver.find_element('link text', '下一页 >')

定位元素,并在页面中心显示

js = 'arguments[0].scrollIntoView()' driver.execute_script(js, el)

获取元素的指定属性值。

text = el.get_attribute('href') print(text)

```python
```python 
# 表示支持python3及以上版本的浏览器配置 
driver = webdriver.Chrome(options=options) 
# 表示python2.7版本的浏览器配置,不要使用 
driver = webdriver.Chrome(chrome_options=options) 

ChromeOptions类:

''' Chrome浏览器的配置项 
''' from selenium import webdriver def options(): # 创建chrome浏览器配置项 options = webdriver.ChromeOptions() # 添加试验性质的配置项 # options.add_experimental_option() # # 添加常规设定 # options.add_argument() # 页面加载策略 options.page_load_strategy = 'eager' # 浏览器最大化 # options.add_argument('start-maximized') # 指定位置启动浏览器 options.add_argument('window-position=2500,200') # 设置窗体的启动大小 options.add_argument('window-size=1200,800') # 去掉浏览器提示自动化黄条:没什么用处,只是为了好看而已。(附加去掉控制台多余日志信息) options.add_experimental_option('excludeSwitches', ['enable-automation', 'enable-logging']) # 只支持与2.7版本的selenium,目前已经被弃用了。 # options.add_experimental_option('disable-infobars') # 无头模式:不在桌面实现浏览器的运行,作为后台静默运行,虽然看不到,但是一切照旧。偶尔场景会有异常,但很少 # options.add_argument('--headless') # 读取本地缓存的操作:webdriver启动的时候默认是不会加载本地缓存数据的。有时候想要绕过验证码或者登录流程,可以通过加载本地缓存来实现 # 调用本地缓存一定要先关闭所有的浏览器,不然会报错。 # options.add_argument(r'--user-data-dir=C:\Users\xuzhu\AppData\Local\Google\Chrome\User Data') # 去掉账号密码弹出框 prefs = dict() prefs['credentials_enable_service'] = False prefs['profile.password_manager_enable'] = False # 隐身模式下无法调用selenium中的switch_to.new_window()函数 # options.add_argument('incognito') # 去掉控制台多余信息手段二,可以作为保险的存在。(当你发现还有多余信息的时候) options.add_argument('--log_level=3') options.add_argument('--disable-gpu') options.add_argument('--ignore-certificate-errors') # 去掉控制台多余信息 # options.add_experimental_option('excludeSwitches', ['enable-logging']) # return这一步很重要。因为需要有options对象进行返回才可以对webdriver生效 return options 

关键字驱动

## 关键字驱动介绍 
自动化测试领域下,有两大设计模式,作为测试框架的核心底层。 
- 关键字驱动:广泛应用在接口、WEB、APP的测试领域下。 
本质意义上而言,就是面向对象的编程思维。是一种可以以一套思维逻辑来满足大范围的项目的自动化测试需求。 
在测试框架体系下,关键字驱动是非常常用的一种设计模式。 
例如:考虑将复用性比较高的逻辑代码封装成函数的形态,通过调用这个函数,来实现逻辑的运行。 
```python 
def 刷花(所有学员): if 所有学员听懂了: 刷花 else: 懵逼 

在自动化中,关键字驱动的封装可以把整个代码结构变得更加灵活、容易维护,极大地降低了代码的冗余,提升了代码的拓展性。 关键字驱动不仅仅只是封装操作行为,可以封装一切。 关键字驱动结构:

  1. 结构形态的清晰化,结构分离:代码与数据分离,逻辑代码与测试代码分离。

  2. 封装一定要复用性高。

  3. 足够灵活的封装

  • POM(页面对象模型)

关键字驱动的优势

  1. 可以随时添加或修改关键字驱动类,便于后期的各类维护。

  2. 代码变得更加简洁

  3. 维护更加容易,冗余降低

关键字驱动类设计原理

通过以操作行为为关键字的形态进行封装,可以有效地将各类业务的自动化测试实现。如果要解决单个框架应对多个系统的自动化测试业务,则优先考虑关键字驱动。 结构上的逻辑代码与测试代码的完全分离。 关键字驱动类一定是结合数据驱动类来实现完整的测试形态。 关键字驱动形态,最为核心的应用在于接口自动化测试,UI层,一般而言是结合企业需求来定义的。 基于企业的实际需求来设计一个对应的测试框架。而不是单纯的代码库的堆积。所有的测试框架都不是以固定的内容去套用不同的公司体系,一定是结合公司体系来设计完整的测试框架。

在封装关键字驱动类中的函数时,一定要考虑到每一个函数是否会有不同的业务场景,如果有,则需要合理设计代码的逻辑。确保每一个函数都能够有高复用性与灵活性

代码 ''' 关键字驱动类。 一般在常态化中,考虑封装各类操作行为,作为关键字驱动的核心底层结构。 以工具类的形态,便于其他的类来进行调用。 常用的操作行为: 1. 访问url 2. 创建driver对象 3. 元素定位 4. 三类等待 5. 输入、点击 6. 切换iframe和句柄 。。。。。 封装的概念上,我们优先考虑自己用的上的内容,进行封装。 Selenium本身类似于一家超级无敌大的商场。关键字驱动类类似于家用的工具箱,要往工具箱里添加我们需要的东西。 在调用工具箱实现自己的自动化时,如果发现工具少了,或者缺失了,可以及时到Selenium中进行补充。 ''' import time

import SafeDriver.drivers from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from class06_options_web import chrome_options

构造浏览器对象,基于type_参数,构造对应的浏览器对象。

def open_browser(type): ''' getattr是python内置的四大函数之一,反射机制,用于获取指定对象的属性或者函数。 driver = getattr(webdriver, type)()意思就是: if type_ == 'Chrome': driver = webdriver.Chrome() elif type_ == 'Edge': driver = webdriver.Edge() elif..... 因为反射本身是用来获取指定对象属性的。如果要获取的是函数,则需要在反射的后面加() 例如: getattr(webdriver, type) 表示获取webdriver的type属性 getattr(webdriver, type)() 表示获取webdriver的type函数 ''' try: if type_ == 'Chrome': driver = webdriver.Chrome(options=chrome_options.options()) else: driver = getattr(webdriver, type_)() except: # 可以考虑通过测码提供的safedriver来实现chrome浏览器对象的生成。 driver = SafeDriver.drivers.driver() return driver

# 这种写法可以更加好地全面化满足用户的调用需求
# browser = {'chrome': ['Chrome', 'chrome', 'cc', '谷歌'],
#            'ie': ['ie', 'Ie', 'IE', '阿姨']}
# if type_ in browser['chrome']:
#     driver = webdriver.Chrome(options=chrome_options.options())
# elif type_ in browser['ie']:
#     driver = webdriver.Ie()
# else:
#     driver = webdriver.Chrome()
# return driver

class Keys: # 临时driver对象 # driver = webdriver.Chrome()

# 构造函数
def __init__(self, type_):self.driver = open_browser(type_)self.driver.implicitly_wait(5)# url的访问
def open(self, url):self.driver.get(url)# 元素定位:一定要考虑各种不同的元素定位方法。
def locate(self, by, value):return self.driver.find_element(by, value)# 输入
def input(self, by, value, txt):self.locate(by, value).send_keys(txt)# 点击
def click(self, by, value):self.locate(by, value).click()# 浏览器关闭
def quit(self):self.driver.quit()# 文本断言
def assert_text(self, by, value, expected):try:reality = self.locate(by, value).textassert expected == reality, '{0}与{1}不相等'.format(expected, reality)except Exception as e:print('断言失败:{}'.format(e))# 显式等待
def driver_wait(self, by, value):return WebDriverWait(self.driver, 10, 0.5).until(lambda el: self.locate(by, value), message='元素获取失败')# 强制等待
def sleep(self, time_):time.sleep(time_)# 句柄的切换:为了满足有些场景下不需要close,需要考虑逻辑的处理
def switch_handle(self, status=1):handles = self.driver.window_handlesif status == 1:self.driver.close()self.driver.switch_to.window(handles[1])# 断言预期结果是否包含在实际结果内def assert_almost_equal(self, by, value, expected):try:reality = self.locate(by, value).textassert expected in reality, '{0}不在{1}的范围内'.format(expected, reality)return Trueexcept:return False# 文本断言def assert_text(self, by, value, expected):try:reality = self.locate(by, value).textassert expected == reality, '{0}与{1}不相等'.format(expected, reality)except Exception as e:print('断言失败:{}'.format(e))# 切换Iframedef switch_frame(self, value, by=None):if by is None:self.driver.switch_to.frame(value)else:self.driver.switch_to.frame(self.locate(by, value))

调试

if name == 'main': key = Keys('谷歌') key.open('百度一下,你就知道')

调用方法
'''通过调用关键字驱动类来实现自动化测试效果测试用例类,调用关键字驱动类,来实现测试的业务需求。
'''
from class07_web_keys.web_keys import Keyskey = Keys('Chrome')# 百度搜索
# key.open('http://www.baidu.com')
# key.input('id', 'kw', '虚竹关键字')
# key.click('id', 'su')
# key.sleep(5)
# key.quit()# 注册流程
key.open('http://39.98.138.157/shopxo/index.php?s=/index/user/logininfo.html')
key.input('name', 'accounts', 'xuzhu666')
key.input('name', 'pwd', '123456')
key.click('xpath', '//button[text()="登录"]')
key.sleep(5)
key.quit()
讲义:
## Openpyxl 
Excel数据驱动,核心关键是要用excel文件来实现数据的管理。 
数据驱动:正常而言,所有的测试框架一定是代码与数据的分离。通过分离,可以更好地管理各个内容。可以更加轻量级的维护成本。一般而言,相对较多的测试数据内容,都可以通过数据驱动的形态来实现数据的导入和管理。数据驱动的表现形式就是文件的形态。 
常见的数据驱动形态:Excel、Yaml、Py、Json。。。。 
Excel数据驱动:基于excel文件形态来实现的数据驱动。管理整个测试过程中的所有数据内容。 
优势:对于编程能力几乎为零的人而言,是很好一种驱动形态。 
劣势:数据的管理和维护上,相较于其他的数据驱动形态而言,会更加麻烦一些。 
很多人还是在使用xlwt和xlrd的库来操作数据库。现在已经淘汰了。 
### 环境部署 
pip install openpyxl 
### 数据驱动的实现 
把测试数据放到excel文件中,在python的环境下,基于测试数据的内容,来执行相应的自动化操作行为。 '''用于配置excel的写入格式内容:把断言的结果Pass和Failed更加突出一些PatternFill类用于定义颜色Font类用于定义格式
'''
from openpyxl.styles import PatternFill, Font# pass写入配置
def pass_(cell, row, column):cell(row=row, column=column).value = 'Pass'# 单元格显示:绿色加粗cell(row=row, column=column).fill = PatternFill('solid', fgColor='AACF91')cell(row=row, column=column).font = Font(bold=True)# Failed写入配置
def failed(cell, row, column):cell(row=row, column=column).value = 'Failed'# 单元格显示:绿色加粗cell(row=row, column=column).fill = PatternFill('solid', fgColor='FF0000')cell(row=row, column=column).font = Font(bold=True)---------------------------------------------------------
'''excel文件读取类。用于实现测试用例文件的读取与执行。
'''
import pathlibimport openpyxlfrom conf import log_conf
from exce_read import excel_conf
from web_keys.keys import Keys# 解析测试用例中测试参数单元格的内容,并转换为字典的形态返回
def arguments(value):data = dict()# 如果value有值,进行切分if value:str_temp = value.split(';')for temp in str_temp:t = temp.split('=', 1)data[t[0]] = t[1]# 如果value没有值,就不做任何操作。else:passreturn data#
#
# # 获取当前路径,并切换到excel路径下
# def path():
#     file = pathlib.Path(__file__).resolve().parents[1] / 'data/自动化测试用例demo.xlsx'
#     return file# 获取指定的测试用例文件,进行自动化执行
def read(file, log):# 获取log# log_file = pathlib.Path(__file__).resolve().parents[1] / 'conf/log.ini'# log = log_conf.get_log(log_file)# 获取当前路径,并切换到excel路径下,pathlib.Path函数返回的是路径,不是str,所以不能用连接符# file = pathlib.Path(__file__).resolve().parents[1] / 'data/自动化测试用例demo.xlsx'# 获取excel中的内容excel = openpyxl.load_workbook(file)# sheet = excel['Sheet1']# 获取所有的sheet页,来执行里面的测试内容for name in excel.sheetnames:sheet = excel[name]log.info('**********正在执行{}Sheet页*********'.format(name))for values in sheet.values:# 获取测试用例的正文内容if type(values[0]) is int:# 用例描述可以用于日志的输出log.info('*****************正在执行:{}*****************'.format(values[3]))# print(values)# 参数的处理:通过一个dict来接收所有的参数内容。便于定值不定长的传参形态# 参数最终形态:'type_=Chrome' 改变为 {type_: 'Chrome'}data = arguments(values[2])# print(data)'''调用的函数是values[1],这是固定的。操作行为的调用分为以下几种不同类型:1. 实例化2. 基于实例化对象进行的操作行为3. 断言机制:有预期与实际的对比,以及有单元格测试结果的写入''''''第一行open_browser第二行open:getattr(key,'open')(**data)key.open(**data)key.open(url='http://www.baidu.com')第三行input:getattr(key,'input')(**data)key.input(**data)key.input(by='id',value='kw',txt='虚竹的Excel')第四行click'''# 实例化操作if values[1] == 'open_browser':key = Keys(**data)# 断言行为:基于断言的返回结果来判定测试的成功失败,并进行写入操作elif 'assert' in values[1]:status = getattr(key, values[1])(expected=values[4], **data)# 基于status判定写入的测试结果if status:excel_conf.pass_(sheet.cell, row=values[0] + 2, column=6)else:excel_conf.failed(sheet.cell, row=values[0] + 2, column=6)# 保存Excel:放在这里以确保每一次写入都可以被保存,避免因为代码报错而未保存之前的测试结果excel.save(file)# 常规操作行为else:getattr(key, values[1])(**data)excel.close()log.info('********执行完毕*********')
编号操作步骤测试数据行为描述预期结果实际结果
1open_browsertype_Chrome启动浏览器
2openurl=访问指定网址
3inputby=id;value=kw;tinputxt=虚竹输入搜索虚竹
4clickby=id;cvalue=su点击百度一下
5sleeptime_=3等待3秒钟

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com