python自动化测试学习笔记合集三

181 篇文章 19 订阅
5 篇文章 0 订阅


 

上次我们学到了redis的一些操作,下面来实际运用以下。

这里我们先来学习一下什么是cookie和session。

什么是Cookie

其实简单的说就是当用户通过http协议访问一个服务器的时候,这个服务器会将一些Name/Value键值对返回给客户端浏览器,并将这些数据加上一些限制条件。在条件符合时,这个用户下次再访问服务器的时候,数据又被完整的带给服务器。

因为http是一种无状态协议,用户首次访问web站点的时候,服务器对用户一无所知。而Cookie就像是服务器给每个来访问的用户贴的标签,而这些标签就是对来访问的客户端的独有的身份的一个标识,这里就如同每个人的身份证一样,带着你的个人信息。而当一个客户端第一次连接过来的时候,服务端就会给他打一个标签,这里就如同给你发了一个身份证,当你下次带着这个身份证来的时候,服务器就知道你是谁了。所以Cookie是存在客户端的,这里其实就是在你的浏览器中。

Cookie中包含了一个由名字=值(name=value)这样的信息构成的任意列表,通过Set-Cookie或Set-Cookie2HTTP响应(扩展)首部将其贴到客户端身上。

Cookie的分类

这里Cookie主要分为两种:

会话Cookie:不设置过期时间,保存在浏览器的内存中,关闭浏览器,Cookie便被销毁

普通Cookie:设置了过期时间,保存在硬盘上

关于Session

上面我们知道了Cookie可以让服务器端跟踪每个客户端的访问,但是每次客户端的访问都必须传回这些Cookie,如果Cookie很多,这无形地增加了客户端与服务端的数据传输量,而Session的出现正是为了解决这个问题。

同一个客户端每次和服务端交互时,不需要每次都传回所有的Cookie值,而是只要传回一个ID这个ID是客户端第一次访问服务器的时候生成的,而且每个客户端是唯一的。这样每个客户端就有了一个唯一的ID,客户端只要传回这个ID就行了,这个ID通常是NANE为JSESIONID的一个Cookie。所以Session其实是利用Cookie进行信息处理的。

cookie和session的共同之处在于:cookie和session都是用来跟踪浏览器用户身份的会话方式。

cookie和session的区别是:cookie数据保存在客户端,session数据保存在服务器端。

cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session,当然也没有绝对的安全,只是相对cookie,session更加安全

session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE

cookie和session各有优缺点,所以将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中。

实例:

先来验证用session登录的程序,分析:

首先先设计一个登录的程序,生成session写入redis,然后设计一个查询程序,传入session进行校验。

    第一次登录:从my_user表中验证用户是否存在,用户存在且密码正确的场合生成session(规则:(当前时间戳+username))存入redis。

    第二次登录查看:

#1、先验证用户是否登陆,username,session
#2、验证session是否正确,判断和redis里边是否一致
#3、如果一致返回查询结果
#4、如果不一致,提示session非法
#              session不存在,则提示用户未登录
#              session不一致,登陆失败
#在K-V中传入session

以下是常用工具,放在lib目录的tools文件中:

#常用工具
import pymysql,hashlib,time
import redis
from conf import setting
#

#def op_mysql(host,user,passwd,db,sql,port=3306,charset='utf8'):
def op_mysql(sql):
    conn=pymysql.connect(host=setting.MYSQL_HOST,user=setting.USER,passwd=setting.PASSWORD,port=setting.PORT,db=setting.DB,charset='utf8')
    cur=conn.cursor(cursor=pymysql.cursors.DictCursor)
    cur.execute(sql)
    sql_start=sql[:6].upper()
    if sql_start=='SELECT':#取sql的前6位,判断它是什么类型的语句。
        res=cur.fetchall()
    else:
        conn.commit()
        #res='ok'
    cur.close()
    conn.close()
    return res
def op_redis(k,v=None,expired=0,db=0):
#def op_redis(host,passwd,k,v=None,port=6379,db=1):
    #r=redis.Redis(host=host,password=passwd,port=port,db=db)
    r=redis.Redis(host=setting.REDIS_HOST,password=setting.REDIS_PASSWORD,port=setting.REDIS_PORT,db=db)

    if v:
        r.setex(k,v,expired)
        res='ok'
    else:
        #res=r.get(k).decode()#获取不到的时候返回none,none不能直接进行decode操作
        res=r.get(k)
        if res:
            res=res.decode()
        else:
            res='none'
    return res


