最近随着项目越来越大,页面也越来越多。这种regression的bug也屡见不鲜,造成这一原因的根本原因是,我们缺少了自动化测试。很多以前正常的功能,在无意间被破坏,而测试也只focus在新开发的功能上。这就造成,每当濒临发布,一堆的bug铺面而来。为了减少不必要的工作,一套自动化测试是非常有必要的。
此次,我会采用python+Selenium+unittest构建一套基本的自动化测试。
环境需求(window)
项目搭建
项目结构
一、test_config(配置)
包含一系列系统运行所需的配置信息,包括地址信息,账号密码等
# -*- coding: utf-8 -*-
import os
test_home_url = 'http://baidu.com'
test_login_user_account = 'xxxxx'
test_login_user_password = 'xxxxx'
test_base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
test_log_path = test_base_path + os.path.sep + 'test_report' + os.path.sep + 'log' + os.path.sep
test_screenshot_path = test_base_path + os.path.sep + 'test_report' + os.path.sep + 'screenshot' + os.path.sep
test_report_path = test_base_path + os.path.sep + 'test_report' + os.path.sep + 'report' + os.path.sep
test_report_html_title = 'baidu_test_result'
test_data_path = test_base_path + os.path.sep + 'test_data' + os.path.sep
test_case_path = test_base_path + os.path.sep + 'test_suite' + os.path.sep + 'test_case' + os.path.sep
二、test_driver(驱动)
主要是做以下三个部分,检查浏览器驱动,及封装驱动使用
1). 可以根据浏览器类型选择驱动
# -*- coding: utf-8 -*-
from selenium import webdriver
from test_driver.chromeDriver import ChromeDriver
class BrowserDriver(object):
def get_driver(self, browser="chrome"):
if browser == "firefox" or browser == "ff":
driver = webdriver.Firefox()
elif browser == "internet explorer" or browser == "ie":
driver = webdriver.Ie()
elif browser == "opera":
driver = webdriver.Opera()
elif browser == "phantomjs":
driver = webdriver.PhantomJS()
elif browser == 'edge':
driver = webdriver.Edge()
else:
chromedriver = ChromeDriver()
chromedriver.check_update_chromedriver()
driver = webdriver.Chrome()
try:
driver.maximize_window()
driver.implicitly_wait(20)
return driver
except Exception:
raise NameError(
"Not found %s browser,You can enter 'ie', 'ff', 'opera', 'phantomjs', 'edge' or 'chrome'." % browser)
2). 检查所选浏览器类型,检查相应的浏览器版本和驱动版本是否一致
比如你选谷歌浏览器,则部分检查代码如下,需要根据浏览器版本下载相应的驱动到python的安装目录。
def check_update_chromedriver(self):
'''
Check chromedriver version and chrome browser version, if not compatible, download and update chromedriver version.
'''
warnings.simplefilter("ignore", ResourceWarning)
chrome_version = self.get_chrome_version()
chrome_main_version = int(chrome_version.split(".")[0]) # chrome main version
driver_version = self.get_chrome_driver_version()
driver_main_version = int(driver_version.split(".")[0]) # chromedriver main version
if chrome_main_version == driver_main_version:
print('Chromedriver version({}) is compatible with chrome browser({}), no need to update chromedriver version!'.format(driver_version,chrome_version))
else:
try:
print("chromedriver version({}) is not compatible with chrome browser version({}), updating...Please wait...>>>".format(driver_version,chrome_version))
self.get_latest_chrome_driver(chrome_version)
except Exception as e:
print(f'Fail to update: {e}')
3). 封装selenium的基本操作
包括最大化,点击,鼠标右键,元素查找等
class DriverProvider:
def __init__(self, driver=None):
if driver:
self.driver = driver
else:
self.driver = BrowserDriver().get_driver()
def close(self):
self.driver.close()
def quit(self):
self.driver.quit()
def get_element_attribute(self, loc, attr)
try:
e = self.driver.find_element(*loc)
return e.get_attribute(attr)
except:
# print log
# save snapshot screen
pass
def get_element_text(self, loc)
pass
三、test_suite(测试用例)
包括一个你所需做的test_page, test_case, 和test_data, 此处我们的test_case可以使用unittest框架,也可以选择pytest。此处我们选择unittest进行架构,比如我们测试百度的首页及搜索功能。基本架子如下,当然你也可以根据自己的习惯去构建,我是将整个test suite又分拆成三个包:
1)case子包
提供对应页面的case,比如我这里做了首页的标题测试和搜索功能测试,当然可以更细节
class TestHomePage(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.page = HomePage()
cls.page.open(test_home_url)
def test_baidu_btn_title(self):
self.assertEqual(self.page.get_baidu_button_text(), baidu_title)
def test_baidu_search_function(self):
self.page.fill_search_text(baidu_search_text)
self.page.click_search_button()
self.assertTrue(self.page.is_search_text_existed_in_first_list_item(baidu_search_text))
def tearDown(self):
self.page.driver.refresh()
time.sleep(10)
@classmethod
def tearDownClass(cls):
cls.page.quit()
if __name__ == '__main__':
unittest.main()
2)page子包
提供对应页面的基于我们provider的操作,HomePage继承自DriverProvider(我们自己定义),最好是把我们的选择器也提取出来单独放在一个文件里,因为我们可以可以会经常修改选择器(随着前端开发的进行)。
from test_driver.driverProvider import DriverProvider as Provider
from selenium.webdriver.common.by import By
import time
class HomePage(Provider):
# Check homepage - title
def get_baidu_button_text(self):
return self.get_element_attribute((By.XPATH, '//input[@id="su"]'), 'value', 'baidu_button_text')
# fill search text
def fill_search_text(self, kw):
self.input_text((By.XPATH, '//input[@id="kw"]'), kw)
time.sleep(2)
# click search button
def click_search_button(self):
self.click_element((By.XPATH, '//input[@id="su"]'))
time.sleep(5)
# is search item existed
def is_search_text_existed_in_first_list_item(self, text):
searchText = self.get_element_text((By.XPATH, '//div[@class="content_left"]/div[1]/div/div/h3/a'))
return text in searchText
3)data子包
提供我们测试时用到的数据,比如上面case用到的baidu_title,baidu_search_text
baidu_title = '百度一下'
baidu_search_text = '你好'
四、test_report(打印log和html报告)
log子目录存放我们跑测试过程中的日志。
report子目录存放我们html报告。
screenshot子目录存放case错误的页面截图。
此处我们使用的HtmlTestRunner进行报告的打印。可自行上网搜索报告模板,当然也可以使用jinjia2进行结果的打印。
上面搭建完成,基本就已经可以了,然后我们在startup里启动我们的自动化测试。
我们使用TestLoader去扫描case路径下的所有文件,然后使用HtmlTestRunner进行html报告的打印
import unittest
from test_config.config import test_case_path
from test_report.report import Report
if __name__ == '__main__':
suite = unittest.TestSuite()
loader = unittest.TestLoader()
suite.addTests(loader.discover(test_case_path))
Report(suite).run()
报告如下:
发表评论
所有评论(0)