自动化搭建环境及基础理论

383 阅读23分钟

自动化搭建环境及基础理论


在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自动化搭建手册(配置第三方自动化测试工具):

  1. 安装python(3.6)最好安装到D盘,记得勾选添加环境变量(add..to path)
  2. 安装pycharm
  3. 安装selenium 2.53.6指selenium的版本(命令pip install selenium==2.53.6)
  4. 安装连接数据库工具的第三方包 pip install pymysql==0.9.3
  5. 安装pillow图像处理库 pip install pillow==5.4.1
  6. 安装ddt用来实现数据驱动的自动化工具 pip install ddt==1.2.0
  7. 安装xlrd库实现读写Excel文件 pip install xlrd==1.2.0
  8. 将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定位到我们需要操作的元素的源代码(通过元素的属性值来定位元素)

  1. from 第三方库名import驱动名从第三方库引入库里的驱动模块
from selenium import webdriver
import time
  1. 变量名****=驱动名#**驱动实例化
driver=webdriver.Firefox()
  1. 浏览器驱动****.get****(网址)****#****使用浏览器打开某网页
webdriver.Firefox.get(‘www.baidu.com’)
  1. 输入框使用****.send_keys(“输入的内容”)点击按钮使用.click()**
driver.find_element_by_id(‘zentao’).click()
driver.find_element_by_name(‘account’).send_keys(‘admin’)
  1. 通过页面元素的属性来定位页面元素的方法 语法:浏览器驱动.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('13456')’# 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.TestCasename前后的__下划线是两个 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':’1332'’'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自动化理论

  1. PO/POM你了解吗? 了解,PO/POM就是page object model页面对象设计模式 用到的有:python + selenium +unittest + ddt +POM
  2. PO的优势是什么? PO提供了一种在UI层操作,业务流程与验证分离的模式,这使得测试代码变得更加清晰、可读、易维护。对象库与测试用例的分离,使得我们更好的复用对象,甚至能与不同的工具进行深度的结合应用,可复用的代码会变得更加优化。
  3. 功能测试和自动化测试各占多少比例? 一般情况下,自动化测试不会超过30%,还是以功能测试为主,即在3:7左右
  4. 你会不会搭建自动化测试环境? 会的,我去公司前已经搭建好了,我们那边有个10年自动化测试经验的工程师,他搭建的自动化测试框架。我们有完整的自动化环境搭建手册。我们只需要按照安装手册一步一步安装软件,配置相应的环境变量即可。 比如我们采用的是python + selenium +unittest + ddt 以及PO设计模式来进行自动化测试的,我们先安装python3.6,然后安装selenium,pip,pillow,ddt,pymysql,HTMLTestRunner等第三方库,然后配置相应的环境变量就可以了**。**
  5. 在自动化测试中是怎么组织测试用例(怎么识别那些case的)? 我们的测试用例都放在case目录下,通过单元测试框架里的discover方法,筛选出以test开头的用例,循环添加到测试套件中,让系统全部执行筛选出来的用例。
  6. 你们的测试数据怎么进入到测试用例的? 我们首先通过xlrd来封装读取Excel的方法,然后用封装的方法读取data目录下的Excel数据文件,最后将读取的数据放在列表里,通过ddt数据驱动工具,将列表里的数据循环添加到执行的测试用例里。
  7. 自动化测试中下拉列表元素是如何处理的? 我们首先引入selenium里的select类,定位下拉列表元素位置并将其赋值给一个变量,然后将元素的位置传到select类里,调用select_by_value的方法或者select_by_visible_text的方法进行下拉列表的选取
  8. 自动化中如何截图? 我们是通过get_screenshot_as_file函数进行截图
  9. 自动化中怎么截取部分截图? 首先对整个页面进行截图保存,接下来通过location获取要截取图片的左上角坐标,通过size获取元素的尺寸(宽和高),然后就得到了图片的右下角坐标,再通过PIL的Image方法读取保存的图片。最后通过左上角及右下角坐标使用crop进行裁切,最后保存成图片就可以了。
  10. 如何处理时间控件? 定位这个时间控件,然后写一段js脚本去除时间控件的只读属性,然后执行js代码,再采用send_keys去输入内容就可以了。
  11. 如何处理弹框? 我们通过driver.swith_to.alert,切换到弹框页面上,通过accept点击确定,或者通过dismiss点击取消,或者send_keys向弹框里输入值
  12. 定位元素的方式有哪些? 有8种元素定位方式:id定位,name定位,class_name定位,tag_name标签名定位, link_text文本定位,partail_link_text部分文本定位,xpath定位,css定位
  13. 自动化是如何生成测试报告的? 首先引入HTMLTestRunner外部文件,先将时间格式化成年月日时分秒的格式来定义测试报告的文件名,然后定位报告的储存路径,通过open函数采用wb的方式打开这个文件,然后采用HTMLTestRunner方法,传入打开的测试报告文件,测试用例的标题,测试用例的描述生成执行器,最后让执行器执行测试套件即可生成测试报告了。
  14. 如何提高自动化脚本的稳定性?
  15. 不要右键复制Xpath,自己写相对路径,多用id节点查找
  16. 保证元素定位没又问题,第二个影响的因素就是等待,少用强制等待与隐式等待
  17. 定位元素方法重新封装,结合显示等待,自己定义一套定位元素的方法。
  18. Selenium的特点有什么? 开源,免费,API(封装的函数)简单、灵活 多浏览器支持:Firefox chrome ie等 多平台支持:linux macos windows 多语言支持:java python JavaScript PHP ruby等 对页面有良好的支持
  19. 什么是UI自动化测试? 使用自动化工具来批量自动运行测试用例测试页面
  20. 单元自动化测试 单元测试框架 Java:testNG、Junit Python:unittest、pytest C#:Nunit 几乎主流的语言里边都会有单元测试框架
  21. 接口自动化(不分WebApp) 接口测试工具:jmeter、postman、soapUI、loadrunner 代码执行接口自动化:python的requests库 java的httpclient/httpunit
  22. UI自动化测试(web自动化测试) QTP(最早)、Robot Framework、Selenium(目前最流行的)
  23. APP自动化测试 Monkey以及Monkey runner是Android自带的测试工具 Appium(目前市场最流行的)
  24. 什么样的项目适合做自动化测试? (1)如果一个项目频繁做回归测试。 (2)系统界面比较稳定(页面变动少的适合做UI自动化,页面变动多的适合做接口自动化) (3)软件维护周期比较长,项目进度压力不是太大。 (4)测试人员具备较强的编程能力。
  25. 使用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)
  1. 使用句柄切换页面
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)

软件测试专业书籍

博客来源:雨夜的博客