def md5_password(st:str):#规定传参的类型必须是str类型
    #st = hashlib.md5()
    bytes_st=st.encode()
    m=hashlib.md5(bytes_st)
    return m.hexdigest()

#main.py

import flask,time,hashlib
from lib.tools import  op_mysql,op_redis,md5_password
import json
server=flask.Flask(__name__)
@server.route('/login',methods=['post'])
def login():
    username=flask.request.values.get('name','')
    password=flask.request.values.get('passwd','')
    sql="select * from my_user where username='%s';"%(username)
    if username and password:
        if op_mysql(sql):
            print(op_mysql(sql))
            if password==op_mysql(sql)[0]['passwd']:
                session=md5_password(str(time.time())+username)
                op_redis('session:%s'%username,session,expired=6000,db=2)
                response={'code':200,'msg':'登陆成功','session':session}
            else:
                response={'code':101,'msg':'密码不正确'}
        else:
            response={'code':102,'msg':'用户不存在'}
    else:
        response={'code':103,'msg':'用户名或密码不能为空'}
    return json.dumps(response,ensure_ascii=False)

启动服务后,在postman中调用127.0.0.1:8088/login?name=pei&passwd=123456,执行一个正确的用户登录,:

{"msg": "登陆成功", "code": 200, "session": "28b14dea0c7a668650fbb19f6364f482"}

查看到redis里边已经插入了一个session数据:

下面进行第二部,传入用户名、session,如果验证正确则查询中表中的数据:

@server.route('/getall',methods=['post','get'])
def getall():
    username=flask.request.values.get('name')
    session=flask.request.values.get('session')
    k='session:%s'%(username)
    redis_session=op_redis(k,db=2)
    if username and session:
        if redis_session:
            if redis_session==session:

                sql="select red,blue from seq "
                response = op_mysql(sql)
            else:
                response={'code':101,'msg':'session非法'}
        else:
            response={'code':102,'msg':'未登录'}
    else:
        response={'code':103,'msg':'必填参数为空'}
    return  json.dumps(response,ensure_ascii=False)

以上是在k-v参数中传入session值,如需需要在cookie中传入session,代码如下:

就是把session=flask.request.values.get('session')改为session=flask.request.cookies.get('session')则取值就是在cookie中进行取值了。

@server.route('/getall_cookie',methods=['post','get'])
def getall_cookie():
    username=flask.request.values.get('name')
    session=flask.request.cookies.get('session')
    k='session:%s'%(username)
    redis_session=op_redis(k,db=2)
    if username and session:
        if redis_session:
            if redis_session==session:

                sql="select red,blue from seq "
                response = op_mysql(sql)
            else:
                response={'code':101,'msg':'session非法'}
        else:
            response={'code':102,'msg':'未登录'}
    else:
        response={'code':103,'msg':'必填参数为空'}
    return  json.dumps(response,ensure_ascii=False)

在我们登录购物网站的话,如果勾选记住密码,一般情况下就是在客户端浏览器上添加了cookie,这样用户打开网站后后台会自动校验cookie信息,不用每次都传一次,如下是设置cookie的代码:

要在页面添加cookie需要先response=flask.make_response(),然后response.set_cookie('session',session)set上要添加的cookie信息

@server.route('/login_setcookie',methods=['post'])
def login_setcookie():
    username=flask.request.values.get('name','')
    password=flask.request.values.get('passwd','')
    sql="select * from my_user where username='%s';"%(username)
    if username and password:
        if op_mysql(sql):
            print(op_mysql(sql))
            if password==op_mysql(sql)[0]['passwd']:
                session=md5_password(str(time.time())+username)
                op_redis('session:%s'%username,session,expired=6000,db=2)
                response=flask.make_response()
                response.set_cookie('session',session)
                msg={'code':200,'msg':'登陆成功','session':session}
            else:
                msg={'code':101,'msg':'密码不正确'}
        else:
            msg={'code':102,'msg':'用户不存在'}
    else:
        msg={'code':103,'msg':'必填参数为空'}
    return response

