+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2019-03(1)

2019-04(1)

2019-06(1)

2019-07(5)

2019-08(120)

一个基于POM模式的Web自动化测试框架

发布于2020-08-02 10:49     阅读(1086)     评论(0)     点赞(0)     收藏(5)


基于最近可能工作要求,和自动化脚本效率的问题上,对设计模式进行了一些了解

所以参考性的编写了一个这样的POM模式的Web自动化测试框架

如果大家有需要,可以看看,指导探讨一下

 

整体的文件目录

设置了公共文档的读出,在config.ini

可以把一下公共的东西,如url,账号等放进去

 

 

  1. 对公共类进行了封装 为Common中basePage包
  1. class BasePage:
  2. """测试基类"""
  3. def __init__(self, driver):
  4. self.driver = driver
  5. def get_img(self):
  6. """截图"""
  7. # img文件夹路径
  8. img_path = os.path.join(test_123.getcwd.get_cwd(), 'img/')
  9. # img文件夹不存在,新建该文件夹
  10. if not os.path.exists(img_path):
  11. os.makedirs(img_path)
  12. # 获取当前日期
  13. local_date = time.strftime('%Y-%m-%d', time.localtime(time.time()))
  14. # 日期文件夹路径
  15. date_file_path = os.path.join(img_path,local_date)
  16. # 日期文件夹不存在,新建该文件夹
  17. if not os.path.exists(date_file_path):
  18. os.makedirs(date_file_path)
  19. # 截图存放路径
  20. local_time = time.strftime('%Y-%m-%d %H%M%S', time.localtime(time.time()))
  21. jt_name = local_time+'.png'
  22. jt_path = os.path.join(date_file_path, jt_name)
  23. try:
  24. self.driver.get_screenshot_as_file(jt_path)
  25. log1.info('截图保存成功')
  26. except BaseException:
  27. log1.error('截图失败', exc_info=1)
  28. print('Screenshot_Path:', jt_path)
  29. def open_browser(self):
  30. """打开浏览器,访问url"""
  31. browser = config.config_read('environment', 'browser')
  32. log1.info('读取浏览器配置,值为%s' % browser)
  33. url = config.config_read('environment', 'url')
  34. log1.info('读取url,值为%s' % url)
  35. # noinspection PyBroadException
  36. try:
  37. if browser == 'chrome':
  38. option = webdriver.ChromeOptions()
  39. option.add_argument('disable-infobars')
  40. self.driver = webdriver.Chrome(chrome_options=option)
  41. log1.info('打开chrome浏览器')
  42. elif browser == 'firefox':
  43. self.driver = webdriver.Firefox()
  44. log1.info('打开firefox浏览器')
  45. else:
  46. log1.error('浏览器配置有误,应为chrome或firefox')
  47. self.driver.get(url)
  48. log1.info('访问url')
  49. self.driver.maximize_window()
  50. log1.info('浏览器最大化')
  51. self.driver.implicitly_wait(10)
  52. log1.info('设置静态等待时间10秒')
  53. return self.driver
  54. except BaseException:
  55. log1.error('浏览器打开报错', exc_info=1)
  56. def get_element(self, selector):
  57. """定位元素"""
  58. by = selector[0]
  59. value = selector[1]
  60. bys = ['id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath']
  61. element = None
  62. if by in bys:
  63. try:
  64. if by == 'id':
  65. element = self.driver.find_element_by_id(value)
  66. elif by == 'name':
  67. element = self.driver.find_element_by_name(value)
  68. elif by == 'class':
  69. element = self.driver.find_element_by_class_name(value)
  70. elif by == 'tag':
  71. element = self.driver.find_element_by_tag_name(value)
  72. elif by == 'link':
  73. element = self.driver.find_element_by_link_text(value)
  74. elif by == 'plink':
  75. element = self.driver.find_element_by_partial_link_text(value)
  76. elif by == 'css':
  77. element = self.driver.find_element_by_css_selector(value)
  78. elif by == 'xpath':
  79. element = self.driver.find_element_by_xpath(value)
  80. log1.info('元素定位成功。定位方式:%s,使用的值:%s' % (by, value))
  81. return element
  82. except NoSuchElementException:
  83. log1.error('没有定位到元素,定位方式:%s,使用的值:%s' % (by, value), exc_info=1)
  84. else:
  85. log1.error('元素定位方式错误,请使用id,name,class,tag,link,plink,css,xpath为定位方式参数')
  86. @staticmethod
  87. def isdisplayed(element):
  88. """元素是否存在"""
  89. value = element.is_displayed()
  90. return value
  91. def type(self, selector, value):
  92. """往输入框输入内容"""
  93. element = self.get_element(selector)
  94. element.clear()
  95. # noinspection PyBroadException
  96. try:
  97. element.send_keys(value)
  98. log1.info('输入的内容:%s' % value)
  99. except BaseException:
  100. log1.error('内容输入报错', exc_info=1)
  101. self.get_img()
  102. def click(self, selector):
  103. """点击元素"""
  104. element = self.get_element(selector)
  105. # noinspection PyBroadException
  106. try:
  107. element.click()
  108. log1.info('点击元素成功')
  109. except BaseException:
  110. isdisplay = self.isdisplayed(element)
  111. if isdisplay is True:
  112. self.my_sleep(3)
  113. element.click()
  114. log1.info('点击元素成功')
  115. else:
  116. log1.error('点击元素报错', exc_info=1)
  117. @staticmethod
  118. def my_sleep(secondes):
  119. """强制等待"""
  120. time.sleep(secondes)
  121. log1.info('强制等待%d秒' % secondes)
  122. def get_title(self):
  123. """获取title"""
  124. title = self.driver.title
  125. log1.info('当前打开的title是:%s' % title)
  126. return title
  127. def get_text(self, selector):
  128. """获取text"""
  129. element = self.get_element(selector)
  130. text = element.text
  131. log1.info("获取的text:%s" % text)
  132. return text
  133. def use_js(self, js):
  134. """调用js"""
  135. # noinspection PyBroadException
  136. try:
  137. self.driver.execute_script(js)
  138. log1.info('js执行成功,js内容为:%s' % js)
  139. except BaseException:
  140. log1.error('js执行报错', exc_info=1)
  141. def switch_menue(self, parentelement, secelement, targetelement):
  142. """三级菜单切换"""
  143. self.my_sleep(3)
  144. # noinspection PyBroadException
  145. try:
  146. self.driver.switch_to_default_content()
  147. self.click(parentelement)
  148. log1.info('成功点击一级菜单:%s' % parentelement)
  149. self.click(secelement)
  150. log1.info('成功点击二级菜单:%s' % secelement)
  151. self.click(targetelement)
  152. log1.info('成功点击三级菜单:%s' % targetelement)
  153. except BaseException:
  154. log1.error('切换菜单报错', exc_info=1)
  155. def switch_ifarme(self, selector):
  156. """切换farm"""
  157. element = self.get_element(selector)
  158. # noinspection PyBroadException
  159. try:
  160. self.driver.switch_to.frame(element)
  161. log1.info('切换frame成功')
  162. except BaseException:
  163. log1.error('切换frame报错', exc_info=1)
  164. def get_handle(self):
  165. """获得当前handle"""
  166. handle = self.driver.current_window_handle
  167. return handle
  168. def chage_handle(self, handle):
  169. """切换窗口"""
  170. handles = self.driver.window_handles
  171. for i in handles:
  172. if i != handle:
  173. self.driver.switch_to_window(i)
  174. def dr_quit(self):
  175. self.driver.quit()

