搭建测试框架,框架目录解析
config : 配置文件,将项目相关的配置全放到这个文件夹中,python支持yaml,ini
ini文件介绍
以[section]开始
以[option=value]结尾
备注以;开头
section不可重名
yaml文件介绍
以---开头,表明文件的开始
列表中的所有成员都开始于相同的缩进级别,并且使用一个“-”作为开头(一个横杠和一个空格)
一个字典是由一个简单的键:值的形式(这个冒号后面必须是一个空格)
ini读取文件封装,yaml读取文件封装
configutil.py
import configparser
import os
import yaml
class ReadIni():
def read_ini(file, section, option):
conf = configparser.ConfigParser()
conf.read(file)
res=conf.get(section, option)
print(res)
return res
class ReafYaml():
def read_yaml(file,key):
f=open(file,encoding='utf-8')
file_data =f.read()
res=yaml.load(file_data,Loader=yaml.FullLoader)
print(res.get(key))
return res.get(key)
if __name__ == '__main__':
current_path = os.path.dirname(os.path.realpath(__file__))
config_path = os.path.dirname(current_path) + os.sep + "config"
yaml_file = os.path.join(config_path, 'test.yaml')
ReafYaml.read_yaml(yaml_file, 'username')
data : 数据文件,将测试用例参数化相关的文件放在这里,xlsx,csv,json
driver :驱动文件
log :日志文件,如test log,error log
report :测试报告
test :测试文件
case-测试用例
test.py
import unittest
from selenium import webdriver
from test.locators import *
from utils.configutil import ReadIni,ReafYaml
from test.page import *
from utils.excelutil import *
from selenium.webdriver.common.action_chains import ActionChains
import yaml
import os
from utils.logutil import *
current_path = os.path.dirname(os.path.realpath(__file__))
config_path = os.path.dirname(current_path) + os.sep + "config"
ini_file = os.path.join(config_path, 'test.ini')
ip = ReadIni.read_ini(ini_file, 'ip_address', 'ip')
# print(ip)
url = '{}user/login?redirect=http%3A%2F%2Fmis-next.aunbox.ce%2FuserDetail'.format(ip)
excel_file = os.path.join(os.path.dirname(current_path) + os.sep + "data", 'case.xlsx')
username = ReadExcel.read_excel(excel_file,'Sheet1','A')
class LoginTest(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.implicitly_wait(10)
self.driver.get(url)
def test_login(self):
Logger('C:\\Users\\Administrator\\PycharmProjects\\yunding\\log\\test.log','info').info('add project')
for user in username:
loginpage=LoginPage(self.driver)
loginpage.enter_username(user)
loginpage.enter_password()
loginpage.click_login_button()
self.assertEqual('超级管理员',loginpage.get_login_name())
quitlogin=self.driver.find_element_by_xpath('//*[@id="root"]/section/section/header/div[2]/span')
ActionChains(self.driver).move_to_element(quitlogin).perform()
self.driver.find_element_by_class_name('ant-dropdown-menu-item').click()
self.driver.get(url)
# self.driver.find_element(*LoginLocators.username).send_keys("{}".format(user))
# self.driver.find_element(*LoginLocators.password).send_keys("{}".format(pad))
# self.driver.find_element(*LoginLocators.loginbutton).click()
# id=self.driver.find_element(*LoginLocators.loginname)
# self.assertEqual('超级管理员',id.text)
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main()
common-测试相关的抽象通用代码
page-页面类
元素定位
locators.py
from selenium.webdriver.common.by import By
# 页面元素
class LoginLocators():
username=(By.ID,'account')
password=(By.ID,'password')
loginbutton=(By.CLASS_NAME,'ant-btn')
loginname=(By.CLASS_NAME,'userName___fQOhV')
元素操作
page.py
from test.locators import *
# 页面元素的操作
class BasePage():
def __init__(self,driver):
self.driver = driver
class LoginPage(BasePage):
'''
用户登录页面元素的操作,,,到这里消失
'''
UserName = (By.XPATH,'//*[@id="username"]') #登录名
def enter_username(self,name):
ele = self.driver.find_element(*LoginLocators.username)
# ele.clear()
ele.send_keys(name) #对用户名元素进行输入
def enter_password(self):
ele = self.driver.find_element(*LoginLocators.password)
ele.send_keys('123456') #输入密码
def click_login_button(self):
ele = self.driver.find_element(*LoginLocators.loginbutton)
ele.click() #点击登录按钮
def get_login_name(self):
ele = self.driver.find_element(*LoginLocators.loginname)
return ele.text #返回登录名
utils :公共方法
config的类
log的类
logutil.py
import logging
from logging import handlers
class Logger(object):
level_relations = {
'debug':logging.DEBUG,
'info':logging.INFO,
'warning':logging.WARNING,
'error':logging.ERROR,
'critical':logging.CRITICAL
}
def __init__(self,fp='d:\\Project_Redmine_01\\log\\test.log',level='info'):
self.level = self.level_relations.get(level)
self.logger = logging.getLogger(fp)
self.logger.setLevel(self.level)
formatter = logging.Formatter('%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
th = handlers.TimedRotatingFileHandler(fp)
th.setFormatter(formatter)
th.setLevel(self.level)
self.logger.addHandler(th)
def debug(self,msg):
self.logger.debug(msg)
def info(self,msg):
self.logger.info(msg)
def warning(self,msg):
self.logger.warning(msg)
def error(self,msg):
self.logger.error(msg)
def critical(self,msg):
self.logger.critical(msg)
if __name__ == '__main__':
log = Logger('abcd.log','debug')
log.info('this is info msg')
log.critical('this is critical msg')
读,写excel的类
excelutil.py
import configparser
import os
import yaml
class ReadIni():
def read_ini(file, section, option):
conf = configparser.ConfigParser()
conf.read(file)
res=conf.get(section, option)
print(res)
return res
class ReafYaml():
def read_yaml(file,key):
f=open(file,encoding='utf-8')
file_data =f.read()
res=yaml.load(file_data,Loader=yaml.FullLoader)
print(res.get(key))
return res.get(key)
if __name__ == '__main__':
current_path = os.path.dirname(os.path.realpath(__file__))
config_path = os.path.dirname(current_path) + os.sep + "config"
yaml_file = os.path.join(config_path, 'test.yaml')
ReafYaml.read_yaml(yaml_file, 'username')
生成报告的类
run.py
import os
import time
import unittest
import HTMLTestRunner
current_path = os.path.dirname(os.path.realpath(__file__))
# print(current_path)
report_path = os.path.join(current_path,'report')
# print(report_path)
case_path = os.path.join(current_path,'test')
# print(case_path)
report_name = time.strftime('%Y%m%d%H%M%S',time.localtime((time.time())))
testsuite = unittest.TestLoader().discover(case_path)
filename = "{}\\{}.html".format(report_path,report_name)
f = open(filename,'wb')
runner = HTMLTestRunner.HTMLTestRunner(stream=f,title='report',description='this is a report')
runner.run(testsuite)
f.close()
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!
在我的QQ技术交流群里(技术交流和资源共享,广告勿扰)
可以自助拿走,群号:175317069 群里的免费资料都是笔者十多年测试生涯的精华。还有同行大神一起交流技术哦
如果对你有一点点帮助,各位的「点赞」就是小编创作的最大动力,我们下篇文章见!