我的第一份UI自动化测试框架
一、框架介绍:
1、本框架使用Python开发语言,结合selenium,unnitest单元测试框架,再采用PO模型进行封装,整个框架结构一共包含了十大模块,如下图所示: 1、base层:基础层,存放我们的基础定位元素的方法,一共八种常用的方法; 2、business层:业务层,存放我们业务功能处理; 3、case层:存放我们测试用例; 4、congfig层:存放元素的定位信息; 5、handle层:存放页面的操作信息; 6、img层:存放图片信息; 7、log层:存放日志信息; 8、page层:存放页面信息; 9、report层:存放测试报告信息; 10、until层:存放工具类信息;
二、框架搭建
1、本框架配置文件采用的是ini文件存储,所以第一步是在until层,创建读取ini文件:
def __init__(self, file_name=None, node=None):
if file_name is None:
file_name = r'C:\Users\Mrlin\PycharmProjects\Cost_management_system\config\YuanGon.ini'
if node is None:
self.node = 'RegisterElement'
else:
self.node = node
self.cf = self.getIni(file_name)
def getIni(self, file_name):
cf = configparser.ConfigParser()
cf.read(file_name, encoding='UTF-8')
return cf
def getMessage(self, node, key):
data = self.cf.get(node, key)
return data
2、写好读取ini配置文件之后,开始进行第二步,在base层定义我们selenium操作页面元素的方法:
def __init__(self, driver):
self.driver = driver
def get_element(self, file_path, note, key):
read_ini = Read_ini(file_path)
data = read_ini.getMessage(note, key)
by = data.split('>')[0]
value = data.split('>')[1]
try:
if by == 'id':
return self.driver.find_element_by_id(value)
elif by == 'name':
return self.driver.find_element_by_name(value)
elif by == 'className':
return self.driver.find_element_by_class_name(value)
elif by == 'xpath':
return self.driver.find_element_by_xpath(value)
elif by == 'link_text':
return self.driver.find_element_link_text(value)
elif by == 'partial_link_text':
return self.driver.find_element_partial_link_text(value)
elif by == 'css_selector':
return self.driver.find_element_css_selector(value)
else:
return self.driver.find_element_tag_name(value)
except:
return None
3、两份文件编写完成后,就可以在开始第三步,再config层编写我们的定位元素配置信息了:
;登录页面相关定位信息
;[]内内容为node,=号左边为key,右边内容根据‘>’拆分
[LoginElement]
;选择账号登录
salecard_select = xpath>//span[text()='账号登录']
;用户名
salecard_login_Name = xpath>//input[@placeholder='账号']
;密码
salecard_login_Password = xpath>//input[@placeholder='密码']
;验证码
salecard_code = xpath>//input[@placeholder='请输入验证码']
;验证码图片
salecard_code_img = xpath>//img[@alt='验证码']
;登录按钮
salecard_login_Button = xpath>//span[text()='登录']
[URL]
;系统网址
login_url = http://test-passport.gzjunbo.net/login/index.html?callback=http://test-card-admin.liulianglf.cn/index.html
4、配置信息编写完成之后,便可以开始第四步,在page层编写业务所需的页面信息:
def __init__(self, driver):
self.login_find_element = MatchElementPosition(driver)
self.file_path = os.path.abspath(os.path.dirname(os.getcwd())) + r'\config' + r'\salecard_login.ini'
def get_login_select(self):
return self.login_find_element.get_element(self.file_path, 'LoginElement', 'salecard_select')
def get_login_name(self):
return self.login_find_element.get_element(self.file_path, 'LoginElement', 'salecard_login_Name')
def get_login_password(self):
return self.login_find_element.get_element(self.file_path, 'LoginElement', 'salecard_login_Password')
def get_login_code(self):
return self.login_find_element.get_element(self.file_path, 'LoginElement', 'salecard_code')
def get_login_code_img(self):
return self.login_find_element.get_element(self.file_path, 'LoginElement', 'salecard_code_img')
def get_login_button(self):
return self.login_find_element.get_element(self.file_path, 'LoginElement', 'salecard_login_Button')
5、编写完成页面信息之后,便可以开始第五步,再handle层编写页面操作信息了:
def __init__(self, driver):
self.salecard_login_page = SalecradLoginPage(driver)
def click_select(self):
return self.salecard_login_page.get_login_select().click()
def send_name(self, username):
return self.salecard_login_page.get_login_name().send_keys(username)
def send_password(self, password):
return self.salecard_login_page.get_login_password().send_keys(password)
def send_code(self, code):
return self.salecard_login_page.get_login_code().send_keys(code)
def click_button(self):
return self.salecard_login_page.get_login_button().click()
6、编写完成页面操作的脚本之后,可以开始开始第六步,在business层编写业务处理逻辑:
def __init__(self, driver):
self.driver = driver
self.login_handle = LoginHandle(driver)
self.getcode = GetCode(driver)
def user_operate(self, name, password):
self.login_handle.click_select()
time.sleep(1)
self.login_handle.send_name(name)
time.sleep(1)
self.login_handle.send_password(password)
time.sleep(1)
self.getcode.get_img(r'E:\Knowledge\img\whole_code.png', r'E:\Knowledge\img\code.png')
code = self.getcode.get_code(r'E:\Knowledge\img\code.png')
self.login_handle.send_code(code)
time.sleep(1)
def success_assert(self):
text = self.driver.title
if text == '酬金业务-运营管理后台':
return True
elif text == '登录中心':
return True
else:
return False
def user_normal_operate(self, name, password):
self.user_operate(name, password)
time.sleep(1)
self.login_handle.click_button()
time.sleep(5)
return self.success_assert()
7、到这已经完成所有的基本操作,接下来便是在case层编写我们的测试用例,因为我们在case层使用了log日志记录、读取excel进行参数化、以及使用HTMLtestrunner进行报告输出,所以呢需要在until层把这些工具类先编写好,方便调用; <1>创建日志文件,读取log日志:
def __init__(self):
self.logger = logging.getLogger()
self.logger.setLevel(logging.INFO)
base_dir = os.path.abspath(os.path.join(os.path.dirname("__file__"), os.path.pardir))
log_file = datetime.datetime.now().strftime('%Y-%m-%d') + '-' + 'log.ini'
log_name = base_dir + "/log/" + log_file
self.file_handle = logging.FileHandler(log_name, 'a', encoding='utf-8')
formatter = logging.Formatter('%(asctime)s %(filename)s ---> %(funcName)s %(levelno)s: %(levelname)s ---> %(message)s')
self.file_handle.setFormatter(formatter)
self.logger.addHandler(self.file_handle)
def get_log(self):
return self.logger
def close_log(self):
self.logger.removeHandler(self.file_handle)
self.file_handle.close()
<2>创建excel文件,读取excel文件:
def __init__(self, excel_path=None, index=None):
if excel_path is None:
excel_path = r'E:\Knowledge\config\Test_case_parameters.xls'
else:
self.excel_path = excel_path
if index is None:
index = 0
else:
self.index = index
self.data = xlrd.open_workbook(excel_path)
self.table = self.data.sheets()[index]
def get_row(self):
rows = self.table.nrows
if rows >= 1:
return rows
return None
def get_cell(self, row, column):
rows = self.get_row()
if rows >= row:
title = self.table.cell(row, column).value
return title
return None
def get_column_data(self, column):
result = []
rows = self.get_row()
if rows is not None:
for i in range(1, rows):
value = self.table.cell(i, column).value
result.append((value))
return result
return None
def get_excel_data(self):
result = []
rows = self.get_row()
if rows is not None:
for i in range(1, rows):
value = self.table.row_values(i)
result.append((value))
return result
return None
def write_data(self, row, column, value):
excel_value = self.data
write_data = copy(excel_value)
if row >= 1 and column >= 0:
write_data.get_sheet(0).write(row, column, value)
write_data.save(r'E:\Knowledge\config\Test_case_parameters.xls')
return None
<3>做完这两步,接下来可以直接在case层编写我们的测试用例文件:
@ddt.ddt
class Knowledge(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.log = RecordLog()
cls.logger = cls.log.get_log()
def setUp(self):
self.RP = Premise()
self.RP.get_url()
@ddt.data(*data)
def test_normal_login(self, data):
name, password = data
case = self.RP.LB.user_normal_operate(name, password)
self.assertTrue(case)
self.logger.info('test is chrome')
def tearDown(self):
self.RP.driver.quit()
@classmethod
def tearDownClass(cls):
cls.log.close_log()
8、最后一步便是,执行我们的case,报告采用HTMLtestrunner:
def allcase():
case_dir = os.path.abspath(os.path.dirname(os.getcwd())) + r'\case'
testcase = unittest.TestSuite()
discover = unittest.defaultTestLoader.discover(case_dir,
pattern='test_*.py',
top_level_dir=None)
for test_suite in discover:
for test_case in test_suite:
print(test_case)
testcase.addTest(test_case)
return testcase
if __name__ == "__main__":
now_time = time.strftime('%Y-%m-%d %H_%M_%S')
file_path = os.path.abspath(os.path.dirname(os.getcwd())) + r'\report' + r'\Automation_Report_'+ now_time + '.html'
f = open(file_path, 'wb')
runner = HTMLTestRunner.HTMLTestRunner(stream=f, title='专业知识点掌握情况反馈系统自动化测试报告', description='专业知识点掌握情况反馈系统自动化测试报告', verbosity=2)
runner.run(allcase())
f.close()
结语
最后到这框架介绍就结束了,这是一个简单的UI自动化框架,里面还有很多可以优化的地方;
|