软件自动化测试概述
- 自动化测试是为了在软件测试的过程中节省人力、时间等资源以机器执行测试代替人工测试过程而进行的测试
- 自动化测试只能用来做简单逻辑的业务测试
- 自动化测试主要目的是为了验证已测功能的正确性
自动化测试适用情况
- 测试任务明确、需求不会频繁变动
- 软件系统稳定,变动少
- 软件需要在多平台、环境下运行执行相同的测试用例
- 项目周期长,进度压力不大、测试时间相对充裕等
web自动化测试环境
- 编程语言:python3
- 编辑器:编辑器可选用pycharm、vscode、eclipse等,此处使用vscode
- 工具:selenium3、virtualenv
- 第三方模块 HTMLTEestRunner,用来生成测试报告
- selenium主要用于web应用程序的自动化测试
- 开源、免费
- 具备支持多平台、支持多款浏览器、多语言等特点
- 可用python自带的pip进行安装,在DOS窗口输入pip install selenium(未输入版本号,默认安装最新版本)即可自动安装
- virtualenv用来创建虚拟环境,可用python自带的pip进行安装,在DOS窗口输入pip install virtualenv
web自动化项目创建
- 一个自动化项目和开发软件一样需要创建项目在项目下创建包用来管理不同的文件
项目文件构成
- 在项目中所有的文件、文件夹名不要使用中文命名,命名尽量做到能见名思意
- 测试用例文件夹cass:存放测试用例
- 测试数据文件夹data:存放测试数据
- 浏览器驱动文件夹drivers:因为使用的是selenium3,所以需要单独下载浏览器驱动
- 测试报告文件夹reports:存放测试报告
- 第三方模块文件夹utils:存放第三方模块,在此文件夹内创建一个名为__init__.py的文件,让文件夹变成一个包
- 虚拟环境nenv,创建虚拟环境时自动生成(打开vscode后在终端输入virtualenv env生成虚拟环境)
- 运行文件run.py,效果和主程序入口相同,执行测试并且生成测试报告
激活虚拟环境、在虚拟环境内安装selenium3
- 创建好项目文件后需要先激活虚拟环境
- 首先进入创建虚拟环境时生成的文件夹 nenv/Scripts
- 运行activate,终端文件位置前面出现(nenv)即为激活成功,安装selenium3
F:\vscd>cd ./nenv/Scripts
F:\vscd\nenv\Scripts>activate
(nenv) F:\vscd\nenv\Scripts>
(nenv) F:\vscd\nenv\Scripts>cd ../..
(nenv) F:\vscd>pip install selenium
访问百度
- UI自动化测试首先从元素定位开始,通过selenium的webdriver可以对web页面元素定位
- 常用元素定位方法:id、name、class、link、xpath、css等
- 首先我们通过webdriver来做一个简单的百度首页输入点击操作
from selenium import webdriver
driver = webdriver.Chrome(executable_path='./drivers/chromedriver')
driver.get("http://www.baidu.com")
driver.find_element_by_name('wd').send_keys("selenium3")
driver.find_element_by_id('su').click()
driver.quit()
- 首先我们导入selenium中的webdriver
- 实例化一个调用Chrome浏览器的webdriver传入浏览器驱动地址,命名为driver
- 通过webdriver使用get()方法访问百度首页
- webdriver使用name属性定位找到百度搜索框元素,用send_keys传入参数
- webdriver使用id属性定位到搜索按钮,并点击click()
- quit()方法退出
unittest单元测试框架
- 单元测试是负责对最小的软件设计模块进行验证以发现模块中的错误
- unittest是python语言自带的单元测试框架(python有多种单元测试框架pytest/nose等)
- 这里我们使用unittest框架编写测试用例,在cass文件夹里创建用例test1.py代码如下
from selenium import webdriver
import unittest
class TestDemo(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome(executable_path='./drivers/chromedriver')
print('test start')
def test_01(self):
self.driver.get("http://www.baidu.com")
title = self.driver.title()
self.assertEqual(title,"百度一下,你就知道","判断是否相等")
def tearDown(self):
self.driver.quit()
print('test end')
if __name__ == '__main__':
unittest.main()
- 首先导入unittest模块,创建测试类TestDemo并继承unittest的TestCase测试类
- setUp()方法用于执行测试用例前的初始化工作,这里我们实例化一个webdriver并打印一个‘test start’(这里的self.driver中的self和Java中的this效果相同,把实例化的webdriber变为全局变量)
- 在用例test_01中我们打开百度首页,用title()获取百度首页title,通过assertEqual方法对比
- tearDown()和setUp()成对出现,为测试用例执行后的工作,我们在这里退出浏览器并打印‘test end’
- 最后使用unittest提供的全局main方法,把单元测试模块变为可直接运行的脚本
测试集和运行结果
- 在项目中会有多个测试用例需要验证,unittest提供的Test Suite测试套件可以把测试用例集合在一起执行
- 以之前的代码为例创建测试集
...代码块
if __name__ == '__main__':
#构造测试集
suite = unittest.TestSuite()
suite.addTest(TestDemo('test_01'))
#执行测试
runner = unittest.TextTestRunner()
runner.run(suite)
- 首先调用unittest的TestSuite()类来创建测试套件
- 使用addTest()方法加载test_01测试用例
- 调用unittest的TextTestRunner()的run()方法来运行测试套件
自动加载测试用例和HTML测试报告
- 当我们有多个测试用例时,手动添加测试用例会变得耗费大量时间。unittest还提供了一个discover()方法来自动识别并添加测试用例
- 在我们创建项目时所创建的run.py文件用来构造测试集
- 用第三方模块HTMLTestRunner来运行测试集合,生成HTML测试报告
- 执行完成后,可到reports文件夹下查看测试报告
import unittest
from utils import HTMLTestRunner
import time
#创建用例地址
test_dir = './cass'
#获取本地当前时间
now = time.strftime('%Y-%m-%d-%H-%M-%S-')
discover = unittest.defaultTestLoader.discover(start_dir=test_dir,pattern='test*.py')
with open("./reports/%s测试报告.html" % now,"wb") as f:
runner = HTMLTestRunner.HTMLTestRunner(stream=f,verbosity=1,title='测试报告',description='详细描述----')
runner.run(discover)
- 首先我们用discover加载测试集
- start_dir:测试用例地址
- pattern = 'test*.py:用例文件名正则匹配
- with open() 文件操作,参数嵌入报告名称、读写方式
- 实例化HTMLTestRunner(),参数stream为文件,verbosity权限等级,title和description参数为选填
setUpClass()和tearDownClass()
- 当我们的测试类里面的测试用例初始化内容一样时,可以用setUpClass()来代替setUp()
- 使用setUpClass()和tearDownClass()时,前面需加装饰器classmethod
- 使用之前的代码如下
from selenium import webdriver
import unittest
class TestDemo(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome(executable_path='./drivers/chromedriver')
print('test start')
@classmethod
def tearDownClass(cls):
cls.driver.quit()
print('test end')
def test_01(self):
self.driver.get("http://www.baidu.com")
title = self.driver.title()
self.assertEqual(title,"百度一下,你就知道","判断是否相等")
自定义模块封装
- 当一个同一个功能需要执行多条测试用例时,为了减少冗余代码、节约时间我们可以把这个功能封装成一个单独的模块使用
- 以百度登录为例,在utils文件夹中创建一个Login.py文件代码如下
from selenium import webdriver
import time
class User():
def __init__(self,browser='Chrome'):
if browser == 'Chrome':
driver=webdriver.Chrome(executable_path='./drivers/chromedriver')
else:
print('浏览器驱动不存在')
self.driver = driver
def user_login(self,name,password):
self.driver.get('http://www.baidu.com')
#设置等待时间
self.driver.implicitly_wait(30)
#窗口最大化
self.driver.maximize_window()
self.driver.find_element_by_link_text('登录').click()
usernamelogin = self.driver.find_elements_by_css_selector('p.tang-pass-footerBarULogin')[0]
usernamelogin.click()
username = self.driver.find_element_by_id('TANGRAM__PSP_10__userName')
username.send_keys(name)
userpass = self.driver.find_element_by_id('TANGRAM__PSP_10__password')
userpass.send_keys(password)
self.driver.find_element_by_id('TANGRAM__PSP_10__submit').click()
def user_logout(self)
#操作过程...
self.driver.quit()
- 首先创建一个类,在类的__init__初始化方法中传入参数self和browser,并给browser一个默认值Chrome意为默认选择谷歌浏览器,通过类传入的参数直接赋给browser,并判断浏览器种类,加载相应的驱动(这里可以预写多个浏览器)
- 把实例化的webdriver变为全局变量
- user_login()方法中传入我们要登录的用户名和密码
- user_login方法中是登录操作过程,logout()为退出登录并退出浏览器
- 在cass文件夹下创建登录模块测试类test_login.py,代码如下
import unittest
import time
from utils import Login
class TestDemo1(unittest.TestCase):
@classmethod
def setUpClass(cls):
#调用Login文件下的User类别并传入浏览器名
cls.driver = Login.User('Chrome')
@classmethod
def tearDownClass(cls):
#调用退出登录
cls.driver.user_logout()
def test_01(self):
调用登录,并传入参数name password
name = 'xxx'
password = 'xxx'
self.driver.user_login(name,password)
webdriver封装
- 在webUI自动化中使用最频繁就是元素定位,而元素定位方法写起来太长,这时候我们可以对webdriver进行封装
- 在utils中创建一个Myselenium.py文件,代码如下
from selenium import webdriver
class Myselenium():
def __init__(self,browser):
if browser == 'Chrome':
driver=webdriver.Chrome(executable_path='./drivers/chromedriver')
else:
print('浏览器驱动不存在')
self.driver = driver
#传入参数by:定位方法,value元素属性值
def slide(self,by,value):
if by == 'link_text':
target = self.driver.find_element_by_link_text(value)
'''
滚动页面直到找到元素
'''
self.driver.execute_script("arguments[0].scrollIntoView();", target)
elif by == 'id':
target = self.driver.find_element_by_id(value)
self.driver.execute_script("arguments[0].scrollIntoView();", target)
elif by == 'name':
target = self.driver.find_element_by_name(value)
self.driver.execute_script("arguments[0].scrollIntoView();", target)
elif by == 'class':
target = self.driver.find_element_by_class_name(value)
self.driver.execute_script("arguments[0].scrollIntoView();", target)
elif by == 'xpath':
target = self.driver.find_element_by_xpath(value)
self.driver.execute_script("arguments[0].scrollIntoView();", target)
else:
print('元素定位失败')
return target
#打开浏览器
def open_url(self,url):
self.driver.get(url)
#元素点击操作
def click(self,by,value):
self.slide(by,value).click()
#输入框输入
def input(self,by,value,key):
self.slide(by,value).send_keys(key)
#退出浏览器
def quit(self):
self.driver.quit()
#浏览器返回
def back(self):
self.driver.back()
#浏览器前进
def forward(self):
self.driver.forward()
#获取title
def title(self):
self.driver.title()
#浏览器最大化
def max_window(self):
self.driver.maximize_window()
#设置浏览器大小
def set_window(self,x,y):
self.driver.set_window_size(x,y)
- 封装后的webdriver使用,创建测试类test02.py,代码如下:
from utils import MySelenium,readdata
import unittest
class TestDemo2(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = MySelenium.Myselenium('Chrome')
@classmethod
def tearDownClass(cls):
cls.driver.quit()
def test_01(self):
a = '搜索内容'
self.driver.open_url('http://www.baidu.com')
self.driver.max_window()
self.driver.input('id','kw',a)
self.driver.click('id','su')
a = self.driver.title()
self.driver.back()
b = self.driver.title()
self.assertEqual(a,b)
读取本地文件数据
- python提供了文件读取工具xlrd
- 用来读取本地xls文件(只读)
- 在虚拟环境中用pip install xlrd 安装即可
- xlrd的cell(x,y).value方法可读取文件数据,我们把该方法一样封装成一个模块
- 在utils文件夹下创建一个readdata.py文件,代码如下:
import xlrd
def getdata(x,y):
#打开文件路径
testdata = xlrd.open_workbook('./data/test1.xls')
#设置读取的sheet名
table = testdata.sheet_by_name('Sheet1')
#获取表格中的值
value = table.cell(x,y).value
return value
from utils import MySelenium,readdata
import unittest
class TestDemo2(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = MySelenium.Myselenium('Chrome')
@classmethod
def tearDownClass(cls):
cls.driver.quit()
def test_01(self):
#获取坐标第二行第一列的数据
a = readdata.getdata(1,0)
self.driver.open_url('http://www.baidu.com')
self.driver.max_window()
self.driver.input('id','kw',a)
self.driver.click('id','su')
a = self.driver.title()
self.driver.back()
b = self.driver.title
self.assertEqual(a,b)