目录
在讲解PO模型之前先给大家巩固下selenium与logger,代码附在了最后
一、selenium:
1.定位:
webdriver提供了18种(注意是18种,不是8种)的元素定位方法,前面8种是通过元素的属性来直接定位的,后面的xpath和css定位更加灵活,需要重点掌握其中一个。前八种是大家都熟悉的,经常会用到的:
1.id定位:find_element_by_id(self, id_)
2.name定位:find_element_by_name(self, name)
3.class定位:find_element_by_class_name(self, name)
4.tag定位:find_element_by_tag_name(self, name)
5.link定位:find_element_by_link_text(self, link_text)
6.partial_link定位find_element_by_partial_link_text(self, link_text)
7.xpath定位:find_element_by_xpath(self, xpath)
8.css定位:find_element_by_css_selector(self, css_selector)
9.id复数定位find_elements_by_id(self, id_)
10.name复数定位find_elements_by_name(self, name)
11.class复数定位find_elements_by_class_name(self, name)
12.tag复数定位find_elements_by_tag_name(self, name)
13.link复数定位find_elements_by_link_text(self, text)
14.partial_link复数定位find_elements_by_partial_link_text(self, link_text)
15.xpath复数定位find_elements_by_xpath(self, xpath)
16.css复数定位find_elements_by_css_selector(self, css_selector
17.find_element(self, by='id', value=None)
18.find_elements(self, by='id', value=None)
2.加载url
driver.get(url)
3.输入
find_element(self,loc).send_keys(text)
4.点击
find_element(self,loc).click()
5.清除
find_element(self,loc).clear()
6.获取文本内容
find_element(self,loc).text
7.获取属性
find_element(self,loc).get_attribute(name)
8.切换/窗口切换
8.1Frame切换
切换到frame
wd.switch_to.frame(frame_reference)
切回原来的主html
wd.switch_to.default_content()
8.2窗口切换:
wd.switch_to.window(handle)
9.等待
timd.sleep(固定等待)
implicitly_wait(隐式等待)
WebDriverWait(显示等待)
#等待元素可见
WebDriverWait(self.driver,timeout,poll_frequency).until(EC.visibility_of_element_located((By.XPATH,loc)))
#等待元素不可见
WebDriverWait(self.driver,timeout,poll_frequency).until_not(EC.visibility_of_element_located((By.XPATH,loc)))
二、logging模块简介
logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比print,具备如下优点:
可以通过设置不同的日志等级,在release版本中只输出重要信息,而不必显示大量的调试信息;print将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据;logging则可以由开发者决定将信息输出到什么地方,以及怎么输出;
尽管可以在Python代码中配置logging,但是这样并不够灵活,最好的方法是使用一个配置文件来配置。在Python 2.7及以后的版本中,可以从字典中加载logging配置,也就意味着可以通过文件加载日志的配置。
然后通过logging.config.fileConfig(filename)来调用写好的配置文件,运行可以看到调用正常
三、什么是PO?
1.简介
在自动化中,Selenium自动化测试中有一个名字经常被提及PageObject(思想与面向对象的特征相同),通常PO模型可以大大提高测试用例的维护效率,页面对象模型(PO)是一种设计模式,用来管理维护一组页面元素的对象库.在PO下,应用程序的每一个页面都有一个对应的Page类.每一个Page类维护着该页面的元素集和操作这些元素的方法.怎么设计PO?
2.设计的原则
1.抽象每一个页面
2.页面中元素不暴露,仅报错操作元素的方法
3.页面不应该有繁琐的继承关系
4.页面中不是所有元素都需要涉及到,核型业务元素做建模使用
5.把页面划分功能模块,在Page中实现这些功能方法
3.PO模型的实现
专业介绍完毕,但是没接触过的小伙伴看到这些俗不可耐的介绍肯定会头蒙的,下面来跟我一起有效探索PO模型吧,本文不讲基础,只讲解思想与实现,基础还需要各位自己巩固。
我所理解的PO模型就是将一个完整的代码划分模块然后分块管理,我这边主要划分为底层封装(关键),配置文件,数据管理,输出,页面操作相关,测试用例等几个模块
详细划分如下:
下面看下对selenium封装的一个实现,
使用logger进行一个log打印,打印完之后进行元素的查找,查找完毕后打印日志表示查找成功,然后进行输入操作,若操作失败则截图保存到对应路径中,
截图代码如下,
页面操作文件(.py)
四、代码
4.1Logger
#log.conf [loggers] keys=root,file,fileAndConsole [handlers] keys=fileHandler,consoleHandler [formatters] keys=simpleFormatter [logger_root] level=DEBUG handlers=consoleHandler [logger_file] level=DEBUG handlers=fileHandler qualname=file propagate=1 [logger_fileAndConsole] level=DEBUG handlers=fileHandler,consoleHandler qualname=fileAndConsole propagate=0 [handler_fileHandler] class=FileHandler args=(".\\OutPuts\\Log\\_log.log",'a','utf-8') level=DEBUG formatter=simpleFormatter [handler_consoleHandler] class=StreamHandler args=(sys.stdout,) level=DEBUG formatter=simpleFormatter [formatter_simpleFormatter] format=%(asctime)s %(filename)s %(levelname)s %(message)s
#define_log.py import logging import logging.config from os import path from BasePage.global_param import conf_log #调用logging 配置文件 并打印log class DefineLog: def setLoger(self): print(conf_log) #读取配置文件中的内容 logging.config.fileConfig(conf_log) #选择模式输出到控制台和文件中 logger = logging.getLogger('fileAndConsole') return logger if __name__ == '__main__': de = DefineLog() logger = de.setLoger() #正常输出log信息 logger.info('info') logger.debug('debug')
4.2Base_Page
#Base_Page import time from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from BasePage.define_log import DefineLog from BasePage.global_param import img_path #基础页面操作配置 如点击、查找元素、输入。。。 class BasePage: def __init__(self,driver): self.driver = driver self.defineLog = DefineLog()# fileHandler,consoleHandler self.logger = self.defineLog.setLoger() #打开对应的url def open_url(self,url): self.driver.get(url) #等待元素可见 def wait_element_visible(self,loc,timeout=150,poll_frequency=0.5,model=None): self.logger.info('{}--等待元素可见--{}'.format(model,loc)) print(2.2) try: start = time.time() WebDriverWait(self.driver,timeout,poll_frequency).until(EC.visibility_of_element_located((By.XPATH,loc))) end = time.time() print('等待时长:%.2f 秒' % (end - start)) except: self.save_webImage(model) raise #等待一个元素不可见 def wait_element_no_visible(self,loc,timeout=7,poll_frequency=0.5,model=None): """ :param loc: 元素定位表达(定位元素类型,元素定位方法) :param timeout: 等待的上限 :param poll_frequency: 轮询频率 :param model: 等待失败时截图操作 :return: None """ print('{}--等待元素不可见:{}'.format(model,loc)) try: start = time.time() WebDriverWait(self.driver,timeout,poll_frequency).until_not(EC.visibility_of_element_located((By.XPATH,loc))) end = time.time() print('等待时长:%.2f 秒'%(end-start)) except: print('{}等待元素不可见失败:{}'.format(model,loc)) #截图 self.save_webImage(model) raise #查找一个元素element def find_elements(self,loc,model=None): self.logger.info('{}--等待元素可见--{}'.format(model,loc)) try: return self.driver.find_element(By.XPATH,*loc) except: print('查找元素失败') #截图 self.save_webImage(model) raise #输入操作 def input_text(self,loc,text,model=None): #查找元素 element = self.driver.find_element(By.XPATH,loc) #打印日志 self.logger.info('{}在元素{}中输入文本:{}'.format(model,loc,text)) try: #进行输入操作 element.send_keys(text) except: print('输入操作失败') #若操作失败后截图 self.save_webImage(model) raise def send_key(self,key): ActionChains(self.driver).send_keys(key).perform() #点击操作 def click_element(self,loc,model=None): #先查找元素在点击 element = self.driver.find_element(By.XPATH,loc) #点击操作 self.logger.info('{}在元素{}中点击'.format(model, loc)) try: element.click() except: print('点击操作失败') #截图 self.save_webImage(model) raise #清除操作 def clean_text(self,loc,model=None): element = self.find_element(By.XPATH,loc) #清除操作 self.logger.info('{}在元素{}中清除'.format(model,loc)) try: element.clear() except: print('清除失败') #截图 self.save_webImage(model) raise # 获取文本内容 def get_text(self, loc, model=None): # 先查找元素在获取文本内容 ele = self.find_element(By.XPATH,loc) # 获取文本 self.logger.info('{} 在元素 {} 中获取文本'.format(model, loc)) try: text = ele.text print('{} 元素 {} 的文本内容为 {}'.format(model, loc, text)) return text except: print('获取元素 {} 的文本内容失败,报错信息如下:'.format(loc)) # 截图 self.save_webImgs(model) raise # 获取属性值 def get_element_attribute(self, loc, name,model=None): # 先查找元素在去获取属性值 ele = self.find_element(By.XPATH,loc) # 获取元素属性值 self.logger.info('{} 在元素 {} 中获取属性值'.format(model, loc)) try: ele_attribute = ele.get_attribute(name) print('{} 元素 {} 的文本内容为 {}'.format(model, loc, ele_attribute)) return ele_attribute except: print('获取元素 {} 的属性值失败,报错信息如下:'.format(loc)) self.save_webImgs(model) raise #截图 def save_webImage(self,model=None): #filepath:图片保存目录/model(页面功能名称)_当前时间到秒.png filePath ='{}{}.png'.format(img_path,model) print(filePath) try: self.driver.save_screenshot(filePath) print('截图成功,图片路径为{}'.format(filePath)) except: print('截屏失败!')
4.3报告
#run.py import unittest from BasePage.global_param import test_case_path,report_name from HtmlTestRunner import HTMLTestRunner """运行文件""" if __name__ == '__main__': discover = unittest.defaultTestLoader.discover(r"./",pattern='test*.py') with open(report_name,'w') as f: runner =HTMLTestRunner(stream=f,report_title='test1',report_name='result.html',verbosity=2,descriptions='运行结果') runner.run(discover)