第三 章unittest框架

3.1 unittest简介

unittest是一个python版本的单元测试框架,可以用于python的单元测试。相似的其它语言工具Java的Junit,C#的Nunit等。可以使用Unittest做单元测试,也可以完成Web自动化测试。

  • 自动化测试用例的组织和管理
  • 提供丰富的比较方法、完成结果的检查
  • 提供执行过程数据、如:执行时间、执行结果等

3.2 unittest 语法

  • Test Case:一个TestCase实例就是一个测试用例,即一个test开头的测试函数。
  • Test Fixture:用于测试前的环境初始化和测试后的环境清理,通过setUp函数和tearDown函数完成。
  • Test Runner:unittest单元测试框架提供了TextTestRunner类来运行多个Test Suite或test case。
  • Test Suite:一个功能测试需要很多Test Case,可以多个测试用例统一进行执行,把多个用例加到一个Test Suite中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import unittest # 导入unittest模块
from selenium import webdriver
from time import time
from time import sleep

class Test(unittest.TestCase):
@classmethod
def setUpClass(self): # 初始环境
self.browser = webdriver.Chrome()
self.browser.get('http://127.0.0.1:8080/oa/')
self.browser.implicitly_wait(10) # 隐性等待
def test001(self): # 测试主体部分
self.browser.find_element_by_name('loginId').send_keys('admin')
self.browser.find_element_by_name('password').send_keys('sys123456')
cg = self.browser.find_element_by_id('button_submit').click()
if cg == True:
print('登陆成功')
self.browser.find_element_by_partial_link_text('退出登录').click()
def test002(self):
self.browser.find_element_by_name('loginId').send_keys('admin1')
self.browser.find_element_by_name('password').send_keys('sys1234567')
self.browser.find_element_by_id('button_submit').click()
sb = self.browser.find_element_by_xpath(
'/html/body/div[1]/div/table/tbody/tr[2]/td[2]/div/table/tbody/tr[2]/td/div/table/tbody/tr/td[2]')
sb = sb.text
if sb == '登录名或密码错误,请重试!':
print(sb)
@classmethod
def tearDownClass(self): # 清理环境
sleep(3)
self.browser.close() # 关闭浏览器
unittest.main()

3.3 断言

断言方法是 unittest 框架提供的一组方法,可以通过这些方法完成期望结果和实际结果的对比。assert+空格+要判断语句+逗号+“报错语句” python提供
assertEqual(a,b,msg=None) 检查a==b,不等则报错
assertNotEqual(a,b,msg=None) 检查a!=b,相等则报错
assertIn(a,b,msg=None) 检查a in b,不在报错
assertNotIn(a,b,msg=None) 检查a not in b,在报错
assertTrue(a,msg=None) 检查表达式a成立,不成立报错
assertFalse(a,msg=None) 检查表达式a不成立,成立报错assertIsInstance(obj,cls,msg=None) 检查obj是cls一个实例,是则pass,不是就报错
assertNotIsInstance(obj,cls,msg=None)检查obj不是cls一个实例,是则pass
self.assertIsNone(expr,msg)
self.assertIsNotNone(expr,msg)

断言 特殊语法1:assert a,b,”报错信息” 语法2:self.assertXXX(a,b,msg=”报错信息”)

举个栗子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import unittest
class TestAsser(unittest.TestCase):
def setUp(self): # 初始化环境
print("测试开始")
def tearDown(self): # 清理环境
print("测试结束")
def test001(self):
assert 3 == 5,"错误"
# 解释:预期结果(断言):3等于5 这个表达式成立
# 实际结果:3等于5 这个表达式不成立 所以,预期结果和实际结果不符 则报错并打印报错信息
self.assertEqual(10,100,msg="错误")
# 解释:预期结果(断言):10等于100 这个表达式成立
# 实际结果:10等于100 这个表达式不成立 所以,预期结果和实际结果不符 则报错并打印报错信息
self.assertEqual(10,10,msg="错误")
# 解释:预期结果(断言):10等于10 这个表达式成立
# 实际结果:10等于100 这个表达式成立 所以,预期结果和实际结果相符 则不报错
self.assertNotEqual(10,10,msg="错误")
self.assertNotEqual(10,20,msg="错误")
self.assertIn(1,[4,2,3,4],msg="错误")
self.assertIn(3,[4,2,3,4],msg="错误")
self.assertNotIn('a',{'a':2},msg="错误")
self.assertNotIn('2',{'a':2},msg="错误") # 注:assertNotIn对于字典来说,它只能判断键 不判断值
self.assertTrue(6 == 6,msg='错误')
self.assertTrue(6 == 7,msg='错误')
self.assertFalse(6 == 6,msg='错误')
self.assertFalse(6 == 7,msg='错误')
self.assertIs(5,6,msg='错误')
self.assertIs(5,5,msg='错误')
class People: # 创建类
print('人类')
class Dog:
print('犬类')

