1.新建一个工程testProject
2.在工程的根目录下新建一个conftest.py(测试用例的一些fixture配置)和pytest.ini(改变pytest的运行方式)
3.在工程下创建以下package包和文件夹
# -*- coding:utf-8 -*-
#默认日志格式
DEFAULT_LOG_FMT='%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s: %(message)s'
#默认时间格式
DEFUALT_LOG_DATEFMT='%Y-%m-%d %H:%M:%S'
#输出日志路径
import os
LOG_OUT_PATH=os.path.abspath('..')+'/logs/'
import sys
import logging
from time import strftime
class Logger(object):
def __init__(self):
self._logger=logging.getLogger()
self.DEFAULT_LOG_FILENAME='{0}{1}.log'.format(LOG_OUT_PATH,strftime("%Y-%m-%d"))
self.formatter=logging.Formatter(fmt=DEFAULT_LOG_FMT,datefmt=DEFUALT_LOG_DATEFMT)
self._logger.addHandler(self._get_file_handler(self.DEFAULT_LOG_FILENAME))
self._logger.addHandler(self._get_console_handler())
self._logger.setLevel(logging.INFO) #默认等级
def _get_file_handler(self,filename):
filehandler=logging.FileHandler(filename,encoding="utf-8")
filehandler.setFormatter(self.formatter)
return filehandler
def _get_console_handler(self):
console_handler=logging.StreamHandler(sys.stdout)
console_handler.setFormatter(self.formatter)
return console_handler
@property
def logger(self):
return self._logger
if __name__ == '__main__':
import datetime
logging=Logger().logger
logging.info(u"{}:开始XXX操作".format(datetime.datetime.now()))
# -*- coding:utf-8 -*-
import configparser
class ReadConfig(object):
# 构造函数
def __init__(self, file_name=None):
'''
:param file_name: 配置文件地址
:param node: 节点名字
'''
# 容错处理
if file_name == None:
# 默认地址
self.file_name = r'../config/config.ini'
else:
self.file_name = file_name
self.cf = self.load_ini(self.file_name)
# 加载文件
def load_ini(self, file_name):
cf = configparser.ConfigParser()
cf.read(file_name, encoding='utf-8')
return cf
# 获取value得值
def get_value(self, node, key):
data = self.cf.get(node, key)
return data
# 存储token值到config。ini
def set_value(self, group, instance, value):
self.cf.set(group, instance, value)
# 保存config.ini
def save(self,filename):
with open(filename, 'w') as f:
self.cf.write(f)
if __name__ == '__main__':
cf = ReadConfig()
print(cf.get_value('env', 'ip'))
config.ini文件格式:
# cat ../config/config.ini
[db]
user = root
password = 123456
host = dev.mysql.com
port = 3306
[redis]
host = dev.redis.com
port = 6379
password = 123456
# -*- coding:utf-8 -*-
import pymysql
import sys
class Mc(object):
# 这里 注释连接的方法,是为了 实例化对象时,就创建连接。不许要单独处理连接了。
#
# def connDataBase(self):
# ''' 数据库连接 '''
#
# self.db = pymysql.connect(self.host,self.username,self.password,self.port,self.database)
#
# # self.cursor = self.db.cursor()
#
# return self.db
def __init__(self,db_host="*****", username="root", pw="**********",port=3306, dbname="*****"):
self.db_host=db_host
self.username=username
self.pw=pw
self.dbname=dbname
self.port=port
self.db=pymysql.connect(self.db_host,self.username,self.pw,self.dbname,self.port,charset='utf8')
#print(dbname)
def insertDB(self, sql):
''' 插入数据库操作 '''
self.cursor = self.db.cursor()
try:
# 执行sql
self.cursor.execute(sql)
# tt = self.cursor.execute(sql) # 返回 插入数据 条数 可以根据 返回值 判定处理结果
# print(tt)
self.db.commit()
except:
# 发生错误时回滚
self.db.rollback()
finally:
self.cursor.close()
def deleteDB(self, sql):
''' 操作数据库数据删除 '''
self.cursor = self.db.cursor()
try:
# 执行sql
self.cursor.execute(sql)
# tt = self.cursor.execute(sql) # 返回 删除数据 条数 可以根据 返回值 判定处理结果
# print(tt)
self.db.commit()
except:
# 发生错误时回滚
self.db.rollback()
finally:
self.cursor.close()
def updateDb(self, sql):
''' 更新数据库操作 '''
self.cursor = self.db.cursor()
try:
# 执行sql
self.cursor.execute(sql)
# tt = self.cursor.execute(sql) # 返回 更新数据 条数 可以根据 返回值 判定处理结果
# print(tt)
self.db.commit()
except:
# 发生错误时回滚
self.db.rollback()
finally:
self.cursor.close()
def selectDb(self, sql):
''' 数据库查询 '''
self.cursor = self.db.cursor()
try:
self.cursor.execute(sql) # 返回 查询数据 条数 可以根据 返回值 判定处理结果
data = self.cursor.fetchall() # 返回所有记录列表
#print(type(data))
#print(data[0][0])
except:
print('Error: unable to fecth data')
finally:
self.cursor.close()
return data
def closeDb(self):
''' 数据库连接关闭 '''
self.db.close()
if __name__ == '__main__':
mc=Mc()
sql='SELECT * from student;'
result=mc.selectDb(sql)
print(result)
注意:
连接数据库时报错“AttributeError: ‘NoneType’ object has no attribute ‘encoding’”
解决办法:将下面部分的utf-8改为utf8
self.db=pymysql.connect(self.db_host,self.username,self.pw,self.dbname,self.port,charset=‘utf-8’)
在自动化测试中经常将测试数据放入到Excel中,为了操作简便,将一些操作封装到readExcel类中
# -*- coding:utf-8 -*-
# author_='ting.chun'
# date:2020/10/22 19:05
import xlrd
from xlutils import copy
class ReadExcel:
'''
此类专门用于读取Excel
'''
#__workbook用于存放excel文件的对象
__workbook=None
__sheet=None
__print=False #用于开启全局打印
def __init__(self,file_name,sheet_name):
'''
类的初始化方法,在类似初始化的时候被调用
:param file_name: excel的文件名
:param sheet_name: excel中需要访问的sheet名
'''
self.file_name=file_name
ReadExcel.__workbook=xlrd.open_workbook(file_name)
#根据sheet名称获取sheet内容
ReadExcel.__sheet=ReadExcel.__workbook.sheet_by_name(sheet_name)
def get_number_of_rows(self):
'''
获取表格中内容的最大行数
:return:__number_of_row
'''
__rows_number=self.__sheet.nrows
if ReadExcel.__print is True:
print(__rows_number)
return __rows_number
def get_number_of_cols(self):
'''
获取表格中内容最大的列数
:return: __number_of_cols
'''
__cols_number=self.__sheet.ncols
if ReadExcel.__print is True:
print(__cols_number)
return __cols_number
def get_value_of_row(self,row_index):
"""
获取某一行的所有值构成列表
:param row_index: 行号
:return: 行内容组成的列表
"""
__row_value=self.__sheet.row_values(row_index)
if ReadExcel.__print is True:
print(__row_value)
return __row_value
def get_value_of_col(self, col_index):
"""
获取某一列的所有值构成的列表
:param col_index: 列号
:return: 列中内容组成的列表
"""
__col_value = self.__sheet.col_values(col_index)
if ReadExcel.__print is True:
print(__col_value)
return __col_value
def get_value_of_cell(self, row_index, col_index):
"""
获取某一个单元格中的值
:param row_index: 行号
:param col_index: 列号
:return: 单元格中的内容
"""
# 第row_index行 col_index列是内容
__cell_value = self.__sheet.cell(row_index, col_index).value
if ReadExcel.__print is True:
print(__cell_value)
return __cell_value
def write(self,sheet,row,col,value):
new_workbook=copy.copy(ReadExcel.__workbook)
w_sheet=new_workbook.get_sheet(sheet)
w_sheet.write(row,col,value)
new_workbook.save(self.file_name) #保存文件
if __name__=='__main__':
filename=r'..\config\api_info.xls'
el=ReadExcel(filename,'Sheet1')
el.write(0,2,1,"你好吗")
# -*- coding:utf-8 -*-
# author_='ting.chun'
# date:2020/10/22 11:26
import time,datetime
import random
import string
class Tool:
#获取注册的email
def get_email(self):
value='{}@163.com'.format(str(int(time.time())))
return value
#使用时间戳作为一个唯一标识
def get_unique(self):
unique=int(time.time())
return unique
#生成11的手机号
def get_phone(self):
# 运营商的号码前缀
prefix = [
'130', '131', '132', '133', '134', '135', '136', '137', '138', '139',
'145', '147', '149', '150', '151', '152', '153', '155', '156', '157',
'158', '159', '165', '171', '172', '173', '174', '175', '176', '177',
'178', '180', '181', '182', '183', '184', '185', '186', '187', '188',
'189', '191'
]
#随机取一个手机号前缀
pos=random.randint(0,len(prefix)-1)
#随机生成后8为数字,string。digits是数字0到9
suffix=''.join(random.sample(string.digits,8))
#拼接返回11位手机号
return prefix[pos]+suffix
#print(str(int(time.time()))+"@163.com")
if __name__ == '__main__':
tool=Tool()
phone=tool.get_email()
print(phone)
import pytest
from interface.regexEngine import regex_Engine
from common.readConfig import ReadConfig
import time
import os
class Test_Rengine:
#类级别
def setup_class(self):
#先删除文件
path=r'C:\User****'
file_list =os.listdir(path)
for file in file_list :
os.remove(os.path.join(path,file))
print("在该类执行之前,先引入配置项参数")
cf = ReadConfig(r'../config/reg.ini') # 获取配置文件
url=cf.get_value('env','url')
self.reg=regex_Engine(r'../data/rengine.xlsx',url)
def test_counts(self):
for i in range(11):
res=self.reg.set_regex(i)
if res==1:
print("用例%s执行成功" %(i))
else:
print("用例%s执行失败" %(i))
@pytest.mark.skip
# 类级别
def teardown_class(self):
print("执行结果写入------------------------------")
filename = r'../data/result.xlsx'
self.reg.get_data(filename)
print("----->test_Regine模块用例执行完成")
if __name__ == "__main__":
pytest.main()
上述主要受common包组成模块代码,后续会继续更新,喜欢的请关注哟!