接口自动化测试实战1(项目接口开发)

前言

 

只包含后端接口,技术栈用的是:python+flask+mysql+redis

环境介绍

  1. python:门槛低,第三方库丰富

  2. flask:轻量级web开发框架,快速上手

  3. mysql:主流的数据库,本项目用于储存用户信息,python中可以用pymysql库操作mysql,flask中也有对应的组建

  4. redis:主流的缓存数据库,本项目用于存储token,python中可以用redis库操作redis

环境准备

  1. windows下安装python3.x版本

  2. windows下安装pycharm

  3. mysql安装(建议linux下)

  4. 客户端navicat安装

  5. redis安装(建议linux下)

实战1:demo项目开发

开发几个涉及关联的接口

interface_demo项目需求

用户信息管理,可以注册、登录、添加用户、删除用户

注册:任何用户可以注册,对用户提交的注册信息进行校验,返回对应的信息,其中:

  用户名:必填,唯一

  密码:必填,只能6-12位,入库是加盐加密

  真实名:必填

  性别:非必填,只能0(male)或者1(female)

  电话:必填,唯一,满足电话要求,数字,且11位

登录:用户登录,成功,则保存token到redis,其中:

  用户名:必填

  密码:必填

  如果登录成功,对用户名加时间戳的字符串进行md5加密,生成的值作为token,然后将用户名作为key,token作为value,存入redis,且设置失效时间

添加用户:只能是管理员且登录成功后,才可以添加用户

  token:必填,登录成功返回的token

  添加者:必填

  用户名:必填,唯一

  真实名:必填

  性别:非必填,只能0(male)或者1(female)

  电话:必填,唯一,满足电话要求,数字,且11位

  密码:默认是123456,不填

删除用户:只能是管理员且登录成功后,才可以删除用户

数据库表设计

navicat连接阿里云服务器mysql服务