zs = People() # 实例化对象赋给zs
erha = Dog('二哈')
self.assertIsInstance(erha,People,msg='错误')
self.assertIsInstance(erha,Dog,msg='错误')
self.assertNotIsInstance(erha,People,msg='错误')
self.assertNotIsInstance(erha,Dog,msg='错误')
self.assertIsNone(None,msg='错误')
self.assertIsNone(People,msg='错误')
self.assertIsNone(Dog,msg='错误')
self.assertIsNotNone(Dog,msg='错误')
self.assertIsNotNone(People,msg='错误')
unittest.main()

3.4 测试用例管理

通过Test Suite 测试集(测试套件)来组装单个测试用例,然后通过addTest方法加载
TestCase添加到TestSuite中。接着调用unittest框架的TextTestRunner( )类,通过
TextTestRunner对象调用Run()方法运行suite中所组装的测试用例。
discover方法批量执行脚本用例。使用discover方法会自动收集指定目录下的测试用例添加到测试套件中,然后通过run()方法执行discover,大大简化了测试用例的查找和执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import unittest
class Test1(unittest.TestCase): # 测试类1
@classmethod
def setUpClass(cls): # 初始环境
print("测试开始")
@classmethod
def tearDownClass(cls):
print('测试结束')
def test001(self):
print("类1:第一条测试用例")
def test002(self):
print("类1:第2条测试用例")

class Test2(unittest.TestCase): # 测试类2
def test001(self):
print("类2:第1条测试用例")
def test002(self):
print("类2:第2条测试用例")

class Test3(unittest.TestCase): # 测试类3
def test001(self):
print("类3:第一条测试用例")
def test002(self):
print("类3:第一条测试用例")
unittest.main() # 方法1 完全覆盖
# 构建测试集
suite = unittest.TestSuite() #方法2:验证测试
suite.addTest(Test1('test001'))
suite.addTest(Test3('test002'))
suite.addTest(Test2('test001'))

# 执行测试
runner = unittest.TextTestRunner()
runner.run(suite)

# 方法3
# 构建测试集
suite = unittest.defaultTestLoader.discover(r'D:\chenben\pythonProject\test',pattern='te*.py')
# 测试用例存放的路径
# 执行测试
runner = unittest.TextTestRunner()
runner.run(suite)

3.5 HTML测试报告

自动化测试执行完成以后,需要输出一个完整的测试报告,供测试人员查看测试执行情况,确认自动化测试执行发现的缺陷情况。
HTMLTestRunner是Python标准库的unittest单元测试框架的一个扩展,可以生成一个可读性很强的HTML格式的测试报告。
下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
下载HTMLTestRunner.py文件,然后将其复制到你的python安装目录下(以实际安装目录为准)
test1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import unittest
import HTMLTestRunner
class Test1(unittest.TestCase): # 测试类1
@classmethod
def setUpClass(cls): # 初始环境
print("测试开始")
@classmethod
def tearDownClass(cls):
print('测试结束')
def test001(self):
print("类1:第一条测试用例")
def test002(self):
print("类1:第2条测试用例")

class Test2(unittest.TestCase): # 测试类2
def test001(self):
print("类2:第1条测试用例")
def test002(self):
print("类2:第2条测试用例")

class Test3(unittest.TestCase): # 测试类3
def test001(self):
print("类3:第一条测试用例")
def test002(self):
print("类3:第一条测试用例")
# 用HTML输出测试报告
file = open(r'D:\test\测试报告.html','bw') # 测试报告存在的路径,可以不写
suite = unittest.defaultTestLoader.discover(r'D:\test',pattern='te*.py') # 测试用例存放的路径
# 生成html测试报告
file = HTMLTestRunner.HTMLTestRunner(
stream = file,
title = '测试报告',
description = '测试信息'
)
file.run(suite)
# 执行测试

test2
test3