目录
一、构建测试初始测试数据
二、构建测试阶段
三、编写测试用例
经过前面几篇文章脚本的搭建,基本的方法已封装完毕。
本节开始编写自动化测试的用例。
在Common下面新建TestResource.py脚本。
本项目是根据手机号来创建账号,故里面封装了如何获取初始的测试phone。
可以根据的项目情况,将固定的一些测试账号数据,封装在这个文件下。
# coding=utf-8
import os,sys;sys.path.append(os.path.abspath(os.path.join(os.path.split(os.path.realpath(__file__))[0], "..")))
from Common.DataBaseCommon import MySQL
from Common.Log import MyLog
from Common.BaseInterface import BaseInterface
from Conf.EnvConfig import EnvConfig
import time
class CreateTestAccount:
def __init__(self, channel=None, country=None):
"""
创建产品渠道
:param channel: 产品
:param country: 国家
"""
self.channel = channel
self.country = country
self.log = MyLog()
self.mysql = MySQL(self.channel, self.country, 'YY')
self.cc = EnvConfig().get_interface_conf(self.channel, country=self.country)['cc']
def get_acct(self, phone_same_mobile=False):
"""
获取测试账号
:param phone_same_mobile: True or False;判断生成的账号的登录手机号号是否一样
:return result_dict: dict--phone,mobile,birth_date,last_name,first_name,cc
"""
# 定义开始的时间
start_time = time.time()
next_num = 0
self.log.info('查询当前系统中存在自动化测试账号中最大的PHONE')
select_sql = "select PHONE from YY.YY_cust where firstname='automation' and phone LIKE '186%' order by bvn desc limit 1;"
data = self.mysql.sql_com([select_sql])
self.log.info('最大的测试账号为:{}'.format(data))
# 定义初始PHONE
init_phone = "18600000000"
if data[1] is None:
phone = init_phone
else:
phone = str(int(data[1][0]) + 1 + next_num)
result_dict = {
'phone': phone,
'birth_date': '2000-12-12',
'last_name': 'test',
'first_name': 'automation',
'cc': self.cc
}
self.log.info('生成的测试账号信息为:{}'.format(result_dict))
# 定义结束时间
stop_time = time.time()
total_time = str(round((stop_time - start_time), 3))
self.log.info('---------生成测试账号{}总耗时 : {} S'.format(phone, total_time))
return result_dict
测试场景可以根据业务流程进行划分。
比如电商业务流:
登录--选购商品--下单--付款--收货
那么我们就可以将每个节点都进行一个封装,方便测试用例进行测试数据的构建。
下面以构建注册登录为阶段,写下脚本。
在Interface下新建stage.py文件。
这里我们写一个登录注册的stage流程放在里面。
# -*- coding: UTF-8 -*-
import random
import time
import uuid
from Common.Log import MyLog
from Common.public_method import PublicMethod
from Common.TestResource import CreateTestAccount
from Project.Yangyang.Interface.login import YyLogin
class Stage:
def __init__(self, channel, country):
self.log = MyLog()
self.channel = channel
self.country = country
@property
def description(self):
description = [
{'登录': {'stage': 'login'}},
{'选购商品': {'stage': 'select_product'}},
{'付款': {'stage': 'payment'}},
{'收货': {'stage': 'get_product'}},
]
return description
def _stage_param(self):
stage_param = {}
for one in self.description:
for value in one.values():
for param in value.keys():
if stage_param.get(param) is None:
stage_param[param] = [value[param]]
else:
if value[param] not in stage_param[param]:
stage_param[param].append(value[param])
return stage_param
def login_main(self, login_phone, st=None, business_no=None):
"""
统一登录方法:
:param login_phone:
:return: result_dict 包含token,salt,bvn,uid,transactionPassword,
"""
login_body = {'data': {'st': st, 'phone': login_phone, 'googleAcct': login_phone, 'twitterAcct': login_phone, 'facebookAcct': login_phone}}
result_data = YyLogin(self.channel, self.country).YY_login(login_body)
if result_data['body']['status']['code'] == 0:
self.log.info('-----------登录成功-----------')
data = result_data['body']['data']
result_dict = {
'token': data['token'],
'salt': data['salt'],
'uid': data['uid'],
}
self.log.info(f'返回数据:{result_dict}')
return result_dict
else:
msg = '------------用户登录失败!!!!---------------'
self.log.error(msg)
raise RuntimeError(msg)
def to_stage(self, phone, bvn, stage=None):
if stage is not None and stage not in self._stage_param()['stage']:
raise ValueError(f'请求参数stage[{stage}]未定义!!')
result_dict = self.login_main(phone)
if stage == 'login':
return result_dict
# 传默认值时返回
return result_dict
在项目的TestCase文件夹下,新建test_login.py的测试用例脚本。
分为两大块:
TestYyLoginParameters: 用于存放参数的测试用例
TestYyLoginScenario: 用于存放流程的测试用例。
import allure
import pytest
from pytest_assume.plugin import assume
from Project.Yangyang.Interface.login import YyLogin
from Project.Yangyang.Interface.stage import Stage
from Common.TestResource import CreateTestAccount
channel1 = 'YY'
country1 = 'China'
class TestYyLoginParameters: #参数测试用例集
@allure.feature('test_Yy_login') #该用例集名称
@allure.story('登出接口参数必填测试') #用例集说明
@pytest.mark.parameters_test #用例标签
@pytest.mark.parametrize('param, expect_value', [('login_out_success', 0),
('token_err', 1)]) #用例入参参数及预期结果,param字段是入参条件,expect_value为预期code枚举值的编号
def test_Yy_login_01(self, param, expect_value):
"""
Description:登出接口参数必填测试
Onwer: Yangyang
"""
with allure.step('测试数据构造'): #构建测试数据
create_account = CreateTestAccount(channel1, country1).get_acct()
login_phone = create_account.get('phone')
allure.attach('测试数据', '登录手机号:{}'.format(login_phone)) #测试用例中添加了一段文字
with allure.step('构造阶段数据'): #生成测试阶段数据
response = Stage(channel1, country1).to_stage(login_phone, stage='login') #确定测试阶段
token = response['token']
uid = response['uid']
with allure.step('接口请求'):
if param == 'login_out_success': #枚举param值,变换测试用例
uid = 'uid'
if param == 'token_err':
login_token = 'token'
headers = {'token': token, 'uid': uid}
response = YyLogin(channel1, country1).YY_login(headers=headers)
with allure.step('数据检查'):
expect_code_list = [0, 999] #枚举出逾期的code编号放入list中
with assume:
assert response['body']['status']['code'] == expect_code_list[expect_value], '响应错误!' #断言判断
class TestYyLoginScenario: #场景测试用例集
@allure.feature('test_Yy_login') #该用例集名称
@allure.story('登录接口-用户登录成功') #用例集说明
@pytest.mark.scenario_test #用例标签
@pytest.mark.CheckList #用例标签
def test_Yy_login_02(self):
"""
Description:登录接口-登录成功
Onwer: Yangyang
"""
with allure.step('测试数据构造'):
create_account = CreateTestAccount(channel1, country1).get_acct()
login_phone = create_account.get('phone')
login_bvn = create_account.get('bvn')
allure.attach('测试数据', '登录手机号:{}'.format(login_phone))
allure.attach('测试数据', '用户bvn号:{}'.format(login_bvn))
with allure.step('接口请求'):
req_body = {'data': {'phone': login_phone}}
response = YyLogin(channel1, country1).YY_login(req_body=req_body)
with allure.step('数据检查'):
with assume:
assert response['body']['status']['code'] == 0, '响应错误!'
至此,一个登录接口测试用例就已完成。
如果写的不错,欢迎来个三连行~~~