2.对LOG日志类也进行封装log.py

  1. def get_log(logger_name):
  2. # 获取项目的根目录
  3. project_path = test_123.getcwd.get_cwd()
  4. Logs_path = os.path.join(project_path, 'Logs')
  5. # 获取本地时间,转为年-月-日格式
  6. local_date = time.strftime('%Y-%m-%d', time.localtime(time.time()))
  7. # 日期文件夹路径
  8. date_file_path = os.path.join(Logs_path, local_date)
  9. # 如果没有日期文件夹,创建该文件夹
  10. if not os.path.exists(date_file_path):
  11. os.makedirs(date_file_path)
  12. # 完整日志存放路径
  13. all_log_path = os.path.join(date_file_path, 'All_Logs/')
  14. # 如果没有完整日志文件夹,创建该文件夹
  15. if not os.path.exists(all_log_path):
  16. os.makedirs(all_log_path)
  17. # 错误日志存放路径
  18. error_log_path = os.path.join(date_file_path, 'Error_Logs/')
  19. # 如果没有错误日志文件夹,创建该文件夹
  20. if not os.path.exists(error_log_path):
  21. os.makedirs(error_log_path)
  22. # 获取本地时间,转为年月日时分秒格式
  23. local_time = time.strftime('%Y-%m-%d %H%M%S', time.localtime(time.time()))
  24. # 设置日志文件名
  25. all_log_name = all_log_path + local_time + '.log'
  26. error_log_name = error_log_path + local_time + '.log'
  27. # 创建一个logger
  28. logger = logging.getLogger(logger_name)
  29. logger.setLevel(logging.INFO)
  30. # 创建handler
  31. # 创建一个handler写入所有日志
  32. fh = logging.FileHandler(all_log_name)
  33. fh.setLevel(logging.INFO)
  34. # 创建一个handler写入错误日志
  35. eh = logging.FileHandler(error_log_name)
  36. eh.setLevel(logging.ERROR)
  37. # 创建一个handler输出到控制台
  38. ch = logging.StreamHandler()
  39. ch.setLevel(logging.INFO)
  40. # 定义日志输出格式
  41. # 以时间-日志器名称-日志级别-日志内容的形式展示
  42. all_log_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  43. # 以时间-日志器名称-日志级别-文件名-函数行号-错误内容
  44. error_log_formatter = logging.Formatter(
  45. '%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(lineno)s - %(message)s')
  46. # 将定义好的输出形式添加到handler
  47. fh.setFormatter(all_log_formatter)
  48. ch.setFormatter(all_log_formatter)
  49. eh.setFormatter(error_log_formatter)
  50. # 给logger添加handler
  51. logger.addHandler(fh)
  52. logger.addHandler(eh)
  53. logger.addHandler(ch)
  54. return logger
  55. log1 = get_log('selenium')

