1. 前言

大家好,我是小码哥,拥有超过10年以上的银行测试经验,目前在一家互联网创业公司担任测试经理。在我们那个年代,基本上都是不会写代码的做测试工作,而且基本都是纯手工;最近几年,测试开发开始流行,互联网行业越来越重视测试人员的综合能力,使得我们这些老测试也必须转型,才能跟上时代的步伐,因此我也报名了三丰全栈测开训练营,之前我也在一些网络培训网站上学习一些新的知识点,但我感觉狂师的课程无论是范围、广度、深度比大多数培训机构强很多,也正是工作当中经常能用到的内容,非常值得大家学习。那么,今天我将结合训练营课程的讲解,分享一些关于接口自动化测试学习实践总结,并且这些我已经应用到了实际工作上,希望对大家也有所帮助。(文末作者学习笔记分享)

2. 工作需求背景

  • 利用Pytest+Request+Allure+Jenkins实现接口自动化;
  • 实现一套脚本多套环境执行;
  • 利用参数化数据驱动模式,实现接口与测试数据分离
  • 使用logger定制实现自动化测试日志记录

3. 接口自动化项目代码编写(先在window实现)

3.1 项目准备

先在window安装响应的环境依赖
- 安装python3.7(要保证pip能用,一般安装python3.7会自动安装pip)
- 安装pytest框架---- pip install pytest
- 安装request库---- pip install request
- 安装openpyxl库(测试数据保存在excel中,需要依赖读取excel的库)---- pip install openpyxl
- 安装pycharm(编写python脚本工具)

注意:可能还需要一些依赖的东西,项目步骤里会依据需要进行安装

3.2 设计基于pytest的测试框架结构

在pycharm中开发构建项目结构

- common:存放公共方法
- config:存放环境配置信息
- lib:存放第三方库
- main:框架主入口
- report:存放allure测试报告
- test_case:存放测试用例
- test_data:存放测试数据

3.3 实现接口公共请求发送能力

从这一步开始正式编写代码

封装http请求的公共能力(封装request库,变成自己的公共处理能力),放到common目录下。

# encoding: utf-8
# 代码来源:全栈测开训练营import requests
import urllib3
# from urllib3.exceptions import InsecureRequestWarningurllib3.disable_warnings()
# 加这句不会报错(requests证书警告)
# requests.packages.urllib3.disable_warnings(InsecureRequestWarning)class HTTPRequests(object):def __init__(self, url):self.url = urlself.req = requests.session()# 依据自己公司的请求头默认值配置self.head = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; rv:11.0) like Gecko','Accept': 'image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, ''application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, ''application/msword, */*','Accept-Language': 'zh-CN'}# 封装自己的get请求,获取资源def get(self, uri='', params='', data='', headers=None, cookies=None, verify=False):if headers is None:headers = self.head# print("请求头是:{}".format(headers))url = self.url + uriresponse = self.req.get(url, params=params, data=data, headers=headers, cookies=cookies, verify=verify)return response# 封装自己的post请求,获取资源def post(self, uri='', params='', data='', headers=None, cookies=None, verify=False):if headers is None:headers = self.headurl = self.url + uriresponse = self.req.post(url, params=params, data=data, headers=headers, cookies=cookies, verify=verify)return response# 封装自己的put请求,获取资源def put(self, uri='', params='', data='', headers=None, cookies=None, verify=False):if headers is None:headers = self.headurl = self.url + uriresponse = self.req.put(url, params=params, data=data, headers=headers, cookies=cookies, verify=verify)return response# 封装自己的delete请求,获取资源def delete(self, uri='', params='', data='', headers=None, cookies=None, verify=False):if headers is None:headers = self.headurl = self.url + uriresponse = self.req.delete(url, params=params, data=data, headers=headers, cookies=cookies, verify=verify)return response

3.4 抽离测试环境配置信息

这个步骤的目的有三个 - 为了配置三个不同环境(测试、开发、生产)的URL,每个环境接口测试的URL是不一样的,设置这样一个枚举类,方便后面的程序根据不同的环境,获取不同环境的URL,里面的URL依据自己公司的地址修改,放到config目录
- 获取token需要登录,这里可以设置一个全局的账号密码,这个账号密码获取的token可以给整个接口自动化使用
- 配置获取token的uri,这个uri三个环境的是一致的,登录的接口依据环境只是URL不同,URI还是一致的。

