全csdn最全最详细的Pytest自动化测试框架实战,封神级讲解_pytest资料

91 阅读6分钟
    "body":
    {
      "password":"admin",
      "sex":"男",
      "age":18
    }
  },
  "response":
  [
    {
      "message":
      {
        "username": "用户名不能为空"
      }
    }
  ]
},
{
  "request":
  {
    "url": "http://localhost:5000/login",
    "body":
    {
      "username":"wuya",
      "sex":"男",
      "age":18
    }
  },
  "response":
  [
    {
    "message":
    {
      "password": "账户密码不能为空"
    }
  }
  ]
},
{
  "request":
  {
    "url": "http://localhost:5000/login",
    "body":
    {
      "username":"wuya",
      "password":"admin",
      "sex":"asdf",
      "age":18
    }
  },
  "response":
  [
    {
      "message":
      {
        "sex": "性别只能是男或者女"
      }
    }
  ]
},
{
  "request":
  {
    "url": "http://localhost:5000/login",
    "body":
    {
      "username":"wuya",
      "password":"admin",
      "sex":"男",
      "age":"rrest"
    }
  },
  "response":
  [
    {
      "message":
      {
        "age": "年龄必须为正正数"
      }
    }
  ]
},
{
  "request":
  {
    "url": "http://localhost:5000/login",
    "body":
    {
      "username":"wuya",
      "password":"admin",
      "sex":"男",
      "age":"18"
    }
  },
  "response":
  [
    {
      "age": 18,
      "password": "admin",
      "sex": "男",
      "username": "wuya"
    }
  ]
}

] }


涉及到的测试代码为:



#!/usr/bin/env python #!coding:utf-8 import pytest import requests import json

def readJson(): return json.load(open('login.json','r'))['item']

@pytest.mark.parametrize('data',readJson()) def test_json_login(data): r=requests.post( url=data['request']['url'], json=data['request']['body']) assert r.json()==data['response'][0]

if name == 'main': pytest.main(["-s","-v","test_json_login.py"])


## 3.yaml文件


再来看分离到Yaml文件的数据:




#用户名请求为空 "url": "http://localhost:5000/login" "body": '{ "password":"admin", "sex":"男", "age":18 }' "expect": '{ "message": { "username": "用户名不能为空" } }'

#密码参数为空 "url": "http://localhost:5000/login" "body": '{ "username":"admin", "sex":"男", "age":18 }' "expect": '{ "message": { "password": "账户密码不能为空" } }'

#校验性别参数的验证 "url": "http://localhost:5000/login" "body": '{ "username":"wuya", "password":"admin", "sex":"asdf", "age":18 }' expect: '{ "message": { "sex": "性别只能是男或者女" } }'

#校验年龄是否是正整数 "url": "http://localhost:5000/login" "body": '{ "username":"wuya", "password":"admin", "sex":"男", "age":"rrest" }' "expect": '{ "message": { "age": "年龄必须为正正数" } }'

#登录成功 "url": "http://localhost:5000/login" "body": '{ "username":"wuya", "password":"admin", "sex":"男", "age":"18" }' "expect": '{ "age": 18, "password": "admin", "sex": "男", "username": "wuya" }'


涉及到的测试代码为:



#!/usr/bin/env python #!coding:utf-8 import pytest import requests import yaml

def readYaml(): with open('login.yaml','r') as f: return list(yaml.safe_load_all(f))

@pytest.mark.parametrize('data',readYaml()) def test_login(data): r=requests.post( url=data['url'], json=json.loads(data['body'])) assert r.json()==json.loads(data['expect'])


## 4.CSV


分离到CSV的文件内容为:


![图片](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/3d79cb69c9bc416ea120a7cdb7c312e1~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzIxMjA3NDIwNDUy:q75.awebp?rk3s=f64ab15b&x-expires=1772949871&x-signature=Yrxjn%2BQ1bI287I%2BAzM9enY0DO0E%3D)


涉及到的测试代码为:



#!/usr/bin/env python #!coding:utf-8 import pytest import requests import csv

def readCsv(): data=list() with open('login.csv','r') as f: reader=csv.reader(f) next(reader) for item in reader: data.append(item) return data

