1. UnitTest框架
1.1 什么是框架?
框架,FrameWork,为解决一类事情的功能集合;
1.2 什么是UnitTest框架?
UnitTest框架是专门用来进行执行代码测试的框架;
1.3 为什么使用UnitTest框架?
能够组织多个用例去执行
提供丰富的断言方法
提供丰富的日志与测试结果
2. UnitTest核心要素
1. TestCase
2. TestSuite
3. TextTestRunner
4. Fixture
2.1 TestCase
说明:(测试用例)一个TestCase就是一条测试用例;
使用:
1. 导包:import unittest --> 导入unitest框架
2. 继承:unittest.TestCase --> 新建测试类继承unittest.TestCase
提示:测试方法名称命名必须以test开头;
(原因:unittest.TestCase类批量运行的方法是搜索执行test开头的方法)
2.2 TestSuite
说明:(测试套件)多条测试用例集合在一起,就是一个TestSuite;
使用:
1. 实例化: suite=unittest.TestSuite()
2. 添加用例:suite.addTest("ClassName(MethodName)")
3. 添加扩展:suite.addTest(unittest.makeSuite(ClassName))
(搜索指定ClassName内test开头的方法并添加到测试套件中)
提示:
1). 一条测试用例(.py)内,多个方法也可以使用测试套件
2). TestSuite需要配合TextTestRunner才能被执行
2.3 TextTestRunner
说明:(测试执行)用来执行测试用例套件
使用:
1. 实例化: runner=unittest.TextTestRunner()
2. 执行: runner.run(suite)
2.4 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
3. 案例1
需求:使用UnitTest框架测试登陆
3.1 操作步骤分析:
1. 导包 import unittest
2. 新建测试类并继承unittest.TestCast
3. 新建一个Fixture(setUp、tearDown)
4. 新建登录方法
5. if __name__ == '__main__':
6. unittest.main()执行
3.2 总结-代码实现
import unittest
from time import sleep
from selenium import webdriver
class TestLoginOut(unittest.TestCase):
def setUp(self):
self.driver=webdriver.Firefox()
url = "http://xxx"
self.driver.get(url)
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方法执行unitetest内所有test开头方法
unittest.main()
需求
将test01.py..test10.py共10条用例,将这10条用例批量执行;
问题
1. 使用suite.addtest(unittest.makeSuite(className))导入10条测试类
2. .addtest()需要添加10次
4. defaultTestLoader
说明:
使用unittest.defaultTestLoader()类,通过该类下面的discover()方法自动搜索指定目录下指定开头
的.py文件,并将查找到的测试用例组装到测试套件;
用法:
test_dir = './'
disconver = unittest.defaultTestLoader.discover(test_dir, pattern='test*.py')
(test_dir为要指定的目录 ./为当前目录;pattern:为查找的.py文件的格式 )
运行:
runner=unittest.TextTestRunner()
runner.run(disconver)
4.1 defaultTestLoader与TestSuite区别
1. TestSuite可以添加TestCase中所有test开头的方法和添加指定的test开头方法;
2. defaultTestLoader搜索指定目录下指定开头.py文件,并添加TestCase内所有test开头的方法,不能指定添加方法;
提示:defaultTestLoader属于TestSuite另一种实现方式;
5 UnitTest断言
5.1 什么是断言?
概念:让程序代替人为判断测试程序执行结果是否符合预期结果的过程
5.2 为什么要学习断言?
自动化脚本在执行的时候一般都是无人值守状态,我们不知道执行结果是否符合预期结果,所以我们需要让程序代替人
为检测程序执行的结果是否符合预期结果,这就需要使用断言;
5.3 UnitTest断言分类
1. 布尔型断言
2. 比较断言
3. 复杂断言
5.4布尔型断言(结果只有True和False)
序号 | 断言方法 | 断言描述 |
1 | assertEqual(arg1, arg2, msg=None) | 验证arg1=arg2,不等则fail 【常用】 |
2 | assertNotEqual(arg1, arg2, msg=None) | 验证arg1 != arg2, 相等则fail |
3 | assertTrue(expr, msg=None) | 验证expr是true,如果为false,则fail 【常用】 |
4 | assertFalse(expr,msg=None) | 验证expr是false,如果为true,则fail 【常用】 |
5 | assertIs(arg1, arg2, msg=None) | 验证arg1、arg2是同一个对象,不是则fail |
6 | assertIsNot(arg1, arg2, msg=None) | 验证arg1、arg2不是同一个对象,是则fail |
7 | assertIsNone(expr, msg=None) | 验证expr是None,不是则fail |
8 | assertIsNotNone(expr, msg=None) | 验证expr不是None,是则fail |
9 | assertIn(arg1, arg2, msg=None) | 验证arg1是arg2的子串,不是则fail |
10 | assertNotIn(arg1, arg2, msg=None) | 验证arg1不是arg2的子串,是则fail |
11 | assertIsInstance(obj, cls, msg=None) | 验证obj是cls的实例,不是则fail |
12 | assertNotIsInstance(obj, cls, msg=None) | 验证obj不是cls的实例,是则fail |
5.4.1 案例
需求:断言登录成功的用户名是否为admin,如果断言失败截图保存
扩展:1. 图片名称为动态-时间;2. 图片名称添加断言错误信息
实现步骤分析
成功登陆-->获取登陆后的信息-->添加断言
断言主要代码:
# 获取登陆信息
text = self.driver.find_element_by_css_selector(".loginfo").text
print("登陆成功信息为:",text)
try:
# 使用断言 判断text是否包含admin字符
self.assertIn("admin",text)
except AssertionError:
driver.get_screenshot_as_file("../Image/02img.jpg")
# 抛出异常
raise
5.5比较断言
序号 | 断言方法 | 断言描述 |
---|---|---|
1 | assertAlmostEqual (first, second, places = 7, msg = None, delta = None) | 验证first约等于second。 palces: 指定精确到小数点后多少位,默认为7 |
2 | assertNotAlmostEqual (first, second, places, msg, delta) | 验证first不约等于second。 palces: 指定精确到小数点后多少位,默认为7 注: 在上述的两个函数中,如果delta指定了值,则first和second之间的差值必须≤delta |
3 | assertGreater (first, second, msg = None) | 验证first > second,否则fail |
4 | assertGreaterEqual (first, second, msg = None) | 验证first ≥ second,否则fail |
5 | assertLess (first, second, msg = None) | 验证first < second,否则fail |
6 | assertLessEqual (first, second, msg = None) | 验证first ≤ second,否则fail |
7 | assertRegexpMatches (text, regexp, msg = None) | 验证正则表达式regexp搜索匹配的文本text。 regexp:通常使用re.search() |
8 | assertNotRegexpMatches (text, regexp, msg = None) | 验证正则表达式regexp搜索不匹配的文本text。 regexp:通常使用re.search() 说明:两个参数进行比较(>、≥、<、≤、约等、不约等) |
5.6复杂断言
序号 | 断言方法 | 断言描述 |
---|---|---|
1 | assertListEqual(list1, list2, msg = None) | 验证列表list1、list2相等,不等则fail,同时报错信息返回具体的不同的地方 |
2 | assertTupleEqual (tuple1, tuple2, msg = None) | 验证元组tuple1、tuple2相等,不等则fail,同时报错信息返回具体的不同的地方 |
3 | assertSetEqual (set1, set2, msg = None) | 验证集合set1、set2相等,不等则fail,同时报错信息返回具体的不同的地方 |
4 | assertDictEqual (expected, actual, msg = None | 验证字典expected、actual相等,不等则fail,同时报错信息返回具体的不同的地方 |
6. HTML测试报告
6.1 HTML生成报告方式
1. Export Test Results (UnitTest 自带,不推荐,不讲)
2. HTMLTestRunner(第三方模板)【常用】
6.2 测试报告 生成步骤分析
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)
6.3 实现代码
import time
from CodeEdit.LX04.Tools.HTMLTestRunner import HTMLTestRunner
import unittest
test_dir='.' # 加载当前目录
discover=unittest.defaultTestLoader.discover(test_dir,pattern="test*.py") # 加载当前目录下iweb开头的.py文件
if __name__ == '__main__':
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:
# 实例化HTMLTestRunenr对象,传入报告文件流f
runner=HTMLTestRunner(stream=f,title="iweb_shop项目Web自动化测试报告",description="测试用例共计2条")
runner.run(discover)