# encoding: utf-8
# 代码来源:全栈测开训练营import enumclass URLConf(enum.Enum):"""环境配置信息"""url_mapping = {'dev': 'https://www.dev.com','test': 'https://www.test.com','prod': 'https://www.prod.com'}# token固定的用户名密码,固定用"/"分割用户名和密码email_user = {'dev': 'dev@qq.com','test': 'zidonghua@qq.com/96e79218965eb72c92a549dd5a330112','prod': 'prod@qq.com'}login_uri = r'/api/auth/login/account/v1'

3.5 创建conftest.py放置一些公共的fixture

1、pytest_addoption,设置了只允许输入dev/test/prod三个参数,以区分测试、开发、生产三个环境
2、get_env的fixture,它的作用是你在命令行执行接口自动化时,可以输入--env test将对应的环境信息传入进去
3、http的fixture,这里依据--env test传入的环境信息,去枚举类里获取对应环境的URL,然后返回一个http的session,供测试案例使用
4、get_token_head,依据--env test传入的环境信息,调用获取token方法,并将token放置到请求头head里返回(token一般放在请求头里,这里依据自己公司的请求,返回对应的token信息就可以了)

# encoding: utf-8
# 代码来源:全栈测开训练营import logging
import osimport pytestfrom common.http_request import HTTPRequests
from config.url_config import URLConfdatadir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "test_data")
logger = logging.getLogger('conftest日志')def pytest_addoption(parser):# choices 只允许输入的值的范围parser.addoption("--env", action="store", default='test', choices=['dev', 'test', 'prod'], help="set env")# 获取命令行参数的fixture
@pytest.fixture(scope='session')
def get_env(request):# print("fixutre..................")return request.config.getoption('--env')# 声明一个返回http请求对象的fixture,所有用例在一个session中
# @pytest.fixture(scope='module', autouse=True)
@pytest.fixture(autouse=True)
def http(request):env = request.getfixturevalue("get_env")url_mapping = URLConf.url_mapping.valueurl = url_mapping.get(f'{env}')http = HTTPRequests(url)return http@pytest.fixture(scope='session')
def get_token_head(request):env = request.getfixturevalue("get_env")url_mapping = URLConf.url_mapping.valueurl = url_mapping.get(f'{env}')http = HTTPRequests(url)user = URLConf.email_user.valueuser_list = user.get(f'{env}').split("/")username = user_list[0]password = user_list[1]param = {'clientType': 2,'language': 'en','loginId': username,'loginPassword': password}logger.info("请求的url=={}".format(url))response = http.post(uri=r'/api/auth/login/account/v1', data=param)logger.info("获取的返回值是:".format(response.text))token = Noneif response.status_code == 200:token = response.json().get('result')['token']else:token = 'get token fail'head = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; rv:11.0) like Gecko','Accept': 'image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, ''application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, ''application/msword, */*','Accept-Language': 'zh-CN','Authorization': token}yield head

3.6 将测试数据放到excel中

我们的测试数据是放在excel中,注意,这里有prod\test\dev三个目录,对应三个环境的测试数据,我这里只创建了test测试环境的测试数据。这里的测试数据需要包含两部分: - 你调用接口传入的所有参数; - 你要断言的所有信息,因为你传的参数不同,返回的内容就不同,你断言的内容也就不相同了。

那么这时候,就需要一个读取excel的公共方法了,放到common里

# 创建解析excel的方法
import loggingfrom openpyxl import load_workbooklogger = logging.getLogger("读取excel")class ParseExcel(object):def __init__(self, excelPath, sheetName):self.wb = load_workbook(excelPath)self.sheet = self.wb[sheetName]self.maxRowNum = self.sheet.max_row# 依据传入的数字,决定获取几列excel数据def getDataFromSheet(self, num):dataList = []for line in self.sheet.rows:tmplist = []for i in range(num):tmplist.append(line[i].value)dataList.append(tmplist)print("dadddddd:{}".format(dataList))return dataList[2:]

这里,还需要再test_data中,创建一个文件,为了获取前面test_data依据环境创建的dev/test或prod文件目录

注意:这里只有一个test或prod或dev的文字,是为了拼接....test_data/test目录获取对应环境的excel测试数据而使用的,每次环境切换前,需要更改这个文件,可能这并不是一个好方法,如果大家有找到更好的方法,也可以分享一下

3.7 开始编写自动化测试案例了

测试案例中有几个点,需要解释一下:
1、authBaseDir,这个就是根据test_data/test拼接出来的获取测试数据的目录
2、allure.feature,在测试报告中,会展现这个接口名称,这个名称最好与你公司的开发写的接口模块保持一致,方便后续查找问题
3、allure.story 这里也要与开发写的具体某个接口的名称保持一致。
4、pytest.mark.parametrize,这里就是运用的DDT数据驱动的模式,从excel中一条一条的获取数据,然后执行同一条接口测试用例,excel中比如有3条数据,那么就表示这个案例依据每一条数据的参数,总共执行了三次

# encoding: utf-8"""
create by ArthurAccount Api模块
"""
import logging
import osimport allure
import pytestfrom common.get_data_url import get_data_url
from common.parse_excel import ParseExceldatadir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "test_data")
data_url = get_data_url()
# 获取到test_data\test的目录,如果是prod环境,那么就是获取test_data\prod目录
authBaseDir = os.path.join(datadir, data_url)logger = logging.getLogger("Account Api模块日志")@allure.feature("AccountApi模块")
@pytest.mark.webtest
class TestAccountApi(object):"""Query Related Achievements: /api/auth/account/achievement/related/query/v1"""Query_Related_Achievements_dir = os.path.join(authBaseDir, 'Query_Related_Achievements.xlsx')logger.info("Query_Related_Achievements测试数据的路径是:{}".format(Query_Related_Achievements_dir))parse = ParseExcel(Query_Related_Achievements_dir, 'Sheet1')Query_Related_Achievements_params = parse.getDataFromSheet(5)@allure.story("Query Related Achievements(查询用户成就信息)")@pytest.mark.parametrize("clientType,language,retCode,istoken,result", Query_Related_Achievements_params)def test_001_Query_Related_Achievements(self, get_token_head, http, clientType, language, retCode, istoken, result):uri = '/api/auth/account/achievement/related/query/v1'params = {"clientType": clientType, "language": language}if istoken == 'yes':header = get_token_headresponse = http.get(uri=uri, params=params, headers=header)json_req = response.json()logger.info("Query_Related_Achievements有token的返回值是:{}".format(json_req))assert json_req.get('retCode') == 200assert json_req.get('result')[0]['smallImg'] == resultelse:response = http.get(uri=uri, params=params)json_req = response.json()logger.info("Query_Related_Achievements没有token的返回值是:{}".format(json_req))assert json_req.get('retCode') == 401assert json_req.get('message') == result

3.8 集成allure

写到这里,是不是发现前面的allure.feature是不是用不了呢?这是因为我们还没有集成allure进去。
1、下载allure,放到lib目录下,使你的工程具备allure的能力。

2、pip install allure-pytest 安装pytest对应的allure包

3.9 这时候就可以创建一些执行策略了

1、先在main中创建一个pytest.ini文件,设置一些执行参数

2、在main中创建执行策略
- 先在run_pytest方法中,执行案例并生成allure的json格式的报告文件,这里可以带--env prod将对应环境信息传入,这里没有传是因为默认是test环境,不传入的话就是执行的test环境测试数据
- general_report方法时将生成的json格式的报告,最终生成html文件放置到report下面的目录中
- 创建一个线程,先执行run_pytest,再执行general_report,避免json文件没有生成,这样生成html文件的报告数据可能不全,甚至没有。

# encoding: utf-8
# 代码来源:全栈测开训练营"""
所有案例执行并生成allure测试报告的执行策略
"""import os
import sys
import threading
import pytestsys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../')
from common.report import Reportproject_root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
report_dir = os.path.join(project_root, 'report')
# 存放测试结果的目录,会生成一推json文件
result_dir = os.path.join(report_dir, 'allure_result')
allure_report = os.path.join(report_dir, 'allure_report')report = Report()#  定义搜索条件,搜索所有以test开头的用例
tag = 'test'def run_pytest():# --clean-alluredir# pytest.main(['-vv', '-s', '-m', 'webtest', f'--alluredir={result_dir}', '--clean-alluredir'])# 执行前清除allure_result数据,避免生成报告时,会把上次执行的数据带进去pytest.main(['-vv', '-s', '-k', f'{tag}', f'--alluredir={result_dir}', '--clean-alluredir'])def general_report():# 调用cmd方法 report.allure,根据windows或linux环境判断# 然后执行生成报告的方法generate# --clean 覆盖路径,将上次的结果覆盖掉cmd = "{} generate {} -o {} --clean".format(report.allure, result_dir, allure_report)# 执行命令行命令,并通过read()方法将命令的结果返回print(os.popen(cmd).read())if __name__ == '__main__':# 创建两个线程,分别执行两个方法run = threading.Thread(target=run_pytest)gen = threading.Thread(target=general_report)run.start()# 先执行第一个线程,这个线程执行完才会执行下面的线程和主线程run.join()gen.start()gen.join()

3.10 自动化执行生成结果

在windows下,右键执行main下面的run_test_allure_html.py(就是上一个步骤的python文件),然后打开report/allure_report/index.html看看报告是否生成成功

4. jenkins环境搭建(linux环境)

好了,到这一步,在windows下我们已经执行成功,现在我们要集成到jenkins环境去,并搭建在linux环境下。
1、将代码上传到公司的git(没有git的自己搭建一套吧)
2、找一台linux机器(自己去自己公司找资源)
3、在linux下安装jenkins(我是防止到tomcat中)、python3、pytest、allure、openpyxl(这些步骤在网上可以搜索到,这里不赘述了)
4、启动linux下的tomcat,然后在window下打开jenkins的服务地址

5、创建一个自由风格的job

6、Job需要填写的具体内容有:
- A、选择丢弃旧的构建(保留的构建天数依据自己的情况选择)

- B、“限制项目的运行节点”依据自己的情况选择(我这里给我的jenkins主服务器取了一个叫linux的标签,我的机器也是linux机器)

- C、git--将git上的代码拉下来

- D、“执行shell”,这里把代码从git拉到了jenkins的执行目录里,一般在linux下的root/.jenkins里,在执行shell时,最好chmod修改下整个工程的目录权限,因为有可能因权限问题执行不了

- E、构建后的操作:这里需要再jenkins里安装allure插件才能看到allure Report,第一个Path,这里写的是allure生成的json文件的目录,所以是report/allure_result,第二个Report path指的是生成的index.html文件的目录,所以是report/allure_report

4.2 立即构建并查看报告

上面的job建成后,就可以点击立即构建,执行了。执行完后,点击allure Report查看最终的报告。

5. 小结

今天的分享其实也只是全栈测开训练营代码级测试框架这个技能版块中,很小的一部分知识点,里面涉及到的知识,在工作中都非常实用,非常值得学习。

此次分享就到这里了,算是一个阶段学习总结吧。。虽然我是一只步入中年的测试老兵,但仍阻挡不了我持续学习前进的步伐,希望和那些有着同样学习热情的同学共勉。

月薪40K+银行测试经理,自动化测试实践经验分享相关推荐

  1. 对话中国人寿:DevOps实践经验分享

    对话中国人寿:DevOps实践经验分享 视频文字实录 霍艳明 中国人寿财产保险股份有限公司测试负责人 Q:请问贵公司主要进行了哪些DevOps的有效实践,采用了哪些工具? A:现在我们用的是Jira这 ...

  2. IT项目管理实践经验分享

    其实我本来是想找PMP考友的,但是无人应征,又看到版主的号召,所以就贴个实践经验分享贴,也找点志同道合者交流交流实践经验吧. 我的msn ccjjgg79310@msn.com Email ccjjg ...

  3. 大促场景系统稳定性保障实践经验分享

    简介:11月11日0点刚过26秒,天猫双11的订单创建峰值就达到58.3万笔/秒,阿里云又一次扛住全球最大规模流量洪峰!58.3万笔/秒,这一数字是2009年第一次天猫双11的1457倍. 每到双11 ...

  4. 云计算架构师分享:容器云在金融企业的落地方案 | 周末送资料(原题:某保险公司容器云PaaS平台建设实践经验分享)

    [摘要]随着技术和社区的成熟,容器.Kubernetes.微服务等新事物不再只是概念,已在很多企业落地并发挥了生产力,对容器和PaaS的需求也从试探性转向规模化推广和纵深探索,建设企业级容器PaaS平 ...

  5. 移动APP测试用例设计实践经验分享

    我请大家先思考如下2个问题: 第一,我们为什么要做好测试用例设计? 第二,好的测试用例设计有什么共性? 深入思考这两个问题的答案是一件很有意义的事情,作为移动互联网时代的产品质量守卫军,我们必须提升自 ...

  6. AutoML前沿技术与实践经验分享 | 免费公开课

    传统机器学习的解决范式可表示为: ML Solution = ML expertise + Computation + Data 新机器学习范式可表示为: New ML Solution = 100x ...

  7. AutoML前沿技术与实践经验分享 | 免费报名

    传统机器学习的解决范式可表示为: ML Solution = ML expertise + Computation + Data 新机器学习范式可表示为: New ML Solution = 100x ...

  8. 领域驱动设计(DDD)的实践经验分享之持久化透明

    领域驱动设计(DDD)的实践经验分享之持久化透明 原文:领域驱动设计(DDD)的实践经验分享之持久化透明 前一篇文章中,我谈到了领域驱动设计中,关于ORM工具该如何使用的问题.谈了很多我心里的想法,大 ...

  9. 手段-目的理论定性研究实践经验分享

    手段-目的理论定性研究实践经验分享 -公司型项目需要尽可能高效率的定性研究,选取方法前必须对时间人力成本做出准确评估. -需要有分析方案,事先统一标准:初期需要多沟通,确保标准达成一致. -多人对同一 ...

  10. 银行测试核心项目之测试阶段分享

    最近有小伙伴说「想了解核心系统建设中,冒烟.SIT.UAT.回归测试的重点,如何设计测试案例,或相关的资料推荐等」. 这个话题很笼统,测试这一块儿除了业务测试,还有性能测试.安全测试等:以及不同的角色 ...

最新文章

  1. 属性处理器Spring攻略学习笔记(2.12)------外部化Bean配置
  2. 数论 - 简单数位推理 --- NYIST 514
  3. SpringBoot+MyBatis+Shiro 搭建杂谈
  4. 「递归」第7集 | 腾讯开源联盟出征!
  5. 编写下载服务器。 第一部分:始终流式传输,永远不要完全保留在内存中
  6. ASP.NET Core中使用GraphQL - 第七章 Mutation
  7. Mybatis解析mapper
  8. 【华为云技术分享】云小课 | OBS提供多方面数据安全保障,让存储放心、贴心、省心
  9. 集成学习 Bagging, Boosting, Stacking
  10. R及RStudio下载安装教程(超详细)
  11. hosts文件为空,仍然显示ERR_CONNECTION_RESET的解决方法(hosts.ics)
  12. sata port multiplier
  13. HHDBCS及HHDESK的资源加密功能
  14. linux磁盘分区、挂盘
  15. transferTo和transferFrom
  16. 老毛桃制作U盘-linux
  17. grasemonkey ajax页面,Greasemonkey 中使用 GM_xmlhttpRequest 如何在 https 页面中加载 http 资源?...
  18. Sql server mssqlserver 服务无法启动
  19. 无论用手工处理还是用计算机进行处理,市场调研的数据处理.doc
  20. Nginx配置文件详解说明

热门文章

  1. 手把手教你用FineBI做数据可视化
  2. Docker配置远程访问
  3. linux2T硬盘分区命令,linux系统使用parted命令对大于2T的硬盘进行分区教程
  4. PYTHON:已知一点经纬度、方位角和距离,求另一点的经纬度
  5. 国防科技大学计算机作品赛,信息学院教师在全国计算机类课程实验教学案例设计竞赛中获一等奖...
  6. 激光跟踪传感器的工作原理
  7. C/C++, STM32,KEIL warning: #175-D: subscript out of range
  8. F.conv2d pytorch卷积计算
  9. 新一代超低功耗STM32U5,到底有啥亮点?
  10. 《牧羊少年奇幻之旅》保罗·科埃略