@pytest.mark.parametrize('data',readCsv()) def test_csv_login(data): r=requests.post( url=data[0], json=json.loads(data[1])) assert r.json()==json.loads(data[2])

最后来看分离到Excel的文件内容:


![图片](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/649953f2576e4365a28d618ee128609b~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzIxMjA3NDIwNDUy:q75.awebp?rk3s=f64ab15b&x-expires=1772949871&x-signature=wwpUYMPZkLZSnm2KpdH0Nl84lgU%3D)


涉及到的测试代码为:



#!/usr/bin/env python #!coding:utf-8 import pytest import requests import xlrd

def readExcel(): data=list() book=xlrd.open_workbook('login.xls') sheet=book.sheet_by_index(0) for item in range(1,sheet.nrows): data.append(sheet.row_values(item)) return data

@pytest.mark.parametrize('data',readExcel()) def test_excel_login(data): r=requests.post( url=data[0], json=json.loads(data[1])) assert r.json()==json.loads(data[2])


其实我们发现套路都是一样的,不管把数据分离到什么样的数据格式下,都得符合它的本质思想,也就是参数化的本质是对列表中的对象进行循环赋值,把握住这样的一个思想就可以了。整合上面的所有代码,完整代码为:



#!/usr/bin/env python #!coding:utf-8 import pytest import requests import json import yaml import csv import xlrd

def readJson(): return json.load(open('login.json','r'))['item']

def readYaml(): with open('login.yaml','r') as f: return list(yaml.safe_load_all(f))

def readCsv(): data=list() with open('login.csv','r') as f: reader=csv.reader(f) next(reader) for item in reader: data.append(item) return data

def readExcel(): data=list() book=xlrd.open_workbook('login.xls') sheet=book.sheet_by_index(0) for item in range(1,sheet.nrows): data.append(sheet.row_values(item)) return data

@pytest.mark.parametrize('data',readJson()) def test_json_login(data): r=requests.post( url=data['request']['url'], json=data['request']['body']) assert r.json()==data['response'][0]

@pytest.mark.parametrize('data',readYaml()) def test_yaml_login(data): r=requests.post( url=data['url'], json=json.loads(data['body'])) assert r.json()==json.loads(data['expect'])

@pytest.mark.parametrize('data',readCsv()) def test_csv_login(data): r=requests.post( url=data[0], json=json.loads(data[1])) assert r.json()==json.loads(data[2])

@pytest.mark.parametrize('data',readExcel()) def test_excel_login(data): r=requests.post( url=data[0], json=json.loads(data[1])) assert r.json()==json.loads(data[2])


执行后的结果信息为:


![图片](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/420cf22c2ce94a2a9e1370f7996d44c8~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzIxMjA3NDIwNDUy:q75.awebp?rk3s=f64ab15b&x-expires=1772949871&x-signature=%2BUJ%2BVVygt0P1MdugxRaWLJfLxFs%3D)


     Pytest测试框架最强大的功能除了丰富的第三方插件外,还有就是它的Fixture和共享Fixture的conftest.py,下面具体来看被测试的接口代码:



from flask import Flask,make_response,jsonify,abort,request from flask_restful import Api,Resource from flask_httpauth import HTTPBasicAuth

from flask import Flask from flask_jwt import JWT, jwt_required, current_identity from werkzeug.security import safe_str_cmp

app=Flask(name) app.debug = True app.config['SECRET_KEY'] = 'super-secret' api=Api(app=app) auth=HTTPBasicAuth()

@auth.get_password def get_password(name): if name=='admin': return 'admin' @auth.error_handler def authoorized(): return make_response(jsonify({'msg':"请认证"}),403)

books=[ {'id':1,'author':'wuya','name':'Python接口自动化测试实战','done':True}, {'id':2,'author':'无涯','name':'Selenium3自动化测试实战','done':False} ]

class User(object): def init(self, id, username, password): self.id = id self.username = username self.password = password

def str(self): return "User(id='%s')" % self.id

users = [ User(1, 'wuya', 'asd888'), User(2, 'admin', 'admin'), ]

username_table = {u.username: u for u in users} userid_table = {u.id: u for u in users}

def authenticate(username, password): user = username_table.get(username, None) if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')): return user