添加cookie后,我们在调用getall_cookie时只传入name,就能直接获取到seq表中的数据了。

补充:

mysql注入原理

上述代码中存在的sql语句如下:

sql="select * from my_user where username='%s';"%(username)

在获取username时,由于存在‘’,所以存在漏洞;

我们知道‘1’=‘1’是恒为真的,我们可以通过‘’,来模拟制造出这种恒等式,使sql在执行时跳过一些校验,从而进阶访问系统。

当我们输入name=“' or '1'='1”

我们将上述name的值带入sql如下:

sql="select * from my_user where username='' or '1'='1';"

我们在sqlyog中my_user表中执行这个语句,查询出了所有的用户信息,

在一些查询操作中,很容易产生漏洞,造成信息的泄露。

还有一种注入方式是:username="' show tabales ; --"

sql="select * from my_user where username='' show tabales ; --';"

sql语句中--表示注释掉后边的语句,这样就查询出了所有的表,可以对数据库随意进行操作。

为了防止sql的注入,在编写sql的时候我们尽量避免使用‘’,写成如下方式:

sql="select * from my_user where username=%s;",username

这样在传参的时候,可以直接传到输入的参数进行取值,例如:

def op_mysql_new(sql,*data):#第一个是位置参数,第二个是可变参数
    cur.execute(sql,data)
    #data是一个元祖,*data获取出所有传过去的参数
    print(cur.fetchall())
sql="select * from users where name=%s and passwd=%s;"
name='pei'
passwd='123456'
op_mysql_new(sql,name,passwd)

###################################################33

传参:
def test(a,b):
    print(a,b)

li=[1,2]
test(*li)#一个星代表把list里边的数据穿进去
d={'a':'123','b':'456'}
test(**d)#两个星代表从字典里边的数据传进去

python自动化测试学习笔记-6urllib模块&request模块

python3的urllib 模块提供了获取页面的功能。

urllib.request.urlopen(urldata=None, [timeout, ]*cafile=Nonecapath=Nonecadefault=Falsecontext=None)

-         url:  需要打开的网址

-         data:Post提交的数据

-         timeout:设置网站的访问超时时间

直接用urllib.request模块的urlopen()获取页面,page的数据格式为bytes类型,需要decode()解码,转换成str类型。

import urllib.request

# import json
# import requests
url="http://api.nnzhp.cn/api/user/stu_info?stu_name=xiaohei"
req=urllib.request.urlopen(url)
res=req.read().decode()
print(res)

执行:

{
        "error_code": 2,
        "msg": "无结果"
}

urllib 中实现post数据请求

urlopen()的data参数默认为None,当data参数不为空的时候,urlopen()提交方式为Post。

url1='http://api.nnzhp.cn/api/user/login '
data={
    'username':'niuhanyang',
    'passwd':'aA123456'
}
#urlencode()主要作用就是将url附上要提交的数据。经过urlencode()转换后的data数据为?username=niuhanyang&passwd=aA123456,
## Post的数据必须是bytes或者iterable of bytes,不能是str,因此需要进行encode()编码
data=urllib.parse.urlencode(data).encode('utf-8')
#最终提交的url是http://api.nnzhp.cn/api/user/login?username=niuhanyang?passwd=aA123456
req=urllib.request.Request(url1,data=data)
page=urllib.request.urlopen(req).read()
print(page.decode())

执行查看结果:

{
        "error_code": 0,
        "login_info": {
                "login_time": "20180129202722",
                "sign": "7e4c46e5790ca7d5165eb32d0a895ab1",
                "userId": 1
        }
}

我们看到使用urllib会比较麻烦,需要转码,赋值等操作,request模块可以更加简便的完成请求操作,如下:

1、首先需要安装Request模块

pip install requests

2、导入request模块

import requests

各种接口操作如下:

import requests
import json
#发送无参数的get请求
url='http://www.baidu.com'
req=requests.get(url)
print(req.text)#返回的字符串类型

#发送有参数的request请求
url1='http://api.nnzhp.cn/api/user/stu_info?stu_name=feifei'
req1=requests.get(url1)
print(req1.json())#返回的字典列表