CREATE TABLE `users`(
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(20) NOT NULL,
`password` VARCHAR(255) NOT NULL,
`realname` VARCHAR(255) NOT NULL,
`sex` TINYINT(1) DEFAULT NULL,
`phone` VARCHAR(255) NOT NULL,
`utype` TINYINT(1) DEFAULT NULL,
`addtime` datetime DEFAULT NULL,
`adduser` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `phone` (`phone`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;

创建成功后,查看表结构

MariaDB [katyhudson]> show tables;
+----------------------+
| Tables_in_katyhudson |
+----------------------+
| users               |
+----------------------+
1 row in set (0.000 sec)

MariaDB [katyhudson]> desc users;
+----------+--------------+------+-----+---------+----------------+
| Field   | Type         | Null | Key | Default | Extra         |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL   | auto_increment |
| username | varchar(20) | NO   |     | NULL   |               |
| password | varchar(255) | NO   |     | NULL   |               |
| realname | varchar(255) | NO   |     | NULL   |               |
| sex     | tinyint(1)   | YES |     | NULL   |               |
| phone   | varchar(255) | NO   | UNI | NULL   |               |
| utype   | tinyint(1)   | YES |     | NULL   |               |
| addtime | datetime     | YES |     | NULL   |               |
| adduser | varchar(255) | YES |     | NULL   |               |
+----------+--------------+------+-----+---------+----------------+
9 rows in set (0.001 sec)

接口开发实现

目录规划

 

bin:启动目录

conf:配置

data:存放数据

lib:接口及自己写的工具

start.py

import os, sys
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# print(BASE_PATH)
sys.path.insert(0, BASE_PATH)  # 将项目根路径加入环境变量
from lib.interfaces import server
from conf.settings import SERVER_PORT

if __name__ == '__main__':
   server.run(host='127.0.0.1', port=SERVER_PORT, debug=True)  # 启动服务

settings.py

# 服务配置
SERVER_PORT = 9999  # 服务的端口号

# mysql数据库配置
MYSQL_HOST = 'ip'  # ip
MYSQL_PORT = 3306  # 端口
USER = 'root'  # 用户名
PASSWORD = '123456'  # 密码
DB = 'katyhudson'  # 数据库名

# redis数据库配置
REDIS_HOST = MYSQL_HOST  # ip
REDIS_PASSWORD = '123456'  # 密码
REDIS_PORT = 6379  # 端口
EX_TIME = 6000  # token失效时间

# 其余配置
SALT = '*katyhudson*'  # 加密的盐值

interfaces.py

import flask
import time

from lib.tools import conn_mysql, md5_passwd, op_redis
from flask import request, make_response  # 获取请求参数
from flask import send_from_directory, jsonify

server = flask.Flask(__name__)  # 把这个python文件当做一个web服务
server.config['JSON_AS_ASCII'] = False  # jsonify返回的中文正常显示


# 传json
@server.route('/register1', methods=['get', 'post'])  # 第一个参数是接口的路径,第二个参数是请求方式
def reg():
   print(request.json)
   username = request.json.get("username").strip()  # 必填
   password = request.json.get("password").strip()  # 必填
   realname = request.json.get('realname', '').strip()  # 必填
   sex = request.json.get('sex', '0').strip()  # 非必填
   phone = request.json.get('phone', '').strip()  # 必填
   # u_type = request.json.get('type', '1')

   if username and password and realname and phone:
       res = conn_mysql('select username from users where username="%s";' % username)
       print(res)  # 如果数据库中没有请求的用户数据,返回None
       if res:
           if 'code' not in res:
               return '{"code":9310,"msg":"用户已经存在"}'
           else:
               return jsonify(res)
       elif len(password) < 6 or len(password) > 12:
           return '{"code":9320, "msg":"密码只能6-12位"}'
       elif not (sex == '0' or sex == '1'):
           return '{"code":9340, "msg":"性别只能是0(male)或者1(female)"}'
       elif not (phone.isdigit() and len(phone) == 11):
           return '{"code":9350, "msg":"手机号格式不正确"}'
       elif conn_mysql('select phone from users where phone="%s";' % phone):
           return '{"code":9360, "msg":"手机号已被注册"}'
       else:
           password = md5_passwd(password)  # 调用加密函数
           sql = 'insert into users(username,password,realname,sex,phone,utype,addtime,adduser) values ("%s","%s","%s","%s","%s","%s",now(),"%s");' % (
           username, password, realname, sex, phone, '1', username)
           conn_mysql(sql)
           return '{"code":9370,"msg":"恭喜,注册成功!"}'
   else:
       return '{"code":9300,"msg":"必填参数(username,password,realname,phone)都不能为空"}'

 

# 传k-v
@server.route('/register2', methods=['get', 'post'])
def reg2():
   print(request.values)
   username = request.values.get("username").strip()  # 必填
   password = request.values.get("password").strip()  # 必填
   realname = request.values.get('realname', '').strip()  # 必填
   sex = request.values.get('sex', '0').strip()  # 非必填
   phone = request.values.get('phone', '').strip()  # 必填
   # u_type = request.json.get('type', '1')

   if username and password and realname and phone:
       if conn_mysql('select username from users where username="%s";' % username):
           return '{"code":9310,"msg":"用户已经存在"}'
       elif len(password) < 6 or len(password) > 12:
           return '{"code":9320, "msg":"密码只能6-12位"}'
       elif not (sex == '0' or sex == '1'):
           return '{"code":9340, "msg":"性别只能是0(male)或者1(female)"}'
       elif not (phone.isdigit() and len(phone) == 11):
           return '{"code":9350, "msg":"手机号格式不正确"}'
       elif conn_mysql('select phone from users where phone="%s";' % phone):
           return '{"code":9360, "msg":"手机号已被注册"}'
       else:
           password = md5_passwd(password)
           sql = 'insert into users(username,password,realname,sex,phone,utype,addtime,adduser) values ("%s","%s","%s","%s","%s","%s",now(),"%s");' % (
           username, password, realname, sex, phone, '1', username)
           conn_mysql(sql)
           return '{"code":9370,"msg":"恭喜,注册成功!"}'
   else:
       return '{"code":9300,"msg":"必填参数(username,password,realname,phone)都不能为空"}'

 

# 登录,可以get,也可以post
@server.route('/login', methods=['get', 'post'])
def login():
   username = request.values.get('username', '').strip()
   passwd = request.values.get('password', '').strip()
   if username and passwd:
       passwd = md5_passwd(passwd)
       sql = 'select id,username from users where username="%s" and password="%s"' % (username, passwd)
       sql_res = conn_mysql(sql)  # 获取查询结果
       print('sql_res:', sql_res)
       if sql_res:
           token_str = username + str(int(time.time()))  # 用户名+时间戳
           token = md5_passwd(token_str)  # md5后的token
           op_redis(username, token)  # 放到redis中
           # 下面三行,真实开发代码会这样写,这样可以在客户端浏览器设置cookie(如果是postman发请求,会在postman中设置cookie)
           response = make_response('{"code":9420, "msg":"恭喜%s,登录成功","token":"%s"}' % (username, token))
           response.set_cookie(username, token)  # 设置cookie
           return response
           # return '{"code":9420, "msg":"恭喜%s,登录成功","token":"%s"}'%(username,token)
       else:
           # return '{"code":9410,"msg":"用户名或密码不正确"}'
           # return json.dumps({"code":9410,"msg":"用户名或密码不正确"},ensure_ascii=False)
           return jsonify({"code": 9410,
                           "msg": "用户名或密码不正确"})  # jmeter请求,中文响应乱码(需要加上server.config['JSON_AS_ASCII'] = False);postman请求,中文正常显示

   else:
       return '{"code":9400,"msg":"用户名和密码不能为空"}'

 

# 添加用户,data和token都在body中,body是k-v
@server.route('/add_user1', methods=['post'])
def add_user1():
   token = request.values.get('token', '').strip()  # 必填
   adduser = request.values.get('adduser', '').strip()  # 必填
   username = request.values.get("username").strip()  # 必填
   realname = request.values.get('realname', '').strip()  # 必填
   sex = request.values.get('sex', '0').strip()  # 非必填
   phone = request.values.get('phone', '').strip()  # 必填

   if token and adduser and username and realname and phone:
       if sex != '1' and sex != '0':
           return '{"code":9340, "msg":"性别只能是0(male)或者1(female)"}'
       elif not (phone.isdigit() and len(phone) == 11):
           return '{"code":9350, "msg":"手机号格式不正确"}'
       else:
           redis_sign = op_redis(adduser)  # 从redis里面取到token
           if redis_sign:
               if redis_sign.decode() == token:
                   select_sql = 'select utype from users where adduser="%s"' % adduser
                   res = conn_mysql(select_sql)['utype']
                   # print(res,type(res))
                   if res == 1:
                       return '{"code":9540,"msg":"你是普通用户,无权限添加用户"}'
                   else:
                       if conn_mysql('select username from users where username="%s";' % username):
                           return '{"code":9310,"msg":"用户已经存在"}'
                       else:
                           select_sql = 'select phone from users where phone="%s"' % phone
                           if conn_mysql(select_sql):
                               return '{"code":9360, "msg":"手机号已被注册"}'
                           else:
                               password = md5_passwd('123456')  # 默认密码123456
                               sql = 'insert into users(username,password,realname,sex,phone,utype,addtime,adduser) values ("%s","%s","%s","%s","%s","%s",now(),"%s");' % (
                               username, password, realname, sex, phone, '1', adduser)
                               conn_mysql(sql)
                               return '{"code":9550,"msg":"添加用户成功。"}'
               else:
                   return '{"code":9560,"msg":"token错误"}'
           else:
               return '{"code":9510,"msg":"未登录"}'
   else:
       return '{"code":9500,"msg":"必填参数(token,username,realname,phone,adduser)不能为空"}'

 

# 添加用户,cookie中传token,data传json
# {"username":"test6","realname":"test6","sex":"1","phone":"13800000006","adduser":"qzcsbj1"}
@server.route('/add_user2', methods=['post'])
def add_stu2():
   token = request.cookies.get('token')  # 从cookie里面获取到token
   print('cookies:', request.cookies)
   print('传过来的headers是:', request.headers)
   print(request.json)
   adduser = request.json.get('adduser', '')  # 必填
   username = request.json.get('username', '')  # 必填
   realname = request.json.get('realname', '')  # 必填
   sex = request.json.get('sex', '0')  # 非必填
   phone = request.json.get('phone', '')  # 必填
   if token and adduser and username and realname and phone:
       if sex != '1' and sex != '0':
           return '{"code":9340, "msg":"性别只能是0(male)或者1(female)"}'
       elif not (phone.isdigit() and len(phone) == 11):
           return '{"code":9350, "msg":"手机号格式不正确"}'
       else:
           redis_sign = op_redis(adduser)
           if redis_sign:
               if redis_sign.decode() == token:
                   select_sql = 'select utype from users where adduser="%s"' % adduser
                   res = conn_mysql(select_sql)['utype']
                   # print(res,type(res))
                   if res == 1:
                       return '{"code":9540,"msg":"你是普通用户,无权限添加用户"}'
                   else:
                       if conn_mysql('select username from users where username="%s";' % username):
                           return '{"code":9310,"msg":"用户已经存在"}'
                       else:
                           select_sql = 'select phone from users where phone="%s"' % phone
                           if conn_mysql(select_sql):
                               return '{"code":9360, "msg":"手机号已被注册"}'
                           else:
                               password = md5_passwd('123456')
                               sql = 'insert into users(username,password,realname,sex,phone,utype,addtime,adduser) values ("%s","%s","%s","%s","%s","%s",now(),"%s");' % (
                               username, password, realname, sex, phone, '1', adduser)
                               conn_mysql(sql)
                               return '{"code":9550,"msg":"添加用户成功。"}'
               else:
                   return '{"code":9560,"msg":"token错误"}'
           else:
               return '{"code":9510,"msg":"未登录"}'
   else:
       return '{"code":9500,"msg":"必填参数(token,username,realname,phone,adduser)不能为空"}'

 

# 添加用户,cookie中传token,data传json,添加的用户信息在嵌套字典中
# {"adduser":"qzcsbj","data":{"username":"test9","realname":"test9","sex":"1","phone":"13800000009"}}
@server.route('/add_user3', methods=['post'])
def add_stu3():
   token = request.cookies.get('token')
   print('cookies:', request.cookies)
   print('传过来的headers是:', request.headers)
   print(request.json)
   data = request.json.get('data')
   print(data, type(data))
   adduser = request.json.get('adduser', '')  # 必填
   username = request.json.get('data').get('username', '')  # 必填
   realname = request.json.get('data').get('realname', '')  # 必填
   sex = request.json.get('data').get('sex', '0')  # 非必填
   phone = request.json.get('data').get('phone', '')  # 必填
   print(adduser, username, realname, sex, phone)
   if token and adduser and username and realname and phone:
       if sex != '1' and sex != '0':
           return '{"code":9340, "msg":"性别只能是0(male)或者1(female)"}'
       elif not (phone.isdigit() and len(phone) == 11):
           return '{"code":9350, "msg":"手机号格式不正确"}'
       else:
           redis_sign = op_redis(adduser)
           if redis_sign:
               if redis_sign.decode() == token:
                   select_sql = 'select utype from users where adduser="%s"' % adduser
                   res = conn_mysql(select_sql)['utype']
                   # print(res,type(res))
                   if res == 1:
                       return '{"code":9540,"msg":"你是普通用户,无权限添加用户"}'
                   else:
                       if conn_mysql('select username from users where username="%s";' % username):
                           return '{"code":9310,"msg":"用户已经存在"}'
                       else:
                           select_sql = 'select phone from users where phone="%s"' % phone
                           if conn_mysql(select_sql):
                               return '{"code":9360, "msg":"手机号已被注册"}'
                           else:
                               password = md5_passwd('123456')
                               sql = 'insert into users(username,password,realname,sex,phone,utype,addtime,adduser) values ("%s","%s","%s","%s","%s","%s",now(),"%s");' % (
                               username, password, realname, sex, phone, '1', adduser)
                               conn_mysql(sql)
                               return '{"code":9550,"msg":"添加用户成功。"}'
               else:
                   return '{"code":9560,"msg":"token错误"}'
           else:
               return '{"code":9510,"msg":"未登录"}'
   else:
       return '{"code":9500,"msg":"必填参数(token,username,realname,phone,adduser)不能为空"}'

 

# 添加用户,data和token都在body中,body是json
# {"token":"dcf6455d20a8cb01b573e0838cb79e7a","username":"test6","realname":"test6","sex":"1","phone":"13800000006","adduser":"qzcsbj"}
@server.route('/add_user4', methods=['post'])
def add_stu4():
   token = request.json.get('token')  # 从cookie里面获取到token
   adduser = request.json.get('adduser', '')  # 必填
   username = request.json.get('username', '')  # 必填
   realname = request.json.get('realname', '')  # 必填
   sex = request.json.get('sex', '0')  # 非必填
   phone = request.json.get('phone', '')  # 必填
   if token and adduser and username and realname and phone:
       if sex != '1' and sex != '0':
           return '{"code":9340, "msg":"性别只能是0(male)或者1(female)"}'
       elif not (phone.isdigit() and len(phone) == 11):
           return '{"code":9350, "msg":"手机号格式不正确"}'
       else:
           redis_sign = op_redis(adduser)
           if redis_sign:
               if redis_sign.decode() == token:
                   select_sql = 'select utype from users where adduser="%s"' % adduser
                   res = conn_mysql(select_sql)['utype']
                   # print(res,type(res))
                   if res == 1:
                       return '{"code":9540,"msg":"你是普通用户,无权限添加用户"}'
                   else:
                       if conn_mysql('select username from users where username="%s";' % username):
                           return '{"code":9310,"msg":"用户已经存在"}'
                       else:
                           select_sql = 'select phone from users where phone="%s"' % phone
                           if conn_mysql(select_sql):
                               return '{"code":9360, "msg":"手机号已被注册"}'
                           else:
                               password = md5_passwd('123456')
                               sql = 'insert into users(username,password,realname,sex,phone,utype,addtime,adduser) values ("%s","%s","%s","%s","%s","%s",now(),"%s");' % (
                               username, password, realname, sex, phone, '1', adduser)
                               conn_mysql(sql)
                               return '{"code":9550,"msg":"添加用户成功。"}'
               else:
                   return '{"code":9560,"msg":"token错误"}'
           else:
               return '{"code":9510,"msg":"未登录"}'
   else:
       return '{"code":9500,"msg":"必填参数(token,username,realname,phone,adduser)不能为空"}'

# 删除用户

tools.py

from conf.settings import *


# 加盐加密
def md5_passwd(str):
   str = str + SALT  # 加盐
   import hashlib
   md = hashlib.md5()  # 构造一个md5对象
   md.update(str.encode())
   res = md.hexdigest()
   return res


# 操作数据库
def conn_mysql(sql):
   import pymysql
   try:
       conn = pymysql.connect(host=MYSQL_HOST, user=USER, password=PASSWORD, db=DB, charset='utf8', port=MYSQL_PORT)
   except Exception as e:
       print('mysql连接出错,错误信息为%s' % e)
       res = {"code": 9901, "msg": 'mysql连接出错,错误信息为%s' % e}
   else:
       cur = conn.cursor(cursor=pymysql.cursors.DictCursor)
   try:
       cur.execute(sql)
   except Exception as e:
       msg = "sql执行出错,请检查sql,错误信息为:%s" % e
       res = {"code": 9902, "msg": msg}
   else:
       res = cur.fetchone()
       conn.commit()
   finally:
       cur.close()
       conn.close()
       print("res:", res)
       return res


# 操作redis
def op_redis(k, v=None):
   import redis
   r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD)
   if v:  # v是真,表明是set,否则是get
       r.setex(k, EX_TIME, v)  # 时间是秒,等同于set name jack ex 10
   else:
       return r.get(k)
posted @ 2020-08-01 10:00  tester01home  阅读(9)  评论(1编辑  收藏  举报