def identity(payload): user_id = payload['identity'] return userid_table.get(user_id, None)

jwt = JWT(app, authenticate, identity)

class Books(Resource):

decorators = [auth.login_required]

decorators=[jwt_required()]

def get(self): return jsonify({'status':0,'msg':'ok','datas':books})

def post(self): if not request.json: return jsonify({'status':1001,'msg':'请求参数不是JSON的数据,请检查,谢谢!'}) else: book = { 'id': books[-1]['id'] + 1, 'author': request.json.get('author'), 'name': request.json.get('name'), 'done': True } books.append(book) return jsonify({'status':1002,'msg': '添加书籍成功','datas':book}, 201)

class Book(Resource):

decorators = [auth.login_required]

decorators = [jwt_required()]

def get(self,book_id): book = list(filter(lambda t: t['id'] == book_id, books)) if len(book) == 0: return jsonify({'status': 1003, 'msg': '很抱歉,您查询的书的信息不存在'}) else: return jsonify({'status': 0, 'msg': 'ok', 'datas': book})

def put(self,book_id): book = list(filter(lambda t: t['id'] == book_id, books)) if len(book) == 0: return jsonify({'status': 1003, 'msg': '很抱歉,您查询的书的信息不存在'}) elif not request.json: return jsonify({'status': 1001, 'msg': '请求参数不是JSON的数据,请检查,谢谢!'}) elif 'author' not in request.json: return jsonify({'status': 1004, 'msg': '请求参数author不能为空'}) elif 'name' not in request.json: return jsonify({'status': 1005, 'msg': '请求参数name不能为空'}) elif 'done' not in request.json: return jsonify({'status': 1006, 'msg': '请求参数done不能为空'}) elif type(request.json['done'])!=bool: return jsonify({'status': 1007, 'msg': '请求参数done为bool类型'}) else: book[0]['author'] = request.json.get('author', book[0]['author']) book[0]['name'] = request.json.get('name', book[0]['name']) book[0]['done'] = request.json.get('done', book[0]['done']) return jsonify({'status': 1008, 'msg': '更新书的信息成功', 'datas': book})

def delete(self,book_id): book = list(filter(lambda t: t['id'] == book_id, books)) if len(book) == 0: return jsonify({'status': 1003, 'msg': '很抱歉,您查询的书的信息不存在'}) else: books.remove(book[0]) return jsonify({'status': 1009, 'msg': '删除书籍成功'})

api.add_resource(Books,'/v1/api/books') api.add_resource(Book,'/v1/api/book/int:book_id')

if name == 'main': app.run(debug=True)



我们通过token的方式,首先需要授权,授权成功后才可以针对书籍这些接口进行操作,如添加删除以及查看所有的书籍信息,那么获取token这部分的代码完全可以放在conftest.py里面,具体源码为:



#!/usr/bin/env python #!coding:utf-8 import requests import pytest

@pytest.fixture() def getToken(): '''获取token''' r=requests.post( url='http://localhost:5000/auth', json={"username":"wuya","password":"asd888"}) return r.json()['access_token']


Fixture一点需要考虑的是初始化与清理,也就是说在一个完整的测试用例中,都必须都得有初始化与清理的部分,这样才是一个完整的测试用例的。Fixture可以很轻松的来解决这部分,还有一点需要说的是Fixture的函数也可以和返回值整合起来,如添加书籍成功后,把数据ID返回来,下面就以查看书籍为案例,那么查看书籍前提是需要添加书籍,这样可以查看,最后把添加的书籍删除,这样一个测试用例执行完成后才符合它的完整流程,具体测试代码如下:


![img](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/5cc4f01218794acda3751d031b79189e~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzIxMjA3NDIwNDUy:q75.awebp?rk3s=f64ab15b&x-expires=1772949871&x-signature=olrsoWzaky8DQHPiiYU4u%2BiRm%2BY%3D)
![img](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/c16496fc59f641f9ab54e536f6736a73~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzIxMjA3NDIwNDUy:q75.awebp?rk3s=f64ab15b&x-expires=1772949871&x-signature=R75%2FAwMCdeNzhmAmo7a%2FFHGLdSM%3D)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**了解详情》docs.qq.com/doc/DSlVlZExWQ0FRSE9H**