#发送post请求
url2='http://api.nnzhp.cn/api/user/login '
data={
    'username':'niuhanyang',
    'passwd':'aA123456'
}
req=requests.post(url2,data)#发送的post氢气,第一个参数是url,第二个参数是请求的数据
print(req.json())

#发送入参是json类型的post请求
url3='http://api.nnzhp.cn/api/user/add_stu'
data={
    'name':'feifei',
    'phone':'13121111112',
    'grade':'1000'
}

req=requests.post(url3,json=data)
print(req.json())

#发送带有cookie的post请求
#添加cookie
url4='http://api.nnzhp.cn/api/user/gold_add'
data={
    'stu_id':230,
    'gold':88888
}
cookies={'feifei':'a2b454c3830e20e7d9916f6b52d6a3a7'}
req=requests.post(url4,data,cookies=cookies)
print(req.json())

#发送带有Referer请求的post请求
#
url5='http://api.nnzhp.cn/api/user/all_stu'
data={
    'Referer':'http://api.nnzhp.cn/'
}
req=requests.get(url5,headers=data)
print(req.json())

#下载文件请求

url6='https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1517138333609&di=327abc49fc6d63fed19124cdf826d130&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201510%2F17%2F20151017223821_ZSWBc.jpeg'
r=requests.get(url6)#下载直接请求url然后进行保存
#print(r.status_code)#请求状态码是二进制
res=r.content#获取二进制格式
fw=open('feifei.jpg','wb')
fw.write(res)#保存文件
fw.close()

#上传文件

url7='http://api.nnzhp.cn/api/file/file_upload'
f=open('E:\\besttest\\python\\besttest_code\\练习\\day7笔记\\api\\feifei.jpg','rb')
r=requests.post(url7,files={'file':f})
print(r.json())
#
#下载页面
url='http://www.runoob.com/python/python-intro.html'
r=requests.get(url)
f=open('python.html','wb')
f.write(r.content)
f.close()

python自动化测试学习笔记-6excel操作xlwt、xlrd、xlutils模块

python中通过xlwt、xlrd和xlutils操作xls

  • xlwt模块用于在内存中生成一个xls/xlsx对象,增加表格数据,并把内存中的xls对象保存为本地磁盘xls文件;
  • xlrd模块用于把本地xls文件加载到内存中,可以读取xls文件的表格数据,查询xls文件的相关信息;
  • xlwt可以生成xls文件,xlrd可以读取已经存在的xls文件,但是如果要修改本地已经存在的xls文件,就需要用到xlutils模块。
  • xlutils模块是xlrd和xlwt之间的桥梁,可以使用xlutils模块中的copy模块,拷贝一份通过xlrd读取到内存中的xls对象,就可以在拷贝对象上像xlwt中那样修改xls表格的内容,并保存到本地

要使用这些模块首先要安装导入:

pip install xlrd

pip install xlwt

pip install xluntils

安装好后进行导入

import xlrd
import xlwt
from xlutils.copy import copy
#创建一个excel
book=xlwt.Workbook()
#添加一个sheet
sheet=book.add_sheet('sheet1')
#向sheet中添加数据,行、列、value值
sheet.write(0,0,'id')
sheet.write(0,1,'name')
sheet.write(0,2,'age')
sheet.write(0,3,'sex')
#保存xls,微软的office不能以xlsx为结尾,wps随意
book.save('peitest.xls')

执行后生成了一个excel文件,查看内容

但是像这样一个单元格一个单元格的插入又很浪费时间,我们可以用循环来实现,如下:

##############################
#利用循环写数据
#创建一个excel
book=xlwt.Workbook()
#添加一个sheet
sheet=book.add_sheet('sheet2')
row=0
col=0
list=[
    ['id','name','age','sex'],
    ['01','wang','13','女'],
    ['02','li','23','女'],
    ['03','hang','34','男'],
    ['04','wu','16','女'],
    ['05','ma','22','女']
]
#循环行
for r in range(6):
    #循环列
    for c in range(4):
        #根据行和列找到要赋值的value
        sheet.write(r,c,list[r][c])
        c+=1
    r+=1
