Python+requests+Excel+unittest+HTMLTestRunner
开始之前:
先来梳理一下我们手动进行接口测试的流程是什么样的?
理解接口文档 —> 编写测试用例 —> 准备测试环境 —> 选择测试工具(Postman)—> 执行测试 —> 检查接口返回数据 —> 最后生成测试报告 —> 将测试报告以邮件的方式发送给相关大佬
那么,何为自动化测试呢?
自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。
现在,我们来看看具体是怎么实现的吧!
(以下是我自己实现的方式,大家可以参考下,有许多不完善的地方,也遇到了许多的问题,希望大神们多多指教!)
一、环境搭建:
1、安装Python3(具体安装方法可以百度)
2、安装需要用到的相关库requests、openpyxl
pip3 install requests(HTTP请求库)
pip3 install openpyxl(操作Excel表格库)
pip3 install configparser(操作.ini配置文件库)
后续有一个安装所需库的package.py文件,执行安装即可
3、安装一个IDE,推荐使用PyCharm(具体安装方法可以百度)
二、结构的划分
- common:存放一些公共的方法
- config:
- config.ini 配置文件
- readConfig.py 读取配置文件信息
- logs:存放日志,不创建也可以,在执行脚本过程中会自动生成的
- report:存放执行脚本过程中生成的测试报告
- shellFile:存放在测试执行的过程需要调用的shell脚本
- source:存放在测试执行的过程需要用的源文件。比如图片、视频等
- testCase:存放测试用例代码
- testDataFile:存放测试数据文件(包括Excel、JSON文件)
- case_list.txt 控制该条测试用例的执行或不执行
- installEnv.sh 如果要在Liux系统下执行脚本,只需要运行一下该shell脚本即可
- package.py 安装运行该脚本所需要用到的python相关库
- reset_env.py 重置测试环境(每次启动自动化测试之前,进行测试环境的清理,保持环境的干净)
- runcase.py 启动自动化测试系统入口
二、配置文件目录
1、配置文件config.ini
就是用来存放基本不变的东西,比如测试环境、发送邮件的信息,所有一成不变东西都可以放在这个文件下
[HTTP]
protocol = http
# 开发环境
# ip = 192.168.0.128
# port = 3002
# 测试环境
ip = 192.168.0.118
port = 3002
# 生成环境
basics = www.xxx.com
[EMAIL]
is_send = no
title = xxx Test Report
mail_host = smtp.163.com
mail_user = xxxxxx
mail_pass = xxxxxx
sender = xxxxxx@163.com
receive_user = xxxxxx1@qq.com/xxxxxx2@qq.com
[EXCEL]
module = A
api_name = B
case_id = C
case_name = D
url = E
premise = F
header = G
method = H
data = I
param = J
check = K
expected = L
return = M
rely = N
[EXCEL] 是Excel测试用例表格每一列对应的字母常量,用于后面的读取Excel表格数据使用,比如:用例标题case_name = D
2、读取配置文件readConfig.py
该文件是用来读取config.ini文件的,用到configparser第三方库
#!/usr/bin/python3
# coding=utf-8
import configparser
import os
proDir = os.path.split(os.path.realpath(__file__))[0]
configPath = os.path.join(proDir, "config.ini")
class ReadConfig:
def __init__(self):
self.cf = configparser.ConfigParser()
self.cf.read(configPath)
def get_base_url(self):
protocol = self.cf.get("HTTP", "protocol")
# 测试环境
ip = self.cf.get("HTTP", "ip")
port = self.cf.get("HTTP", "port")
base_url = protocol + '://' + ip + ':' + port
# 生成环境
# basics = self.cf.get("HTTP", "basics")
# base_url = protocol + '://' + basics
return base_url
def get_email(self, mail_key):
email_value = self.cf.get("EMAIL", mail_key)
return email_value
三、测试数据设计
1、Excel测试用例,所有的测试用例都写在Excel表格里,然后读取Excel,进行自动测试
请求头部和请求数据都是写的关键字,关键字对应的数据放在JSON文件
三、公共方法common目录
这里就介绍一下几个主要的方法
1、myLog.py
——主要用到logging模块可以替代print函数的功能,并能将标准输出输入到日志文件保存起来(logging模块是Python标准库,不需要安装)
——我主要对其进行了一下封装定义成自己想要的输出log的格式、控制输出到控制台的等级、需要打印的日志等级,直接看源码吧!
#!/usr/bin/python3
# coding=utf-8
import logging
import os
import time
from datetime import datetime
logger = logging.getLogger(__name__)
path_dir = str(os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)))
logpath = path_dir + '/logs'
def create_file(file_name):
path = file_name[:-7]
if not os.path.isdir(path):
os.makedirs(path)
if not os.path.isfile(file_name):
fb = open(file_name, mode='w', encoding='utf-8')
fb.close()
else:
# print("不需要创建")
pass
def set_handler(level):
if level == 'error':
logger.addHandler(MyLog.err_handler)
logger.addHandler(MyLog.handler)
logger.addHandler(MyLog.console)
def remove_handler(level):
if level == 'error':
logger.removeHandler(MyLog.err_handler)
logger.removeHandler(MyLog.handler)
logger.removeHandler(MyLog.console)
def set_now_time():
now_time = time.strftime(MyLog.time_format, time.localtime(time.time()))
return now_time
class MyLog:
# 基本设置
path = os.path.join(logpath, str(datetime.now().strftime("%Y%m%d")))
now = time.strftime("%H-%M-%S", time.localtime(time.time())) # 获取当前时间
log_file = path + "/log.log"
err_file = path + "/err.log"
create_file(log_file)
create_file(err_file)
time_format = "%Y-%m-%d %H:%M:%S"
# 设置需要输出到控制台的等级
console = logging.StreamHandler()
# console.setLevel(logging.WARNING)
console.setLevel(logging.INFO)
# 设置需要打印的日志等级
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(log_file, encoding='utf-8')
err_handler = logging.FileHandler(err_file, encoding='utf-8')
@staticmethod
def debug(message, name='', line=''):
set_handler('debug')
if name != '' and line != '':
logger.debug(
"[" + set_now_time() + "]" + " - " + name + ', ' + 'Line %s' % line + "] " + " - " + "DEBUG:" + " " + message)
remove_handler('debug')
else:
logger.debug(
"[" + set_now_time() + "]" + " - " + "DEBUG:" + " " + message)
remove_handler('debug')
@staticmethod
def info(message, name='', line=''):
set_handler('info')
if name != '' and line != '':
logger.info(
"[" + set_now_time() + "]" + " - " + name + ', ' + 'Line %s' % line + "] " + " - " + "INFO:" + " " + message)
remove_handler('info')
else:
logger.info(
"[" + set_now_time() + "]" + " - " + "INFO:" + " " + message)
remove_handler('info')
@staticmethod
def warning(message, name='', line=''):
set_handler('warning')
if name != '' and line != '':
logger.warning(