目标
为什么使用UnitTest框架?
1. 能组织用例和执行用例
2. 提供丰富的断言方法
3. 提供丰富的日志与测试结果
单元测试框架
掌握UnitTest框架的基础使用方法
什么是框架
说明:
1. 框架英文单词FrameWork;
2. 为解决一类事情的功能集合;
什么是UnitTest框架
概念:UnitTest框架是专门用来进行执行代码测试的框架;
为什么使用UnitTest框架
1. 能够组织多个用例去执行
2. 提供丰富的断言方法
3. 提供丰富的日志与测试结果
提示
在学习UnitTest框架之前,我们先了解下UnitTest框架内几个核心要素
UnitTest核心要素
1. TestCase
2. TestSuite
3. TextTestRunner
4. Fixture
TestCase(测试用例)
说明:(翻译:测试用例)一个TestCase就是一条测试用例;
使用:
1. 导包:import unittest --> 导入unitest框架
2. 继承:unittest.TestCase --> 新建测试类继承unittest.TestCase
提示:
1). 测试用例:在自动化测试中,一条用例就是一个完整的测试流程;
2). 测试方法名称命名必须以test开头;
(原因:unittest.TestCase类批量运行的方法是搜索执行test开头的方法)
Python
L1 (default)
已复制
# 导入unittest
import unittest
class Test01(unittest.TestCase): # 新建测试类继承unittest.TestCase
# 测试方法名称必须以test开头
def test001(self):
print('test001被执行')
def test002(self):
print('test002被执行')
if __name__ == '__main__': # 可以看看python当中的__name__,当前文件运行,__name__==main
unittest.main() # 执行以test开头的方法
'''
结果:
Test01-->test001被执行
Test01-->test002被执行
'''
TestSuite
说明:(翻译:测试套件)多条测试用例集合在一起,就是一个TestSuite;
使用:
1. 实例化: suite=unittest.TestSuite()
(suite:为TestSuite实例化的名称)
2. 添加用例:suite.addTest(ClassName("MethodName"))
(ClassName:为类名;MethodName:为方法名)
3. 添加扩展:suite.addTest(unittest.makeSuite(ClassName))
(搜索指定ClassName内test开头的方法并添加到测试套件中)
提示:
1). 一条测试用例(.py)内,多个方法也可以使用测试套件
2). TestSuite需要配合TextTestRunner才能被执行
# 导入unittest
import unittest
# 导入测试用例.py
from TestCase.Test01 import Test01
from TestCase.Test02 import Test02
from TestCase.Test03 import Test03
if __name__ == '__main__':
# 实例化suite
suite=unittest.TestSuite()
# 调用 添加用例方法 className(methonName)
suite.addTest(Test01('test001'))
suite.addTest(Test02('test002'))
suite.addTest(Test03('test003'))
# 执行testsuite
unittest.TextTestRunner().run(suite)
'''
结果:
Test01-->test001被执行
Test02-->test002被执行
Test03-->test003被执行
'''
# 导入unittest
import unittest
# 导入测试用例.py
from TestCase.Test01 import Test01
from TestCase.Test02 import Test02
from TestCase.Test03 import Test03
if __name__ == '__main__':
# 实例化suite
suite=unittest.TestSuite()
# 调用 添加用例方法 ClassName
# 搜索指定ClassName内test开头的方法并添加到测试套件中
suite.addTest(unittest.makeSuite(Test02))
# 执行testsuite
unittest.TextTestRunner().run(suite)
'''
结果:
Test02-->test001被执行
Test02-->test002被执行
Test02-->test003被执行
'''
# 导入unittest
import unittest
# 导入测试用例.py
from TestCase.Test01 import Test01
from TestCase.Test02 import Test02
from TestCase.Test03 import Test03
if __name__ == '__main__':
# 搜索指定目录指定的py文件,并返回所有搜索文件内test开头的方法,以测试套件的形式返回
# 定义测试套件
suite=unittest.defaultTestLoader.discover('.',pattern='Test*.py')
unittest.TextTestRunner().run(suite)
TextTestRunner
说明:(翻译:以文本形式执行测试)是用来执行测试用例套件
使用:
1. 实例化: runner=unittest.TextTestRunner()
(runner:TextTestRunner实例化名称)
2. 执行: runner.run(suite)
(suite:为测试套件名称)
Fixture
说明:是一个概述,对一个测试用例环境的搭建和销毁就是一个Fixture;
使用:
1. 初始化(搭建):def setUp(self) --> 首先执行
(setUp:此方法继承于unittest.TestCase)
2. 结束(销毁): def tearDown(self) --> 最后执行
(tearDown:此方法继承于unittest.TestCase)
提示:
1. 必须继承unittest.TestCase类,setUp、tearDown才是一个Fixture;
2. setUp:一般做初始化工作,比如:实例化浏览器、浏览器最大化、隐式等待设置
3. tearDown:一般做结束工作,比如:退出登录、关闭浏览器
4. 如果一个测试类有多个test开头方法,则每个方法执行之前都会运行setUp、结束时运行tearDown
案例
需求:使用UnitTest框架对iweb_shop项目测试
1. 登陆进行测试
操作步骤分析:
1. 导包 import unittest
2. 新建测试类并继承unittest.TestCase
3. 新建一个Fixture(setUp、tearDown)
4. 新建登录方法
5. if __name__ == '__main__':
6. unittest.main()执行
代码实现:
import unittest
from time import sleep
from selenium import webdriver
class TestLoginOut(unittest.TestCase):
def setUp(self):
# self.driver 是成员属性,被类对象内部共享
# self指代当前对象
# driver 是局部变量,生命周期在当前方法内
# 这里由于driver对象在后面还用到也就是要共享,所以将其设为对象内部属性,调用时self.driver
self.driver = webdriver.Firefox()
url = 'http://localhost/iwebshop/'
self.driver.get(url)
# 设置隐式等待10s
self.driver.implicitly_wait(10)
# 最大化浏览器对象
self.driver.maximize_window()
print('setup')
def test_login(self):
driver = self.driver
driver.find_element_by_link_text('登录').click()
driver.find_element_by_css_selector('input[alt*="邮箱"]').send_keys('admin')
driver.find_element_by_css_selector('input[alt*="密码"]').send_keys('123456')
driver.find_element_by_css_selector('.submit_login').click()
sleep(3)
driver.find_element_by_css_selector('.reg').click()
def tearDown(self):
sleep(2)
self.driver.quit() # 确保是同一个浏览器对象
print('tearDown')
if __name__=='main':
# 调用main方法执行unittest内所有test开头方法
unittest.main()
回顾
为什么使用UnitTest框架?
1. 能组织用例和执行用例
2. 提供丰富的断言方法
3. 提供丰富的日志与测试结果
1. UnitTest用例组织和执行用例方法我们基本就学完了
2. 接下来我们学习UnitTest框架的断言方法
UnitTest断言
什么是断言?
概念:让程序代替人为判断测试程序执行结果是否符合预期结果的过程
为什么要学习断言?
自动化脚本在执行的时候一般都是无人值守状态,我们不知道执行结果是否符合预期结果,
所以我们需要让程序代替人为检测程序执行的结果是否符合预期结果,这就需要使用断言;
UnitTest断言分类
1. 基本布尔型断言
2. 比较断言
3. 复杂断言
提示:
1. 这里这介绍基本布尔类型断言 说明:结果只有True和False
2. 比较断言、复杂断言有兴趣的同学请参考4.4附件资料
案例
需求:
1. iweb项目登陆,输入正确用户名和密码,断言登录成功的用户名是否为admin,如果断言失败截图保存
扩展:
1. 图片名称为动态-时间
2. 图片名称添加断言错误信息
实现步骤分析
1. 成功登陆
2. 获取登陆后的信息
3. 添加断言
断言主要代码实现
# 获取登陆信息,因为没有打开新窗口,所以句柄没变化,还是在当前窗口查找元素
import sys
import time
import unittest
from time import sleep
from selenium import webdriver
class TestLoginOut(unittest.TestCase):
def setUp(self):
# self.driver 是成员属性,被类对象内部共享
# self指代当前对象
# driver 是局部变量,生命周期在当前方法内
self.driver = webdriver.Firefox()
url = 'http://localhost/iwebshop/'
self.driver.get(url)
# 设置隐式等待10s
self.driver.implicitly_wait(10)
# 最大化浏览器对象
self.driver.maximize_window()
print('setup')
def test_login(self):
driver = self.driver
driver.find_element_by_link_text('登录').click()
driver.find_element_by_css_selector('input[alt*="邮箱"]').send_keys('admin')
driver.find_element_by_css_selector('input[alt*="密码"]').send_keys('123456')
driver.find_element_by_css_selector('.submit_login').click()
# 获取登录后的提示信息
text = driver.find_element_by_css_selector('.loginfo').text
try:
self.assrtIn('admin',text)
except AssertionError:
# 设置时间字符串(获取运行时系统时间)
nowtime = time.strftime('%Y_%m_%d %H_%M_%S')
# 截取屏幕
driver.get_screenshot_as_file('../Image/%s---%s.jpg' % nowtime,sys.exc_info()[1])
# 抛出捕获的异常,并终止后面的代码
raise AssertionError
# 退出
sleep(3)
driver.find_element_by_link_text('安全退出').click()
def tearDown(self):
sleep(2)
self.driver.quit() # 确保是同一个浏览器对象
print('tearDown')
if __name__=='main':
# 调用main方法执行unittest内所有test开头方法
unittest.main()
测试结果-HTML测试报告
什么是HTML测试报告
说明:HTML测试报告就是执行完测试用例后以HTML(网页)方式将执行结果生成报告
为什么要生成测试报告
1. 测试报告是本次测试目的最终体现形态
2. 测试报告内包含了有关本次测试用例的详情
HTML生成报告方式
Export Test Results (自带)
提示:适合单条用例执行时使用
HTMLTestRunner【重点】
测试报告 生成步骤分析
1. 复制HTMLTestRunner.py文件到项目文件夹
2. 导入HTMLTestRunner、UnitTest包
3. discover加载要执行的用例
(discover=unittest.defaultTestLoader.discover(test_dir,pattern="test*.py"))
4. 设置报告生成路径和文件名
(file_name=file_dir+nowtime+"Report.html")
5. 打开报告 with open(file_name,'wb') as f: # 没有会自动生成文件
6. 实例化HTMLTestRunner对象:runner=HTMLTestRunner(stream=f,[title],[description])
参数说明:
(stream:文件流,打开写入报告的名称及写入编码格式)
(
[],为可选;
title为报告标题,如XXX自动化测试报告
description:为说明;比如操作系统、浏览器等版本
)
7. 执行:runner.run(discover)
实现代码
# 导入unittest
import time
import unittest
# 导入HTMLTestRunner.py
import TestCase.HTMLTestRunner
# 导入测试用例.py
from TestCase.HTMLTestRunner import HTMLTestRunner
from TestCase.Test01 import Test01
from TestCase.Test02 import Test02
from TestCase.Test03 import Test03
test_dir='.'
if __name__ == '__main__':
# 加载当前目录下test开头的.py文件
discover = unittest.defaultTestLoader.discover(test_dir, pattern="Test*.py")
# 定义报告目录
file_dir = '../Report/'
# 定义报告名称格式
nowtime=time.strftime("%Y-%m-%d %H_%M_%S")
# 报告完整路径和名称
file_name = file_dir+nowtime+'Report.html'
with open(file_name,'wb') as f: # 二进制形式写入
# 实例化HTMLTestRunner 对象,传入报告文件流f
runner = HTMLTestRunner(stream=f,title='web自动化测试报告',description='孙腾写的')
runner.run(discover)