#保存excel
book.save('peitest.xls')

执行查看结果:

上述方法是已知数据的行和列来循环的,如果行和列太多的时候就不方便了,我们可以通过循环list来添加数据,如下:

#创建一个excel
book=xlwt.Workbook()
#添加一个sheet
sheet=book.add_sheet('sheet3')
list=[
    ['id','name','age','sex'],
    ['01','wang','13','女'],
    ['02','li','23','女'],
    ['03','hang','34','男'],
    ['04','wu','16','女'],
    ['05','ma','22','女']
]

r=0
for stu in list:
    c=0
    for s in stu:
        sheet.write(r,c,s)
        c+=1
    r+=1
book.save('peitest.xls')

执行查看结果:

读取excel的数据是通过xlrd模块来实现的,如下:

###############################################################################
#读取excel数据
book=xlrd.open_workbook('peitest.xls')
#获取sheet,通过index
sheet=book.sheet_by_index(0)
#获取sheet通过sheet名称
#sheet=book.sheet_by_name('sheet3')
value=sheet.cell(0,0).value
value1=sheet.cell(0,1).value
value2=sheet.cell(0,2).value
value3=sheet.cell(0,3).value

print(value)
print(value1)
print(value2)
print(value3)

执行查看结果:

id
name
age
sex

同样的,如果我们要读取出excel所有的数据,也可以用循环来实现:

#####################################33
#循环来实现读取excel数据
#打开excel
book=xlrd.open_workbook('peitest.xls')
#获取sheet
sheet=book.sheet_by_name('sheet3')
#获取sheet中的行数
row=sheet.nrows
#获取sheet中的列数
col=sheet.ncols
#获取每一行的数据
for i in sheet.get_rows():
    print(i)
#获取某一行的数据,通过循环获取出所有数据
for r in range(row):
    print(sheet.row_values(r))
#获取某一列的数据,通过循环获取出所有数据
for c in range(col):
    print(sheet.col_values(c))

执行查看结果:

[text:'id', text:'name', text:'age', text:'sex']
[text:'01', text:'wang', text:'13', text:'女']
[text:'02', text:'li', text:'23', text:'女']
[text:'03', text:'hang', text:'34', text:'男']
[text:'04', text:'wu', text:'16', text:'女']
[text:'05', text:'ma', text:'22', text:'女']
['id', 'name', 'age', 'sex']
['01', 'wang', '13', '女']
['02', 'li', '23', '女']
['03', 'hang', '34', '男']
['04', 'wu', '16', '女']
['05', 'ma', '22', '女']
['id', '01', '02', '03', '04', '05']
['name', 'wang', 'li', 'hang', 'wu', 'ma']
['age', '13', '23', '34', '16', '22']
['sex', '女', '女', '男', '女', '女']

我们看到上面第一种方法,每一个数据都带一个text,不方便进行后续操作,所以一般用第二种方式来实现。

修改文件

#######################################
import xlrd
import xlwt
from xlutils.copy import copy
#修改excel文件
#打开文件
book=xlrd.open_workbook('peitest.xls')
#复制一份文件用于修改
book2=copy(book)
#获取要修改的sheet
sheet=book2.get_sheet(0)
#修改指定的行和列
sheet.write(0,0,'序号')
#保存为新的excel
book2.save('peitest1.xls')

执行查看结果:

好了  这次就学习到这了哦! 

还想学习的话,记得收藏及关注哦.

感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

① 2000多本软件测试电子书(主流和经典的书籍应该都有了)

② 软件测试/自动化测试标准库资料(最全中文版)

③ 项目源码(四五十个有趣且经典的练手项目及源码)

④ Python编程语言、API接口自动化测试、web自动化测试、App自动化测试(适合小白学习)
————————————————

 

 

⑤ Python学习路线图(告别不入流的学习) 

 在我的QQ技术交流群里(技术交流和资源共享,广告进来腿给你打断)

可以自助拿走,群号768747503备注(csdn999768747503备注(csdn999))群里的免费资料都是笔者十多年测试生涯的精华。还有同行大神一起交流技术哦。


————————————————
版权声明:本文为CSDN博主「自动化测试君」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Yanan990830/article/details/120874523

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值