目录
前言:selenium api只封装部分,业务公共页面page、连接数据库封装,后续实践后补上。有问题欢迎留言补充,谢谢~
一、框架结构目录
二、读取文件
utils下新建file_reader.py
# -*- coding: utf-8 -*-
import yaml
import os
from xlrd import open_workbook
class YamlReader:
def __init__(self, yamlf):
if os.path.exists(yamlf):
self.yamlf = yamlf
else:
raise FileNotFoundError('文件不存在!')
self._data = None
@property
def data(self):
# 如果是第一次调用data,读取yaml文档,否则直接返回之前保存的数据
if not self._data:
with open(self.yamlf, 'rb') as f:
self._data = list(yaml.safe_load_all(f)) # load后是个generator,用list组织成列表
return self._data
class SheetTypeError(Exception):
pass
# 读取excel文件中的内容。返回list。
class ExcelReader:
"""
如:
excel中内容为:
| A | B | C |
| A1 | B1 | C1 |
| A2 | B2 | C2 |
如果 print(ExcelReader(excel, title_line=True).data),输出结果:
[{A: A1, B: B1, C:C1}, {A:A2, B:B2, C:C2}]
如果 print(ExcelReader(excel, title_line=False).data),输出结果:
[[A,B,C], [A1,B1,C1], [A2,B2,C2]]
可以指定sheet,通过index或者name:
ExcelReader(excel, sheet=2)
ExcelReader(excel, sheet='BaiDuTest')
"""
def __init__(self, excelpath, sheet=0, title_line=True):
if os.path.exists(excelpath):
self.excelpath = excelpath # excel文件路径
else:
raise FileNotFoundError('文件不存在!')
self.sheet = sheet # sheet可以是int表示表格的索引,可以是str表示表格的名称
self.title_line = title_line # 是否存在标题行,有标题行,每一行都是都是对应列名的取值;没有标题行,每一行都是一个列表
self._data = list() # 用于存储每行生成的数据。
@property
def data(self):
if not self._data:
workbook = open_workbook(self.excelpath)
if type(self.sheet) not in [int, str]:
raise SheetTypeError('Please pass in <type int> or <type str>, not {0}'.format(type(self.sheet)))
elif type(self.sheet) == int:
s = workbook.sheet_by_index(self.sheet)
else:
s = workbook.sheet_by_name(self.sheet)
if self.title_line:
title = s.row_values(0) # 首行为title
for col in range(1, s.nrows):
# 依次遍历其余行,与首行组成dict,拼到self._data中
self._data.append(dict(zip(title, s.row_values(col))))
else:
for col in range(0, s.nrows):
# 遍历所有行,拼到self._data中
self._data.append(s.row_values(col))
return self._data
if __name__ == '__main__':
y = 'D:\myProject\config\config.yml'
reader = YamlReader(y)
print(reader.data)
e = 'D:/myProject/data/baidu.xlsx'
reader = ExcelReader(e, title_line=True)
print(reader.data)
三、配置文件config.py
utils下新建config.py
#-*- coding: utf-8 -*-
import os
from utils.file_reader import YamlReader
# 通过当前文件的绝对路径,其父级目录一定是框架的base目录,然后确定各层的绝对路径。如果你的结构不同,可自行修改。
# 之前直接拼接的路径,修改了一下,用现在下面这种方法,可以支持linux和windows等不同的平台,也建议大家多用os.path.split()和os.path.join(),不要直接+'\\xxx\\ss'这样
BASE_PATH = os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]
CONFIG_FILE = os.path.join(BASE_PATH, 'config', 'config.yml')
DATA_PATH = os.path.join(BASE_PATH, 'data')
DRIVER_PATH = os.path.join(BASE_PATH, 'drivers')
LOG_PATH = os.path.join(BASE_PATH, 'log')
REPORT_PATH = os.path.join(BASE_PATH, 'report')
class Config:
def __init__(self, config=CONFIG_FILE):
self.config = YamlReader(config).data
def get(self, element, index=0):
"""
yaml是可以通过'---'分节的。用YamlReader读取返回的是一个list,第一项是默认的节,如果有多个节,可以传入index来获取。
这样我们其实可以把框架相关的配置放在默认节,其他的关于项目的配置放在其他节中。可以在框架中实现多个项目的测试。
"""
return self.config[index].get(element)
config目录下新建config.yml
URL: http://www.baidu.com # 测试网址
emailserver: smtp.qq.com #发件箱邮件服务
from_user: XXXXXX@qq.com
from_passwd: tkmyrvvwigmwbihe
to_user: XXXXXXXX@qq.com
#mysql
mysql:
ip: '192.168.3.6'
user: 'root'
pwd: 'password'
db: 'mysql'
#oracle
oracle:
ip: '192.168.3.1'
user: 'root'
pwd: 'password'
port: '1521'
sid: 'barc'
log:
file_name: testcase.log # 输出日志文件名
backup: 5 # 备份名
console_level: WARNING # 控制台输出等级
file_level: DEBUG # 文件输出等级
pattern: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' # 打印输出格式
四、日志
utils下新建logger.py
# -*- coding: utf-8 -*-
import logging
import os
import unittest
import time
import os.path
class Logger(object):
def __init__(self, logger, CmdLevel=logging.INFO, FileLevel=logging.INFO):
self.logger = logging.getLogger(logger)
self.logger.setLevel(logging.DEBUG) # 设置日志默认级别为DEBUG
fmt = logging.Formatter('%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s - %(message)s') # 设置日志输出格式
currTime = time.strftime('%Y%m%d%H%M', time.localtime(time.time())) # 格式化当前时间
log_path = os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]+'/log/'
print('得到的日志路径为:', log_path)
log_name = log_path + currTime + '.log' # 设置日志文件名称
# 设置由文件输出
fh = logging.FileHandler(log_name, encoding='utf-8') # 采用utf-8字符集格式防止出现中文乱码
fh.setFormatter(fmt)
fh.setLevel(FileLevel) # 日志级别为INFO
# 设置日志由控制台输出
# sh = logging.StreamHandler(log_name)
# sh.setFormatter(fmt)
# sh.setLevel(CmdLevel)
self.logger.addHandler(fh) # 添加handler
def getlog(self):
return self.logger
if __name__ == '__main__':
unittest.main()
五、封装浏览器
utils下新建browserengine.py
# -*- coding: utf-8 -*-
from selenium import webdriver
import configparser
import sys, os
class BrowserEngine(object):
def __init__(self, driver):
self.driver = driver
browser_type = "Chrome"
def get_browser(self):
if self.browser_type == 'Firefox':
driver = webdriver.Firefox()
elif self.browser_type == 'Chrome':
driver = webdriver.Chrome()
elif self.browser_type == 'IE':
driver = webdriver.Ie()
else:
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
return driver
六、封装数据库
utils下新建conndb.py
#-*- coding: utf-8 -*-
import cx_Oracle,pymysql,json,os
from utils.config import Config
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
myora = Config().get('oracle')
mysql = Config().get('mysql')
class TestDb(object):
def __init__(self,oracle_type):
if oracle_type == 'oracle':
self.connect = cx_Oracle.connect(myora['user'] + "/" + myora['pwd'] + "@" + myora['ip'] + ":" + myora['port'] + "/" + myora['sid'])
self.cursor = self.connect.cursor()
elif oracle_type == 'mysql':
self.connect = pymysql.connect(mysql['ip'], mysql['user'], mysql['pwd'], mysql['db'])
self.cursor = self.connect.cursor()
else:
print("请连接正确的数据库")
def select(self,sql):
try:
self.cursor.execute(sql)
result = self.cursor.fetchall()
print('查询数据成功')
return result
except Exception as e:
print(e)
finally:
self.disconnect()
#返回json串脚本
# list = []
# self.cursor.execute(sql)
# result = self.cursor.fetchall()
# col_name = self.cursor.description
# for row in result:
# dict = {}
# for col in range(len