自动化搭建环境及基础理论
在dos命令中输入python,在dos命令中输入pip Pip是Python官方推荐的包管理工具,提供了对Python包的查找、下载、安装、卸载的功能,属于python的一部分。 Python3.0以上的版本都是自带pip的,无需再次下载安装。 如需升级pip,有一下两种方式,命令行中输入以下命令:
python -m pip install —upgrade pip 或 easy_install.exe pip,即可升级pip
使用pip安装第三方库,命令行中执行:
pip install xxx
xx 是我们需要安装库的名称。比如安装requests库
UI自动化搭建手册(配置第三方自动化测试工具):
- 安装python(3.6)最好安装到D盘,记得勾选添加环境变量(add..to path)
- 安装pycharm
- 安装selenium 2.53.6指selenium的版本(命令pip install selenium==2.53.6)
- 安装连接数据库工具的第三方包 pip install pymysql==0.9.3
- 安装pillow图像处理库 pip install pillow==5.4.1
- 安装ddt用来实现数据驱动的自动化工具 pip install ddt==1.2.0
- 安装xlrd库实现读写Excel文件 pip install xlrd==1.2.0
- 将HTMLTestRunner.py(用来生成自动化测试报告)文件复制到python的Lib目录(配置 文件目录)
pip命令:
Pip install 包名==版本号 安装第三方的库
Pip list 查看都安装了哪些第三方的库
pip uninstall 包名 卸载第三方库
pip download 包名****==****版本号
pip download ddt==1.2.0(下载ddt 1.2.0到本地)
UI自动化中
python
语法:
首先通过网页F12定位到我们需要操作的元素的源代码(通过元素的属性值来定位元素)
- from 第三方库名import驱动名从第三方库引入库里的驱动模块
from selenium import webdriver
import time
- 变量名****=驱动名#**驱动实例化
driver=webdriver.Firefox()
- 浏览器驱动****.get****(’网址’)****#****使用浏览器打开某网页
webdriver.Firefox.get(‘www.baidu.com’)
- 输入框使用****.send_keys(“输入的内容”)点击按钮使用.click()**
driver.find_element_by_id(‘zentao’).click()
driver.find_element_by_name(‘account’).send_keys(‘admin’)
- 通过页面元素的属性来定位页面元素的方法 语法:浏览器驱动.find_element_by_属性名(‘属性值’).click() (1)使用id定位
driver.find_element_by_link_text(‘开源版’).click()
(2)使用name定位
driver.find_element_by_name(‘password’).send_keys(‘123456’)
(3)使用文本属性来定位
link_text(”元素的文本内容”)
driver.find_element_by_link_text(‘开源版’).click()
(4)使用部分文本定位
partial_link_text(”元素的部分文本内容”) #
driver.find_element_by_partial_link_text(‘开源’).click()
(5)使用class_name类名来定位
driver.find_element_by_class_name(‘us_Submit’).click()
(6)使用xpath来定位 xpath是一个在xml文档里查找的语言 ①通过xpath从根节点/ 逐级定位到元素,需要通过火狐的FirePath插件找路径
driver.find_element_by_xpath(‘/html/body/div/div/div[1]/div/div/div[2]/a[1]’).click()
②通过xpath从任意节点//利用两个属性值@属性 and @属性 定位到元素,需要通过火狐的FirePath插件找路径
driver.find_element_by_xpath(‘//a[@target=“_self” and @href=“/zentao/“]’).click()
③通过xpath定位元素,xpath路径直接在火狐F12的HTML中右键单击需要的那个元素对应的代码,然后复制xpath
driver.find_element_by_xpath(‘//*[@id=“zentao”]’).click()
(7)使用css定位 CSS是一种语言,用来描述html和xml的表现,速度比xpath快 ①id定位用# (#id的属性值)
driver.find_element_by_css_selector(‘#modulemenu').click()
②class定位用. (.class的属性值)
driver.find_element_by_css_selector(‘.modulemenu’).click()
③通过href属性值定位用[] (“[href=’/zentao/’]”)
driver.find_element_by_css_selector(“[href=’/zentao/’]”).click()
driver.find_element_by_css_selector(‘[id="m“dulemenu"]”)’click()
④父子定位(使用较少)逐级定位
driver.find_element_by_css_selector('h‘ml>body>div>div>div.modal-content>div>div>div.col-xs-8>a#zentao')’click()
或者右击复制html中的CSS路径
driver.find_element_by_css_selector('h‘ml body.m-bug-browse header#header nav#mainmenu ul.nav li.active a.active').click()
(8)使用tag_name标签名定位(使用很少,因为标签一般不唯一)
driver.find_element_by_id('s‘bmit')’click()
案例一:
from selenium import webdriver
import time
url='h‘tp://192.168.2.2:81/'
‘river=webdriver.Firefox()
driver.get(url)
time.sleep(2) #等待时间设置为2秒
# driver.find_element_by_id('z‘ntao')’click()
# driver.find_element_by_link_text('开‘版')’click()
# driver.find_element_by_partial_link_text('开‘')’click()
#driver.find_element_by_xpath('/‘tml/body/div/div/div[1]/div/div/div[2]/a[1]').click()
time.sleep(2)
#driver.find_element_by_xpath('/‘a[@target="_self" and @href="/zentao/"]').click()
driver.find_element_by_xpath('/‘*[@id="z“ntao"]”)’click()
driver.find_element_by_name('a‘count')’send_keys('a‘min')’driver.find_element_by_name('p‘ssword')’send_keys('1‘3456')’# driver.find_element_by_tag_name('button').click()
driver.find_element_by_id('s‘bmit')’click()
time.sleep(5)
案例二:
from selenium import webdriver
import time
url='h‘tp://192.168.2.110/geeknet/user.php'
’river=webdriver.Firefox()
driver.get(url)
time.sleep(2)
driver.find_element_by_name('u‘ername')’send_keys('l‘e000000')’driver.find_element_by_name('p‘ssword')’send_keys('0‘0000')’time.sleep(2)
driver.find_element_by_class_name('u‘_Submit').click() #使用class属性定位
time.sleep(5)
driver.quit()
**6.最大化窗口**
driver.maximize_window()
**7.刷新页面**
driver.refresh()
**8.关闭当前窗口**
driver.close()
**9.关闭所有窗口****(****浏览器****)**
driver.quit()
案例:
from selenium import webdriver
import time
url1='h‘tp://192.168.2.2:81/'
‘rl2='h‘tp://192.168.2.110/geeknet/user.php'
’river=webdriver.Firefox()
driver.get(url1)
time.sleep(2)
driver.maximize_window()
time.sleep(2)
driver.refresh()
time.sleep(2)
driver=webdriver.Firefox()
driver.get(url2)
time.sleep(2)
driver.close()
**10.获取标签中的文本内容****.text**
a=driver.find_element_by_id('z‘ntao')’text
print('获‘文本内容为:',’)
**11.获取标签的属性值****.get_attribute('*‘**属性名****')’*
b=driver.find_element_by_xpath('/‘*[@id="a“count"]”)’get_attribute('n‘me')’print('n‘me的属性值为:%s'%’)
**12.判断一个元素是否可见(返回值为布尔型)**
c=driver.find_element_by_id('a‘count')’is_displayed()
print(c)
**13.获取元素的尺寸****(****单位****px****像素****) .size**
cc=driver.find_element_by_id('a‘count')’size
print(type(cc)) #查看账号框类型,会显示是字典类型
print(cc) #查看字典的字段名
print('输‘框高:%s,宽:%s'%’cc['h‘ight']’cc['w‘dth']’)
**14.获取元素的位置****(****以页面最左上角为原点****) .location**
loc=driver.find_element_by_id('s‘bmit')’location
print('登‘按钮横坐标为:%s,纵坐标为:%s'%’loc['x‘]’loc['y‘]’)
**15.清空输入框内容****.clear()**
driver.find_element_by_id('a‘count')’clear()
案例:
from selenium import webdriver
import time
url='h‘tp://192.168.2.2:81/'
‘river=webdriver.Firefox()
driver.get(url)
time.sleep(2)
a=driver.find_element_by_id('z‘ntao')’text
print('获‘文本内容为:',’)
a=driver.find_element_by_id('z‘ntao')’click()
time.sleep(1)
b=driver.find_element_by_xpath('/‘*[@id="a“count"]”)’get_attribute('n‘me')’print('n‘me的属性值为:%s'%’)
c=driver.find_element_by_id('a‘count')’is_displayed()
print(c)
cc=driver.find_element_by_id('a‘count')’size
print(type(cc))
print(cc)
print('输‘框高:%s,宽:%s'%’cc['h‘ight']’cc['w‘dth']’)
loc=driver.find_element_by_id('s‘bmit')’location
print(loc)
print('登‘按钮横坐标为:%s,纵坐标为:%s'%’loc['x‘]’loc['y‘]’)
driver.find_element_by_id('a‘count')’send_keys('a‘min')’time.sleep(2)
driver.find_element_by_id('a‘count')’clear()
driver.quit()
**16.匿名函数表达式**
lam=lambda a,b:a+b
cc=(6,9)
print(lam(cc[0],cc[1]))
#将元组中的元素全部分别赋值给lam匿名函数,需要元组中的元素与函数的元素对应
print(lam(*cc))
## ''‘’’
## ''‘’’**17.强制等待(主要在调试代码时使用)**
time.sleep(3)
**18.隐式等待****:**
设置的是一个全局等待。设置等待时间对页面中所有的元素设置加载时间,如果超出了设置的等待时间则会抛出异常。
隐式等待可以理解为在规定的时间内,浏览器不停地刷新页面,直到找到页面元素为止
driver.implicitly_wait(5)
**19.显式等待** **WebDriverWait().until()**
显示等待:针对单个特定的元素设置的等待,在设置的时间范围内,设置每隔一段时间(默认检测时间0.5秒)检测一次当前页面某个元素是否存在,如果在规定的时间内找到了这个元素,则直接执行下面操作(后边的代码)。如果超过了设置的时间还是检测不到元素则抛出异常。默认异常为:NoSuchElementException默认检测频率:0.5s
第一步分解:
(1)driver.find_element_by_id("z“ntao")”click()
(2)driver.find_element(By.ID,'z’ntao')’click()
(3)aa=driver.find_element_by_id("z“ntao")”aa.click()
(1)(2)(3)的结果是一样的
第二步分解:
①WebDriverWait(driver,5,0.5).until(lambda x:x.find_element_by_id('z‘ntao')’
#until可以将driver的值赋给x
②WebDriverWait(driver,5,0.5).until(lambda x:x.find_element(By.ID,'z’ntao')’
①和②的结果是一样的
第三步分解:
loc=(By.ID,'z’ntao') #将开源版元素的属性及值通过参数赋值到元组中
# *loc分别赋值,使用until函数将loc元组中的值分别赋值给变量w达到①的效果
WebDriverWait(driver,5,0.5).until(lambda w:w.find_element(*loc))
第四步分解:
#将以上操作重新封装为一个函数,函数名为findelement
def findelement(a):
ele=WebDriverWait(driver,5,0.5).until(lambda x:x.find_element(*a))
reReturnle #返回变量ele的值,代表定位到指定元素显示等待
第五步分解(最终结果):
#调用我们封装的函数findelement,当值为loc(元素的位置)时定位元素
def findelement(a):
ele=WebDriverWait(driver,5,0.5).until(lambda x:x.find_element(*a))
return ele
loc=(By.ID,'z’ntao') #元素在开源版代码中的属性名及属性值
findelement(loc).click() #使用我们定义的findelement函数在等待时间内定位元素并点击它
案例:
from selenium import webdriver
#从selenium库中引入By类(路径:selenium\webdriver\common\中有个by的文件,by文件中有个By类)
from selenium.webdriver.common.by import By
#从selenium库中引入WebDriverWait(显示等待)函数
from selenium.webdriver.support.wait import WebDriverWait
url='h‘tp://192.168.2.2:81/'
‘river=webdriver.Firefox()
driver.get(url)
def findelement(a):
ele=WebDriverWait(driver,5,0.5).until(lambda x:x.find_element(*a))
return ele
loc=(By.ID,'z’ntao')’
findelement(loc).click()
n=(By.ID,'a’count')’findelement(n).send_keys('a‘min')’p=(By.NAME,'p’ssword')’findelement(p).send_keys('1‘3456')’d=(By.ID,'s’bmit')’findelement(d).click()
driver.close()
**20. 窗口截图 (截取屏幕作为图片)**
**driver.get_screenshot_as_file(****‘*’**路径/图片重命名****’****)**
driver.get_screenshot_as_file(‘D:/zentao.png’)
**21. 上传文件 send_keys('文‘路径****\****文件名****')’*
driver.find_element_by_name("f“le")”send_keys('D‘\shuzhuang.jpg')’**22. 多表单切换(对不同表单对应不同网址时)switch_to.frame(****‘’’***)**
多表单切换,当源码中有frame时需要用到多表单切换
#frame默认选取表单的id或者name属性
# driver.switch_to.frame('t‘p')’# driver.find_element_by_id('zentao').click()
#下面需要换到另一个表单中进行操作,如果表单没有id和name属性,使用以下方法
aa=driver.find_element_by_css_selector('[‘rc="h“tp://192.168.2.2:81/"]“)’driver.switch_to.frame(aa)
driver.find_element_by_id('z‘ntao')’click()
#切换主文档
driver.switch_to.default_content() #切换到进入网址的初始内容
driver.switch_to.frame('b‘dy')’driver.find_element_by_xpath("/“tml/body/div/div/div/div/font/a")”click()
23. 对话框处理 案例:
from selenium import webdriver
import time
url='h‘tp://192.168.2.2:8080/alert/index.jsp'
’river=webdriver.Firefox()
driver.get(url)
time.sleep(2)
**#处理****alert****对话框(提示弹框)**
driver.find_element_by_xpath('h‘ml/body/div[1]/input[2]')’click()
time.sleep(2)
print(driver.switch_to.alert.text)
driver.switch_to.alert.accept()
time.sleep(2)
**#处理****conform****对话框**
driver.find_element_by_css_selector('[‘alue="确“弹窗按钮"]”)’click()
time.sleep(2)
**# 点击确定**
# driver.switch_to.alert.accept()
**#提取文本内容**
print(driver.switch_to.alert.text)
**# 点击取消**
driver.switch_to.alert.dismiss()
time.sleep(2)
**#处理****prompt****对话框****(****输入框弹框****)**
driver.find_element_by_xpath('h‘ml/body/div[1]/input[1]')’click()
print(driver.switch_to.alert.text)
time.sleep(2)
**#输入内容**
driver.switch_to.alert.send_keys('1‘)’time.sleep(2)
#点击确定
driver.switch_to.alert.accept()
time.sleep(1)
driver.close()
24. 时间控件处理(强制去除元素某属性并输入内容) 案例:
from selenium import webdriver
import time
url='h‘tp://192.168.2.2:8080/date/index.jsp'
’river=webdriver.Firefox()
driver.get(url)
#js即javascript js负责前端页面动作,css负责页面展示样式
#使用js来利用ID='d’mo1'来定位元素并去除标签中的readonly(只读)属性
js="d“cument.getElementById('d‘mo1')’removeAttribute('r‘adonly')’
”river.execute_script(js) #执行js脚本
#然后就可以输入了
driver.find_element_by_id('d‘mo1')’send_keys('2‘20-5-12')’
25. 控制条移动(通过控制窗口的位置) 案例
from selenium import webdriver
import time
''‘’’滚动条移动''’’’rl='h‘tp://192.168.2.110/geeknet/user.php'
’river=webdriver.Firefox()
driver.get(url)
time.sleep(2)
#设置窗口大小
driver.set_window_size(600,600)
time.sleep(2)
#将滚动条定位到原点向右200px,原点向下400px
js='w‘ndow.scrollTo(200,400)'
’river.execute_script(js)
time.sleep(2)
#将滚动条定位到原点向右200px,原点向下600px
js1='w‘ndow.scrollTo(200,600)'
’river.execute_script(js1)
26. 下拉列表、分页处理
#引入****selenium****库中****select****文件中的****Select****类**
from selenium.webdriver.support.select import Select
#通过源码****value****的值选择**
loc1=driver.find_element_by_id('s‘Id') #定位下拉列表框
Select(loc1).select_by_value('o‘')’time.sleep(2)
#通过下拉列表中标签的文本内容选择**
loc2=driver.find_element_by_id('s‘Id')’Select(loc2).select_by_visible_text('河‘')’
案例
from selenium import webdriver
import time
from selenium.webdriver.support.select import Select
url='h‘tp://192.168.2.2:8080/select/index.jsp'
’river=webdriver.Firefox()
driver.get(url)
time.sleep(2)
driver.maximize_window()
time.sleep(1)
Select(driver.find_element_by_id('s‘Id')’.select_by_visible_text('橘‘')’time.sleep(1)
Select(driver.find_element_by_id('s‘Id')’.select_by_value('o‘')’time.sleep(1)
Select(driver.find_element_by_id('s‘Id')’.select_by_value('2’')’time.sleep(1)
Select(driver.find_element_by_id('s‘Id')’.select_by_value('o‘val')’time.sleep(1)
Select(driver.find_element_by_id('p‘geElm_a74e_ce2c')’.select_by_value('2‘)’time.sleep(1)
Select(driver.find_element_by_id('s‘')’.select_by_value('5’')’time.sleep(1)
driver.close()
27. 部分截图(通过截图的左上角右下角坐标切割图片) 先截图,然后在图片上通过页面中元素的位置(横纵坐标)截图 案例
from selenium import webdriver
import time
#引入PIL库(图片处理)中的Image类
from PIL import Image
url='h‘tp://192.168.2.2:8080/bos/login.jsp'
’river=webdriver.Firefox()
driver.get(url)
time.sleep(2)
#先截图保存下来
driver.get_screenshot_as_file('b‘s.png')’#获取图片的左上角坐标并赋值给对象loc
loc=driver.find_element_by_id('log‘nform:vCode').l’cation
print(loc)
#获取图片(元素)尺寸
size=driver.find_element_by_id('log‘nform:vCode').s’ze
print(size)
x=loc['x']‘y’loc['y']‘x’=loc['x']‘s’ze['wid‘h']
y’=loc['y']‘s’ze['hei‘ht']
’打开图片
a=Image.open('bos.p‘g')
#将’上右下的坐标放入一个元组b中
b=(x,y,xx,yy)
#裁切
im=a.crop(b)
#保存
im.save('code.‘ng')
#即’mage.open(‘bos.png’).crop(b).save(‘code.png’)
28. 验证码的五种处理方式 (1)通过cookie获取验证码案例
import time
from selenium import webdriver
url='http:‘/192.168.2.110/geeknet/user.php'
driv’r=webdriver.Firefox()
driver.get(url)
time.sleep(1)
driver.find_element_by_name('usern‘me').sen’_keys('test0‘1')
tim’.sleep(1)
driver.find_element_by_name('passw‘rd').sen’_keys('test0‘1')
tim’.sleep(1)
driver.find_element_by_id('remem‘er').cli’k()
driver.find_element_by_class_name('us_Su‘mit').cli’k()
#获取登录的cookie
cookie=driver.get_cookies()
driver.close()
#使用获取到的cookie重新打开一个网页
url2='http:‘/192.168.2.110/geeknet/user.php'
driv’r=webdriver.Firefox()
driver.get(url2)
time.sleep(2)
driver.maximize_window()
for i in cIokie:
driver.add_cookie(i)
#刷新页面
driver.refresh()
**(2)数据库查询出验证码**
**(3)去掉(注释掉)验证码**
**(4)设置万能验证码 如:****9527**
**(5)通过****OCR****(光学字符识别)技术**
29. 单元测试框架及测试集合 '''单元测’’’unittest 1.类名随便起,类要继承unittest.TestCase,name前后的__下划线是两个 2.测试用例必须以test开头,测试用例的执行顺序是按照26个英文字母以及阿拉伯数字 3.在执行整个脚本的时候要把光标放在if __name上边否则是以单元测试框架的形式运行的 4.鼠标放在类的:后边代表以单元测试框架形式运行所有的测试用例 5.setUp代表预操作(即一部分需要重复利用的代码,前置条件那些代码) 6.tearDown代表最后一步操作,一般都是关闭浏览器'''
’’’ort unittest
class suit(unittest.TestCase):
def setUp(self):
print("测试开始"“
”def test_001(self):
print("执行tes“001--case—
”def test_002(self):
print("执行tes“002--case—
”def test_003(self):
print("执行tes“003--case—
”def tearDown(self):
print("测试结束"“
if ”_name__ =="__mai“__":
” '''执行类‘’’的用例'''
’ # unittest.main() #使用主函数执行所有的测试用例
'''通过建‘’’执行类中的部分用例'''
’ su=unittest.TestSuite() #建立测试集合
su.addTest(suit('test_‘01')) #向测试集合里添加suit类中对应的第一条测试用例
su.addTest(suit('test_‘03'))
’ runner=unittest.TextTestRunner() #生成执行器
runner.run(su) #执行测试集合
30. 以测试报告形式来执行测试集合
#引用unittest类和time类
import unittest,time
#从HTMLTestRunner文件中引入HTMLTestRunner类
from HTMLTestRunner import HTMLTestRunner
class suit(unittest.TestCase):
def setUp(self):
print("测试开始"“
”def test_001(self):
print("执行tes“001--case—
”def test_002(self):
print("执行tes“002--case—
”def test_003(self):
print("执行tes“003--case—
”def tearDown(self):
print("测试结束"“
if ”_name__ =="__mai“__":
” su=unittest.TestSuite() #建立测试集合
su.addTest(suit('test_‘01')) #向测试集合里添加suit类中对应的第一条测试用例
su.addTest(suit('test_‘03'))
’ #description描述 stream数据流 w(写入方式)b(二进制),wb即以二进制方式写入
now=time.strftime('%Y-%m‘%d %H-%M-%S') #使用当前时间并格式化时间为年月日时分秒
fp=open('../re‘ort/'+now+'report.html','wb') #'../report/'+now+'report.html'通过+组合成一个指定路径的文件
runner=HTMLTestRunner(stream=fp,title='自动化测试‘告',desc’iption='用例描述'‘
’ runner.run(su)
fp.close()
31. 以测试报告的形式输出
from selenium import webdriver
from HTMLTestRunner import HTMLTestRunner
import time
import unittest
url='http:‘/192.168.2.110/geeknet/user.php'
clas’ Test_Login(unittest.TestCase):
def setUp(self):
self.driver=webdriver.Firefox()
self.driver.get(url)
time.sleep(1)
def test_login(self):
self.driver.find_element_by_name("usern“me").sen”_keys('bbb')‘ ’ self.driver.find_element_by_name("passw“rd").sen”_keys('01234‘6')
’ self.driver.find_element_by_id("remem“er").cli”k()
time.sleep(1)
self.driver.find_element_by_class_name("us_Su“mit").cli”k()
def tearDown(self):
self.driver.close()
if __name__ =="__mai“__":
”su=unittest.TestSuite()
su.addTest(Test_Login('test_‘ogin'))
’ now=time.strftime("%Y-%m“%d %H-%M-%S")
”fp=open('../re‘ort/'+now+‘repor’.html','wb'’
’ ’runner=HTMLTestRunner(stream=fp,title='自动化测试‘告', des’ription='用例描述'‘
’runner.run(su)
fp.close()
32. 断言
a=self.driver.find_element_by_class_name('f4_b'‘.tex’
self.assertTrue(a=='lee00‘000')
’ # self.assertEqual(a,'lee00’000')
’ # self.assertIn(a,'lee00’000')
**案’**
from HTMLTestRunner import HTMLTestRunner
url='http:‘/192.168.2.110/geeknet/user.php'
clas’ login(unittest.TestCase):
def setUp(self):
self.driver=webdriver.Firefox()
self.driver.get(url)
self.driver.maximize_window()
def test_login(self):
self.driver.find_element_by_name('usern‘me').sen’_keys('lee00‘000')
’ time.sleep(1)
self.driver.find_element_by_name('passw‘rd').sen’_keys('00000‘')
’ time.sleep(1)
self.driver.find_element_by_id("remem“er").cli”k()
time.sleep(1)
self.driver.find_element_by_class_name("us_Su“mit").cli”k()
time.sleep(1)
#断言
a=self.driver.find_element_by_class_name('f4_b'‘.tex’
self.assertTrue(a=='lee00‘000')
’ # self.assertEqual(a,'lee00’000')
’ # self.assertIn(a,'lee00’000')
’ def tearDown(self):
self.driver.close()
项目:
1. 新建一个项目geek_Auto,在其中新建文件case(存放用例)、common(共用代码存放位置)、data(数据)、pages(存放页面,一个页面一个文件)、report(存放报告)和python文件run_all(存放所有的执行代码)  2. 在common中新建一个base.py文件,存放基层代码(类,函数)
#基层代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
class Base(object):
#基于selenium进行二次封装
def __init__(self,driver:webdriver.Firefox):
#__init__初始化函数,当调用这个类,会直接执行这个初始化函数
self.driver=driver
def findelement(self,loc):
#以显示等待的方式定位元素
#loc是元素的定位方式,比如:(By.ID,'zenta’')*是把loc的2个值分开传入find_element的2个参数中 相当于:find_element(loc[0],loc[1])
print("正在获取元“位置信息:定位方式-->%s,—元素value-->%s"%(loc”0],loc[1]))
ele=WebDriverWait(self.driver,5,0.5).until(
lambda x:x.find_element(*loc)#匿名函数
)
return ele
def sendkeys(self,loc,text):
#对findelement函数再次封装,对定位的元素中输入文本
return self.findelement(loc).send_keys(text)
def click(self,loc):
#对findelement函数再次封装,对定位的元素进行点击
return self.findelement(loc).click()
def get_text(self,loc):
#对findelement函数再次封装,获取元素位置的文本
try:
a= self.findelement(loc).text
return a
except:
print('获取文本失‘,返回为空')
’ return ""
i“”__name__=='__mai‘__':
’url="http:“/192.168.2.110/geeknet/user.php"
”river=webdriver.Firefox()
driver.get(url)
d=Base(driver)
loc_user=(By.NAME,'usern’me')
’loc_pwd=(By.NAME,'passw’rd')
’loc_rem=(By.ID,'remem’er')
’loc_login_button=(By.CLASS_NAME,'us_Su’mit')
’loc_login_username=(By.CLASS_NAME,'f4_b'’
’d.sendkeys(loc_user,'test0’1')
’d.sendkeys(loc_pwd,'test0’1')
’d.click(loc_rem)
d.click(loc_login_button)
m=d.get_text(loc_login_username) #获取登录后用户名文本
if m=='test0‘1':
’ print("登录成功"“
3” 在pages文件夹中新建一个python文件login_page.py,对base.py的代码进行再次封装。
from common.base import * #引入common文件夹中base文件的所有内容
import time
class Login_Page(Base):
#将元素赋值给变量
loc_user=(By.NAME,'usern’me')
’loc_pwd=(By.NAME,'passw’rd')
’loc_rem=(By.ID,'remem’er')
’loc_login_button=(By.CLASS_NAME,'us_Su’mit')
’loc_login_username=(By.CLASS_NAME,'f4_b'’
’#三次封装
def input_user(self,text):
#输入用户名
self.sendkeys(self.loc_user,text)
def input_pwd(self,text):
#输入密码
self.sendkeys(self.loc_pwd,text)
time.sleep(3)
def click_keep_login(self):
#点击保存登录信息
self.click(self.loc_rem)
def click_login(self):
#点击登录
self.click(self.loc_login_button)
#四次封装
def login(self,user,pwd,keep_login=False):
#keep_login登录状态默认为假
self.input_user(user)
self.input_pwd(pwd)
if keep_login==True: #如果给的keep_login的参数为真
self.click_keep_login()
self.click_login()
def get_login_username(self):
#获取登录后的用户名文本
return self.get_text(self.loc_login_username)
if __name__=='__main_‘':
u’l="http://“92.168.2.110/geeknet/user.php"
dr”ver=webdriver.Firefox()
driver.get(url)
#Login_Page继承Base的类,Base类需要传递一个参数(浏览器驱动),所以它也需要传递参数
c=Login_Page(driver) #将Login_Page类实例化为c
c.login('test001‘,'test0’1’,True)
’ d=c.get_login_username()
if d=='test001‘:
’ print('登录成功')
4’ 编写用例,在case包中新建文件****test_login_case
#四次封装
from selenium import webdriver
import unittest,time
from pages.login_page import Login_Page
class Test_Login(unittest.TestCase,Login_Page):
def setUp(self):
self.driver=webdriver.Firefox()
url='http://‘92.168.2.110/geeknet/user.php'
’ self.driver.get(url)
# time.sleep(1)
self.driver.maximize_window()
def login_case(self,user,pwd,expect):
self.login(user,pwd,True) #登录并进行断言
result=self.get_login_username()
self.assertTrue(result==expect)
def test_001(self):
self.login_case('test001‘,'test0’1’,'test0’1’)
d’f test_002(self):
self.login_case('123456'‘'test0’1’,'')
’ ’’f test_003(self):
self.login_case('test001‘,'12345’'’'')
’ ’’f test_004(self):
self.login_case('12551',‘45646’2’','')
’ ’’f tearDown(self):
self.driver.close()
if __name__=='__main_‘':
u’ittest.main()
5. 使用ddt框架
#测试数据
testdata=[{'user':'‘est0’1’,'pwd':’t’st0’1’,'expec’'’'test0’1’},
’ {'user':'‘est0’1’,'pwd':’1’345’'’'expec’'’''},
’ ’’ {'user':'‘3232’'’'pwd':’t’st0’1’,'expec’'’''},
’ ’’ {'user':'‘2321’,’pwd':’1’332’'’'expec’'’''},
’ ’’ {'user':'‘est0’1’,'pwd':’'’'ex’e’’'’''},
’ ’’ {'user':'‘,'pw’'’’t’st0’1’,'expec’'’''},
’ ’’ {'user':'‘test’0’','pwd':’t’st0’1’,'expec’'’'test0’1’},
’ {'user':'‘est ’0’','pwd':’t’st0’1’,'expec’'’''},
’ ’’ {'user':'‘est0’1’','pwd':‘t’st0’1’,'expec’'’'test0’1’},
’ ]
from selenium import webdriver
import unittest,time,ddt
from pages.login_page import Login_Page
@ddt.ddt #引用ddt数据驱动框
class Test_Login(unittest.TestCase,Login_Page):
def setUp(self):
self.driver=webdriver.Firefox()
url='http://‘92.168.2.110/geeknet/user.php'
’ self.driver.get(url)
time.sleep(1)
self.driver.maximize_window()
def login_case(self,user,pwd,expect):#登录并且进行断言
self.login(user,pwd,True) #登录函数
result=self.get_login_username()#获取登录后的用户名
self.assertTrue(result==expect) #断言
@ddt.data(*testdata)#将测试数据传递给测试用例 *指的是将测试用例的元素全部遍历出来
def test_001(self,data):#每次遍历testdata里的元素传给data
print(data)
self.login_case(data['user'],‘ata[’pwd'],d‘ta[’expect'‘)
’ef tearDown(self):
self.driver.close()
if __name__=='__main_‘':
u’ittest.main()
**6. 在项目的data文件夹中新建一个Excel文件****data.xls,****然后将此事用例写入进去,纯数字要在数据前加一个英文单引号如:
****’****11223354**
user
pwd
expect
test001
test001
test001
test001
1223456
1234256
test001
2124564
1232465
test001
test001
test001
test001
test001
test 001
test001
test001
test001
test001
**通过xlrd类导入****Excel****表格**
import xlrd
class ExcelUtil():
def __init__(self,excelPath,sheetName="sheet1"“:
” # 打开excel表格
self.data=xlrd.open_workbook(excelPath)
# 通过名称获取
self.table=self.data.sheet_by_name(sheetName)
#获取第一行作为key值
self.keys=self.table.row_values(0)
# 获取总行数
self.rowNum=self.table.nrows
# 获取总列数
self.colNum = self.table.ncols
def dict_data(self):
if self.rowNum<=1:
print("总行数小于1"“
” else:
r=[] #空列表
j=1
for i in ranIe(self.rowNum-1):
s={}
#获取行里的值,以列表的形式存在
values=self.table.row_values(j)
for x in range(self.colNum):
s[self.keys[x]]=values[x]
r.append(s)
j=j+1
return r
if __name__=="__main_“":
”xcelPath = "../data“data.xls"
s”eetName = "Sheet1"“ d”ta = ExcelUtil(excelPath, sheetName)
print(data.dict_data())
7. 引用ddt数据驱动框架
from selenium import webdriver
import unittest,time,ddt
from pages.login_page import Login_Page
from common.read_excel import ExcelUtil
#测试数据
excelPath='D:\pyth‘n\geek_Auto\data\data.xls'
sheetN’me='Sheet1'‘data= ’xcelUtil(excelPath, sheetName)
testdata=data.dict_data()
@ddt.ddt #引用ddt数据驱动框架
class Test_Login(unittest.TestCase,Login_Page):
def setUp(self):
self.driver=webdriver.Firefox()
url='http://‘92.168.2.110/geeknet/user.php'
’ self.driver.get(url)
time.sleep(1)
self.driver.maximize_window()
def login_case(self,user,pwd,expect):#登录并且进行断言
self.login(user,pwd,True) #登录函数
result=self.get_login_username()#获取登录后的用户名
self.assertTrue(result==expect) #断言
@ddt.data(*testdata)#将测试数据传递给测试用例 *指的是将测试用例的元素全部遍历出来
def test_001(self,data):#每次遍历testdata里的元素传给data
print(data) #打印每次传的值
self.login_case(data['user'],‘ata[’pwd'],d‘ta[’expect'‘)
’ef tearDown(self):
self.driver.close()
if __name__=='__main_‘':
u’ittest.main()
8. 在run_all中运行所有的用例
import unittest,time
from HTMLTestRunner import HTMLTestRunner
#测试的路径
test_dir='./case/‘
a=unit‘est.defaultTestLoader.discover(test_dir,pattern='test_lo‘in_excel*.py')
#通过d’scover方法,去测试用例目录下 查找以test开头的测试用例文件,并将查找到的测试用例组装到测试套件里。
if __name__=='__main_‘':
n’w=time.strftime('%Y-%m-%‘ %H-%M-%S')
f’=open('./repor‘/'+now+'r‘port.’tml','wb')
’ ’ r’nner=HTMLTestRunner(stream=fp,title='geek购物网‘动化测试报告',descri’tion='用例描述')
‘ r’nner.run(a)
fp.close()
UI自动化理论
- PO/POM你了解吗? 了解,PO/POM就是page object model页面对象设计模式 用到的有:python + selenium +unittest + ddt +POM
- PO的优势是什么? PO提供了一种在UI层操作,业务流程与验证分离的模式,这使得测试代码变得更加清晰、可读、易维护。对象库与测试用例的分离,使得我们更好的复用对象,甚至能与不同的工具进行深度的结合应用,可复用的代码会变得更加优化。
- 功能测试和自动化测试各占多少比例? 一般情况下,自动化测试不会超过30%,还是以功能测试为主,即在3:7左右
- 你会不会搭建自动化测试环境? 会的,我去公司前已经搭建好了,我们那边有个10年自动化测试经验的工程师,他搭建的自动化测试框架。我们有完整的自动化环境搭建手册。我们只需要按照安装手册一步一步安装软件,配置相应的环境变量即可。 比如我们采用的是python + selenium +unittest + ddt 以及PO设计模式来进行自动化测试的,我们先安装python3.6,然后安装selenium,pip,pillow,ddt,pymysql,HTMLTestRunner等第三方库,然后配置相应的环境变量就可以了**。**
- 在自动化测试中是怎么组织测试用例(怎么识别那些case的)? 我们的测试用例都放在case目录下,通过单元测试框架里的discover方法,筛选出以test开头的用例,循环添加到测试套件中,让系统全部执行筛选出来的用例。
- 你们的测试数据怎么进入到测试用例的? 我们首先通过xlrd来封装读取Excel的方法,然后用封装的方法读取data目录下的Excel数据文件,最后将读取的数据放在列表里,通过ddt数据驱动工具,将列表里的数据循环添加到执行的测试用例里。
- 自动化测试中下拉列表元素是如何处理的? 我们首先引入selenium里的select类,定位下拉列表元素位置并将其赋值给一个变量,然后将元素的位置传到select类里,调用select_by_value的方法或者select_by_visible_text的方法进行下拉列表的选取
- 自动化中如何截图? 我们是通过get_screenshot_as_file函数进行截图
- 自动化中怎么截取部分截图? 首先对整个页面进行截图保存,接下来通过location获取要截取图片的左上角坐标,通过size获取元素的尺寸(宽和高),然后就得到了图片的右下角坐标,再通过PIL的Image方法读取保存的图片。最后通过左上角及右下角坐标使用crop进行裁切,最后保存成图片就可以了。
- 如何处理时间控件? 定位这个时间控件,然后写一段js脚本去除时间控件的只读属性,然后执行js代码,再采用send_keys去输入内容就可以了。
- 如何处理弹框? 我们通过driver.swith_to.alert,切换到弹框页面上,通过accept点击确定,或者通过dismiss点击取消,或者send_keys向弹框里输入值
- 定位元素的方式有哪些? 有8种元素定位方式:id定位,name定位,class_name定位,tag_name标签名定位, link_text文本定位,partail_link_text部分文本定位,xpath定位,css定位
- 自动化是如何生成测试报告的? 首先引入HTMLTestRunner外部文件,先将时间格式化成年月日时分秒的格式来定义测试报告的文件名,然后定位报告的储存路径,通过open函数采用wb的方式打开这个文件,然后采用HTMLTestRunner方法,传入打开的测试报告文件,测试用例的标题,测试用例的描述生成执行器,最后让执行器执行测试套件即可生成测试报告了。
- 如何提高自动化脚本的稳定性?
- 不要右键复制Xpath,自己写相对路径,多用id节点查找
- 保证元素定位没又问题,第二个影响的因素就是等待,少用强制等待与隐式等待
- 定位元素方法重新封装,结合显示等待,自己定义一套定位元素的方法。
- Selenium的特点有什么? 开源,免费,API(封装的函数)简单、灵活 多浏览器支持:Firefox chrome ie等 多平台支持:linux macos windows 多语言支持:java python JavaScript PHP ruby等 对页面有良好的支持
- 什么是UI自动化测试? 使用自动化工具来批量自动运行测试用例测试页面
- 单元自动化测试 单元测试框架 Java:testNG、Junit Python:unittest、pytest C#:Nunit 几乎主流的语言里边都会有单元测试框架
- 接口自动化(不分Web和App) 接口测试工具:jmeter、postman、soapUI、loadrunner 代码执行接口自动化:python的requests库 java的httpclient/httpunit
- UI自动化测试(web自动化测试) QTP(最早)、Robot Framework、Selenium(目前最流行的)
- APP自动化测试 Monkey以及Monkey runner是Android自带的测试工具 Appium(目前市场最流行的)
- 什么样的项目适合做自动化测试? (1)如果一个项目频繁做回归测试。 (2)系统界面比较稳定(页面变动少的适合做UI自动化,页面变动多的适合做接口自动化) (3)软件维护周期比较长,项目进度压力不是太大。 (4)测试人员具备较强的编程能力。
- 使用poython连接Oracle数据库 需要用到cx_oracle这个第三方库。首先,先引入cx_oracle,然后准备好连接数据,如:用户名/登录密码@Oracle服务器IP:端口号(:1521)/连接的数据库名。 例如:test001/test001@192.168.2.2:1521/orcl 代码如下:
import os,cx_Oracle
userName = ‘test001’
pwd=‘test001’
ip=‘192.168.2.2’
db=‘orcl’
sql=“select id from student”
def get_value_from_db(userName,pwd,ip,db,sql):
#建立oracle数据库连接,格式如下:test001/test001@192.168.2.2:1521/orcl
conn=cx_Oracle.connect(userName+ ‘/‘ + pwd + ‘@‘ + ip + ‘:1521/‘ + db)
#获取指针
cur=conn.cursor()
#执行sql语句
cur.execute(sql)
#获取执行结果
row=cur.fetchone()
#把值返回给函数
return row[0]
#关闭指针
cur.close
#关闭数据库连接
conn.close
AA=get_value_from_db(userName,pwd,ip,db,sql)
print(AA)
- 使用句柄切换页面
from selenium import webdriver
from selenium.webdriver.common.by import By
from common.base import Base
driver=webdriver.Firefox()
driver.get(‘https://www.baidu.com/‘)
# handle=driver.current_window_handle
# print(‘当前的handle为: ‘,handle)
ba=Base(driver)
loc_text=(By.ID,’kw’)
loc_cl=(By.ID,’su’)
loc=(By.XPATH,’/html/body/div/div[3]/div/div[3]/div[3]/h3/a’)
loc_2=(By.XPATH,”.//*[@id=‘2’]/h3/a”)
ba.sendkeys(loc_text,'句柄')
ba.click(loc_cl)
ba.click(loc)
handles=driver.window_handles #将所有窗口的句柄输出到一个列表中
print('所有的handle为: ',handles)
driver.switch_to.window(handles[0]) #使用切片的方式切换到初始页面
# ba.click(loc_2)
博客来源:雨夜的博客