3.POM下简单的元素界面

  1. from test_123.Common.basePage import BasePage
  2. class HomePage(BasePage):
  3. """51"""
  4. qydl = ['id', 'qydl']
  5. txtent_userName=['id', 'txtent_userName']
  6. txtent_userPwd=['id','txtent_userPwd']
  7. imgbtnuserLogin=['id','imgbtnuserLogin']
  8. spanError=['id','spanError']
  9. def login_click(self, value):
  10. """输入账号"""
  11. self.click(self.qydl)
  12. self.click(self.txtent_userName)
  13. self.type(self.txtent_userName,value)
  14. def login1_click(self, value):
  15. '''输入密码'''
  16. self.click(self.txtent_userPwd)
  17. self.type(self.txtent_userPwd,value)
  18. self.click(self.imgbtnuserLogin)
  19. ssf=self.get_text(self.spanError)
  20. print(ssf)

4.测试集合的用例管理

 

  1. import unittest
  2. from test_123.Common.basePage import BasePage
  3. from test_123.PageObject.homePage import HomePage
  4. from test_123.Common.log import log1
  5. from test_123.Common.HTMLTestRunner import *
  6. class TestHome(unittest.TestCase):
  7. """测试主页面"""
  8. def setUp(self):
  9. browser = BasePage(self)
  10. self.driver = browser.open_browser()
  11. def test_login(self):
  12. """测试搜索"""
  13. case_name = '测试搜索'
  14. log1.info("执行测试用例:%s" % case_name)
  15. home = HomePage(self.driver)
  16. home.my_sleep(2)
  17. title=home.login_click('123456')
  18. title1=home.login1_click('123456')
  19. def tearDown(self):
  20. home = HomePage(self.driver)
  21. home.dr_quit()

5.对用例进行集合输出报告

