pytest+selenium+allure Webui自动化简易框架
介绍
简易自动化框架。
软件架构
pytest5.4.2
selenium3.141.0
allure_python_commons2.8.29
PyYAML5.4.1
python==3.6.0
依赖安装
使用 pip install -r requirements.txt
目录结构
casecase文件目录
data_casecase参数
driverswebdriver存放
lib定义log、读取yml、时间装饰器
logs存放log文件
page功能方法封装
report报告存放
test_run定义启动类,启动使用的命令
config.ini配置文件
connftest.py全局共享使用
run.py==入口文件
case文件中demo
import allure
import pytest
from page.webpage import BasePage
from lib.init_data import get_data
base_data=get_data("demo.yml")
@pytest.mark.usefixtures()
class Test_case():
@pytest.mark.parametrize("uer",base_data['test_id'])
@allure.feature('打开百度登录')
def test_1(self,uer):
d =BasePage()
d.by_id(uer)
assert 1==2```
yml文件格式
test_id:
- "s-top-loginbtn我的","id",'我的'
webdriver封装
from selenium import webdriver
#封装Chrome启动的driver
def webdrivers():
d = webdriver.Chrome()
return d
webdrivers()
func装饰器
import time
#等待时间装饰器
def think_time(func):
def thinktime(*args,**kwargs):
time.sleep(1)
return func(*args,**kwargs)
return thinktime
init_data 读取不同参数文件的方法
from lib.read_data import data
import os
#对读取测试数据及ini文件的配置
BASE_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
def get_data(file_name):
data_file_path = os.path.join(BASE_PATH, "data_case", file_name)
if '.yml' in file_name:
test_data = data.load_yaml(data_file_path)
if '.json' in file_name:
test_data = data.load_json(data_file_path)
if '.ini' in file_name:
test_data = data.load_ini(data_file_path)
return test_data
loggers日志封装及配置
import os, time
import os.path
import socket
import logging
import logging.handlers
#log日志的配置封装
def singleton(cls, *args, **kw):
instances = {}
def _singleton():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return _singleton
# @singleton
class JFMlogging(object):
def __init__(self):
# host_name = socket.gethostname()
# ip = socket.gethostbyname(host_name)
log_path = 'logs' # 日志存放目录
if not os.path.exists(log_path):
os.mkdir(log_path)
log_file = os.path.join(log_path, "{}.log".format(time.strftime("%Y%m%d")))
self.logger = logging.getLogger()
self.logger.setLevel(logging.INFO)
self.logging_msg_format = '[%(asctime)s] [%(levelname)s] [%(module)s.py-line:%(lineno)d] %(message)s'
self.formater = logging.Formatter(self.logging_msg_format)
self.fileHandler = logging.FileHandler(log_file, mode='a', encoding="UTF-8")
self.fileHandler.setFormatter(self.formater)
self.fileHandler.setLevel(logging.INFO)
self.console = logging.StreamHandler()
self.console.setLevel(logging.INFO)
self.console.setFormatter(self.formater)
self.logger.addHandler(self.fileHandler)
self.logger.addHandler(self.console)
# def getloger(self):
# return self.logger
log = JFMlogging().logger
read_data 重写configparser,解决转码
import yaml
import json
from configparser import ConfigParser
from lib.loggers import log
class MyConfigParser(ConfigParser):
# 重写 configparser 中的 optionxform 函数,解决 .ini 文件中的 键option 自动转为小写的问题
def __init__(self, defaults=None):
ConfigParser.__init__(self, defaults=defaults)
def optionxform(self, optionstr):
return optionstr
class ReadFileData():
def load_yaml(self, file_path):
log.info("加载 {} 文件......".format(file_path))
with open(file_path, encoding='utf-8') as f:
data = yaml.safe_load(f)
log.info("读到数据 ==>> {} ".format(data))
return data
def load_json(self, file_path):
log.info("加载 {} 文件......".format(file_path))
with open(file_path, encoding='utf-8') as f:
data = json.load(f)
log.info("读到数据 ==>> {} ".format(data))
return data
def load_ini(self, file_path):
log.info("加载 {} 文件......".format(file_path))
config = MyConfigParser()
config.read(file_path, encoding="UTF-8")
data = dict(config._sections)
return data
data = ReadFileData()
webpage初始操作及公共方法
from lib.init_data import get_data
from lib.func import think_time
import os
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
BASE_CONF = get_data(os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "config.ini"))['App']
class WebPage():
#读取config.ini中的配置
def __init__(self,d):
self.d = d
self.web = BASE_CONF['URL_NAME']
self.time_out = BASE_CONF['WAIT_TIMEOUT']
class BasePage(WebPage):
#初始化
def __init__(self):
self.driver = webdriver.Chrome()
self.wait = WebDriverWait(self.driver,10)
self.driver.maximize_window()
WebPage.__init__(self,self.driver)
self.openBaidu()
def openBaidu(self):
#默认打开百度
self.d.get(self.web)
#————————————————————————————————————封装公共方法——————————————————————————————————————————
def by_id(self,id):
self.d.find_element_by_id(id).click()
def by_class(self,classname):
self.d.find_element_by_class_name(classname).click()
run_test定义启动项及命令
import pytest
import os
#定义启动项
class RunTest():
def _runpytest(self):
pass
#pytest启动
@staticmethod
def run_alltest():
# # 执行pytest单元测试,生成 Allure 报告需要的数据存在 /temp 目录,使用--clean-alluredir 覆盖之前的json文件
# pytest.main(['-s', '-q','--alluredir', './report','--clean-alluredir'])
# # 执行命令 allure generate ./temp -o ./report --clean ,生成测试报告
# # os.system(" allure generate ./report/result_allure -o ./report/result_html -c")
pytest.main(['-s', '-q', '--alluredir', './report', '--clean-alluredir'])
os.system('allure generate ./report -o ./report/temp --clean')
connftest定义全局的driver
import pytest
import drivers.webdriver
from lib.loggers import log
#初始化全局 driver
@pytest.fixture(scope='class',autouse=True)
def driver():
try:
global driver
driver =drivers.webdriver.webdrivers()
return driver
except Exception as e:
log.info('初始化webdriver{}'.format(e))
run入口文件
from test_run import run_test
#入口文件
class startest(run_test.RunTest):
import time
test_data = time
if __name__ == '__main__':
startest.run_alltest()
工作中用到也是学习阶段,大神看了就指点,不喜勿喷,仅个人的一点小记录而已!!!
源码:https://gitee.com/zc119/web-ui.git