这套框架适合使用的场景:
1、测试数据不多
2、执行人员不需要会代码
3、看报告的时候要看执行详细结果
工程分为以下几部分:
1、公用方法包-Util
2、需要调用的固定变量包-ProjectVar
3、元素路径目录-Conf
4、页面元素常用动作方法+模块动作方法包-Action
5、测试用例执行包-TestUnittest
6、截图目录
看一下目录组成结构:
- 1.公用方法包-Util
- 1.1 DirAndFile.py
- 这个模块是为了创建目录用的
#encoding=utf-8
import os
from ProjectVar.Var import *
def createDir(path,dirName):
#os.path.join(x,y)是拼接路径用的
dirPath=os.path.join(path,dirName)
#判断路径是否存在,存在则pass,否则新建
if os.path.exists(dirPath):
return dirPath
pass
else:
os.mkdir(dirPath)
return dirPath
- 1.2Excel.py
- 这个模块封装了excel的常用操作方法
#encoding=utf-8
from openpyxl import Workbook
from openpyxl import load_workbook
from ProjectVar.Var import *
from openpyxl.styles import Border,Side,Font
class Excel(object):
def __init__(self):
self.font=Font(color=None)
self.colorDict={'red':'FFFF3030','green':'FF008B00'}
self.wb=load_workbook(test_path)
self.ws=self.wb.active
def rename(self,new_name):
#给表格重命名
self.ws.title=new_name
self.wb.save(test_path)
def GetSheetName(self):
#获取所有表格名称
return self.wb.get_sheet_names()
def GetSheetByName(self,sheet_name):
#通过表格名称获取表格
self.ws=self.wb.get_sheet_by_name(sheet_name)
return self.ws
def GetCurrentSheetName(self):
#获取当前表格名称
return self.ws.title
def GetCellContent(self,row_num,col_num):
#获取单元格内容
return self.ws.cell(row=row_num,column=col_num).value
def WriteCellContent(self,row_num,col_num,content):
#往指定的单元格里面写入内容
self.ws.cell(row=row_num,column=col_num).value=content
self.wb.save(test_path)
def GetMaxRow(self):
#获取最大行号
return self.ws.max_row
def GetMaxColumn(self):
#获取最大列号
return self.ws.max_column
其实本次框架中没有用到excel,但是我还是把他写上,方便大家使用;【对于数据的传递也可以使用excel来操作的】
- 1.3GetConf.py
- 这个模块是为了操作配置文件用的方法
#encoding=utf-8
import ConfigParser
from ProjectVar.Var import *
class ParsePageObjectRepositoryConfig(object):
def __init__(self):
self.cf=ConfigParser.ConfigParser()
self.cf.read(page_object_repository_path)
def getItemsFromSection(self,sectionName):
items=self.cf.items(sectionName)
return dict(items)
if __name__=='__main__':
#调试代码
p=ParsePageObjectRepositoryConfig()
print p.getItemsFromSection('126mail_login')
print p.getItemsFromSection('126mail_login')['loginpage.frame'].split('//')[1]
print type(p.getItemsFromSection('126mail_login')['loginpage.frame'].split('//')[1])
- 1.4log.py
- 打印日志用的(这里可以不用这个,因为HTML就可以用)
#encoding=utf-8
import logging
import logging.config
from ProjectVar.Var import *
import os
#读取日志的配置文件
logging.config.fileConfig(project_path+'\\Conf\\Logger.conf')
#选择一个日志格式
logger=logging.getLogger('example02')
def warning(message):
#打印warning级别的信息(日志级别较弱,最弱的是debug)
logger.warn(message)
def debug(message):
#打印debug级别的信息(日志信息级别最弱
logger.debug(message)
def info(message):
#打印info级别信息
logger.info(message)
def error(message):
#打印wornging级别信息
logger.error(message)
if __name__=='__main__':
a = project_path + '\\Conf\\Logger.conf'
print os.path.exists(a)
print a
logging.config.fileConfig(project_path + '\\Conf\\Logger.conf')
info('info level')
warning('warning level')
error('error level')
debug('debug level')
- 1.5ObjectMap.py
- 这个模块是获取页面元素的方法,直接返回要操作的元素,后面调用的时候只需要传递定位元素方法和路径就可以。
#encoding=utf-8
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.ui import Select
import time
def getElement(driver,locateType,locateExpression):
#获取页面单个元素
try:
wait=WebDriverWait(driver,10)
return wait.until(lambda x:x.find_element(locateType,locateExpression))
except Exception,e:
raise e
def getElements(driver,locateType,locateExpression):
#获取页面多个元素
try:
wait=WebDriverWait(driver,10)
return wait.until(lambda x:x.find_elements(locateType,locateExpression))
except Exception,e:
raise e
def getSelectElementWithIndex(driver,index_num):
#获取select下拉框元素---index
select_element=Select(driver.find_element_by_xpath('//select'))
#打印已选中的文本
print select_element.all_selected_options[0].text
return select_element.select_by_index(index_num)
def getSelectElementWithText(driver,text):
#获取select下拉框元素----text
select_element=Select(driver.find_element_by_xpath('//select'))
#打印已选中的文本
print select_element.all_selected_options[0].text
return select_element.select_by_visible_text(text)
def getSelectElementWithValue(driver,value):
#获取select下拉框元素---value
select_element=Select(driver.find_element_by_xpath('select'))
#打印已选中的文本
print select_element.all_selected_options[0].text
return select_element.select_by_value(value)
- 2 .需要调用的公共变量包-ProjectVar
- 2.1Var.py
- 这个模块里面是代码中用到的公用已知变量
#encoding=utf-8
import os
import time
#当前文件路径
file_path=__file__
#工程路径
#os.path.dirname(__file__)当前文件所在路径
project_path=os.path.dirname(os.path.dirname(__file__)).decode('utf-8')
page_object_repository_path=project_path+'//Conf//PageObjectRepository .ini'
url='http:\\www.126.com'
chrom="c:\\Python27\\chromedriver"
ie="c:\\Python27\\IEDriverServer"
firefox="c:\\Python27\\geckodriver"
- 3 . 元素路径目录-Conf
- 3.1PageObjectRepository .ini
- 里面都是页面元素路径的配置文件
[configparse操作配置文件的时候有坑]
[ini中的内容要全部小写,否则读取出来的时候会自动转换成小写,这样就会发生匹配不上的情况]
[126mail_login]
loginpage.frame=xpath>//iframe[@id='x-URS-iframe']
loginpage.username=xpath>//span[.='@126.com']//preceding-sibling::input
loginpage.password=xpath>//label[.='密码']//following-sibling::input[2]
loginpage.loginbutton=xpath>//a[@id='dologin']
[126mail_homepage]
home_age.addressbook=xpath>//div[text()='通讯录']
[126mail_addcontactspage]
addcontacts_page.create_contacts_btn=xpath>//header/div[@role='toolbar']/div[@class='nui-toolbar-item'][1]
addcontacts_page.contact_person_name=xpath>//a[@title='编辑详细姓名']/preceding-sibling::div/input
addcontacts_page.contact_person_email=xpath>//*[@id='iaddress_MAIL_wrap']//input
addcontacts_page.star_contacts=xpath>//span[text()='设为星标联系人']/preceding-sibling::span/b
addcontacts_page.contact_person_mobile=xpath>//*[@id='iaddress_TEL_wrap']//dd//input
addcontacts_page.contact_person_comment=xpath>//textarea
addcontacts_page.save_contace_person=xpath>//span[.='确 定']
- 4 .页面元素常用动作方法+模块动作方法包-Action
- 4.1basic_function.py
- 这个模块里面写的是页面操作的常用方法
#encoding=utf-8
from selenium import webdriver
from Util.ObjectMap import *
from ProjectVar.Var import *
from Util.DirAndFile import *
import traceback
import os
def open_browser(browserName,*arg):
#打开浏览器
try:
if browserName.lower()=='ie':
driver=webdriver.Ie(executable_path=ie)
return driver
elif browserName.lower()=='chrome':
driver=webdriver.Chrome(executable_path=chrom)
return driver
elif browserName.lower()=='firefox':
driver=webdriver.Firefox(executable_path=firefox)
return driver
else:
print u"has no such browser"
pass
except Exception,e:
raise e
def visit_url(driver,url,*arg):
#访问网页
try:
driver.get(url)
except Exception,e:
raise e
def close_browser(driver):
#退出浏览器
try:
driver.quit()
except Exception,e:
raise e
def enter_frame(driver,locatorType,locatorExpression,*arg):
#切换frame
try:
driver.switch_to.frame(getElement(driver,locatorType,locatorExpression))
except Exception,e:
raise e
def get_out_frame(driver):
#切出来 frame
try:
driver.switch_to_default_content()
except Exception,e:
raise e
def input_string(driver,locatorType,locatorExpression,content,*arg):
#send_keys and clear
try:
getElement(driver, locatorType, locatorExpression).clear()
pause(0.5)
getElement(driver,locatorType,locatorExpression).send_keys(content)
pause(0.5)
except Exception,e:
raise e
def click_button(driver,locatorType,locatorExpression):
#点击操作
try:
getElement(driver, locatorType, locatorExpression).click()
except Exception,e:
raise e
def assert_keyword(driver,excepted_word,*arg):
#断言
try:
assert True==(excepted_word in driver.page_source)
except AssertionError,e:
raise e
except Exception,e:
raise e
else:
print 'keyword : %s in page_source'%excepted_word
def pause(seconds,*arg):
time.sleep(float(seconds))
def max_window(driver):
#最大化窗口
try:
driver.maximize_window()
except Exception,e:
raise e
def get_element_out_to_can_see(driver,locatorType, locatorExpression,*arg):
#把元素拉倒可见的位置
try:
target = getElement(driver,locatorType, locatorExpression)
driver.execute_script("arguments[0].scrollIntoView();", target)
except Exception,e:
raise e
def scroll_page_to_buttom(driver):
#滚动条到最下方
try:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
except Exception,e:
raise e
def scroll_page_to_top(driver):
#滚动条到最上方
try:
driver.execute_script("window.scrollTo(0, 0);")
except Exception,e:
raise e
def capture_screen(driver,pictureName):
# 获取正常截图
dirPath=createDir(project_path+"//ScreenPictures//CapturePicture",time.strftime("%Y-%m-%d"))
os.chdir(dirPath)
try:
driver.get_screenshot_as_file(pictureName)
except Exception,e:
raise e
def error_screen(driver,pictureName):
# 获取异常截图
dirPath=createDir(project_path + "//ScreenPictures//ErrorPicture", time.strftime("%Y-%m-%d"))
os.chdir(dirPath)
try:
driver.get_screenshot_as_file(pictureName)
except Exception,e:
raise e
- 4.2 action_login.py
- 这个模块中写的是login的操作步骤方法
#encoding=utf-8
from Action.basic_function import *
def login(driver,usernameAndpassword,*arg):
username,password=usernameAndpassword.split('||')
visit_url(driver,url)
pause(2)
enter_frame(driver,"id", "x-URS-iframe")
pause(1)
input_string(driver,"xpath", "//span[.='@126.com']//preceding-sibling::input", username)
pause(1)
input_string(driver,"xpath", "//label[.='密码']//following-sibling::input[2]", password)
pause(1)
click_button(driver,"xpath", "//a[@id='dologin']")
- 4.3 action_addaddress.py
- 这个模块里面封装的是添加联系人的动作步骤
#encoding=utf-8
from Action.basic_function import *
driver=None
def add_address(driver,name,email,tel,comment,*arg):
click_button(driver,"xpath","//div[text()='通讯录']")
pause(2)
click_button(driver,"xpath","//header/div[@role='toolbar']/div[@class='nui-toolbar-item'][1]")
pause(2)
input_string(driver,"xpath","//a[@title='编辑详细姓名']/preceding-sibling::div/input",name)
pause(0.5)
input_string(driver,"xpath","//*[@id='iaddress_MAIL_wrap']//input",email)
pause(0.5)
input_string(driver,"xpath","//*[@id='iaddress_TEL_wrap']//dd//input",tel)
pause(0.5)
input_string(driver,"xpath","//textarea",comment)
pause(0.5)
click_button(driver,"xpath","//span[.='确 定']")
- 4.4 test_data.py
- 这个模块里面写的是用到的测试数据(所有用到的测试数据全在里面,和代码是完全分离的)
#encoding=utf-8
#login的测试数据
login_info=("lxxxx_xxxx||ainixxxxxxxxx","lxxxx_xxxx||ainixxxxxxx")
#login后的断言内容
login_keyword=u'退出'
#添加联系人测试数据
addressbook_info=[('ajin','[email protected]','18681867102','I am a beautiful girl ,I love my dad and mum!'),
('gangbeng','[email protected]','18689856963','I like meat !')]
#浏览器的选择
browser_name='Chrome'
- 5 .测试用例执行包-TestUnittest
- 5.1 login_unittest.py
#encoding=utf-8
from HTMLTestRunner import HTMLTestRunner
import unittest
from Action.action_login import *
from Action.test_data import *
class TestLogin(unittest.TestCase):
def setUp(self):
self.driver=open_browser(browser_name)
def test_login(self):
for i in range(len(login_info)):
try:
login(self.driver,login_info[i])
pause(3)
self.assertIn(login_keyword,self.driver.page_source,login_keyword+' not in page_source')
except Exception,e:
print 'login error, ' + login_keyword + 'in page_source can not be found !'
error_screen(self.driver,'login-'+login_keyword+time.strftime('%H%M%S')+'.png')
print traceback.format_exc()
else:
capture_screen(self.driver,'login-'+login_keyword+time.strftime('%H%M%S')+'.png')
print 'login success, '+login_keyword+'in page_source can be found !'
finally:
print u'login 第%d次用例执行结束'%(i+1)
pause(2)
def tearDown(self):
self.driver.quit()
if __name__=='__main__':
suite=unittest.TestSuite()
suite.addTest(TestLogin('test_login'))
with open('HTMLForLogin.html','w')as fp:
runner=HTMLTestRunner(stream=fp,title='login report',description='report',verbosity=2)
runner.run(suite)
- 5.2 addaddress_unittest.py
- 增加联系人测试执行模块
#encoding=utf-8
from HTMLTestRunner import HTMLTestRunner
import unittest
from Action.action_addaddress import *
from Action.action_login import *
from Action.test_data import *
from Action.test_data import *
class TestAddAdress(unittest.TestCase):
def setUp(self):
self.driver=open_browser(browser_name)
def test_addAddress(self):
try:
login(self.driver, login_info[0])
pause(2)
except Exception,e:
raise e
else:
print 'login success'
finally:
print 'next is addaddressbook'
for i in range(len(addressbook_info)):
try:
add_address(self.driver,addressbook_info[i][0],addressbook_info[i][1],addressbook_info[i][2],addressbook_info[i][3])
pause(2)
self.assertIn(addressbook_info[i][0],self.driver.page_source,addressbook_info[i][0]+'not in page_source')
except Exception,e:
print 'addaddress error, ' + addressbook_info[i][0] + 'in page_source can not be found !'
error_screen(self.driver,'addressbook-'+addressbook_info[i][0]+time.strftime('%H%M%S')+'.png')
print traceback.format_exc()
else:
capture_screen(self.driver,'addressbook-'+addressbook_info[i][0]+time.strftime('%H%M%S')+'.png')
print 'addaddress success, '+addressbook_info[i][0]+'in page_source can be found !'
finally:
print u'addaddress 第%d次用例执行结束'%(i+1)
pause(2)
continue
def tearDown(self):
self.driver.quit()
if __name__=='__main__':
suite=unittest.TestSuite()
suite.addTest(TestAddAdress('test_addAddress'))
with open('HTMLForAddAddress.html','w')as fp:
runner=HTMLTestRunner(stream=fp,title='addAddress report',description='report',verbosity=2)
runner.run(suite)
我这里没有再开一个模块,来专门的用unittest去集成他们,大家可以自己操作一下,很简单的!!
之前的1、2、3、4都是为了5的执行,将5中的两个测试脚本跑完之后,得到测试截图和测试报告:
以上的例子是用126邮箱登录创建联系人做的测试框架,同样的,在我们的项目中我也用了,还挺好用的,毕竟测试数据不多,这样写够了,但是觉得还是要改进下,后面改进了,会继续更新!!!