调用HtmlTestRuuner进行报告:

entrance.py

  1. import test_123.Common.HTMLTestRunner
  2. import unittest
  3. import logging
  4. from time import strftime, localtime, time
  5. from test_123.TestSuites.testHome import TestHome
  6. suite = unittest.TestSuite()
  7. # 获取TestSuite的实例对象
  8. suite.addTest(TestHome('test_login'))
  9. # 把测试用例添加到测试容器中
  10. now = strftime("%Y-%m-%d-%H_%M_%S", localtime(time()))
  11. # 获取当前时间
  12. filename = now + "test.html"
  13. # 文件名
  14. fp = open(filename, "wb")
  15. # 以二进制的方式打开文件并写入结果
  16. runner = test_123.Common.HTMLTestRunner.HTMLTestRunner(
  17. stream=fp,
  18. verbosity=2,
  19. title="51.test",
  20. description="测试报告的详情")
  21. runner.run(suite)
  22. fp.close()
  23. log_format = '%(asctime)s - %(levelname)s - %(message)s'
  24. logging.basicConfig(filename="server.log", filemode='a+', format=log_format, level=logging.DEBUG)

6.当用例进行了测试后,对测试用例发送到自己邮箱,这个在搭建在Jenkins上时就可以定时看报告

  1. #!/usr/bin/python3
  2. import os
  3. import time
  4. import smtplib
  5. from email.mime.application import MIMEApplication
  6. from email.mime.multipart import MIMEMultipart
  7. from email.mime.text import MIMEText
  8. from test_123.entrance import filename
  9. import test_123.getcwd
  10. from test_123.Common.config import Config
  11. from test_123.Common.log import log1
  12. config = Config()
  13. #rq = time.strftime('%Y%m%d', time.localtime(time.time())) # 获取本地时间 转换成日期
  14. my_sender = config.config_read('sender', 'email') # 发件人邮箱账号
  15. my_pass = config.config_read('sender', 'password') # 发件人邮箱密码
  16. usernmae = config.config_read('sender', 'username') # 发件人姓名 #
  17. my_user = config.config_read('addressed','heemail') # 收件人邮箱
  18. path = test_123.getcwd.get_cwd()
  19. file = 'E:\\untitled\\test_123\\Common\\'+ filename#附件路径
  20. def mail():
  21. ret = True
  22. try:
  23. # 构造一个邮件体:正文 附件
  24. msg = MIMEMultipart()
  25. msg['Subject'] = "51测试" # 主题
  26. msg['From'] = my_sender # 发件人
  27. msg['To'] = my_user # 收件人
  28. # 构建正文
  29. part_text = MIMEText("这个是UI测试,HTMLtextrunner测试报告")
  30. msg.attach(part_text) # 把正文加到邮件体里面去
  31. # 构建邮件附件
  32. # file = file #获取文件路径
  33. part_attach1 = MIMEApplication(open(file, 'rb').read()) # 打开附件
  34. part_attach1.add_header('Content-Disposition', 'attachment', filename=file) # 为附件命名
  35. msg.attach(part_attach1) # 添加附件
  36. server = smtplib.SMTP_SSL("smtp.qq.com", 465) # 发件人邮箱中的SMTP服务器,设置端口是465
  37. server.login(my_sender, my_pass) # 括号中对应的是发件人邮箱账号、邮箱密码
  38. server.sendmail(my_sender, [my_user, ], msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
  39. server.quit() # 关闭连接
  40. except Exception: # 如果 try 中的语句没有执行,则会执行下面的 ret=False
  41. ret = False
  42. return ret
  43. ret = mail()
  44. if ret:
  45. print("邮件发送成功")
  46. else:
  47. print("邮件发送失败件")

到这里就简单介绍了一下过程,水平不足,可能说得不太明白

 

如果大家需要的话,可以找我要一下全部源码



所属网站分类: 技术文章 > 博客

作者:喵喵喵

链接: https://www.pythonheidong.com/blog/article/469022/

来源: python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

0 0
收藏该文
已收藏

评论内容:(最多支持255个字符)