目录
- 案例1
- 2、生成测试报告
- 断言基本操作
- 数据驱动 ddt data
- 巩固
- 总结
unittest是python单元测试框架,类似于JUnit框架
意义:
- 灵活的组织ui接口测试自动化用例
- 让用例高效的执行
- 方便验证测试用例的结果
- 集成html形式测试报告
- 一个class继承unittest.TestCase类,即是一个个具体的TestCase(类方法名称必须以test开头,否则不能被unittest识别)
- 每一个用例执行的结果的标识,成功是. ,失败为F,出错是E
- 每一个测试以test01、test02…依次写下去,unittest才可按照编号执行
- versity参数控制输出结果,0是简单报告、1是一般报告、2是详情报告。
- 用setUp()、terUpClass()以及tearDownClass()可以在用例执行前布置环境,以及在用例执行后清理环境。
- 参数中加stream,可以讲报告输出到文件:可以用HTMLTestRunner输出html报告。
- 多个单元的测试用例集合在一起,就是TestSuite。
案例1
from selenium import webdriver | |
import requests | |
def test01(): | |
''' | |
用例1 | |
:return: | |
''' | |
url = "http://www.ynhousedata.cn/house/assessment/assess_public?token=9a5008072cfd7336350306fdd9ea9485×tamp=2022-04-22 09:20:33&layer=1&total_layer=8&total_area=120&pre_id=4450" | |
re = requests.get(url) | |
print(re.status_code, re.text, re.headers, re.encoding) | |
def test02(): | |
''' | |
用例1 | |
:return: | |
''' | |
driver = webdriver.Chrome() | |
driver.get('https://www.baidu.com/') | |
search = input('输入搜索内容\n') | |
driver.find_element_by_xpath('//*[@id="kw"]').send_keys(search) | |
driver.find_element_by_xpath('//*[@id="su"]').click() | |
test01() | |
test02() |
以上测试,一旦test01出错,后边的代码无法执行,而且测试报告,不便于查阅。
import unittest | |
class TestCases(unittest.TestCase): | |
@classmethod | |
def setUpClass(cls) -> None: | |
print('所有用例的前置') | |
@classmethod | |
def tearDownClass(cls) -> None: | |
print('所有用例的后置') | |
def setUp(self) -> None: | |
print('每个用例前置') | |
def tearDown(self) -> None: | |
print('每个用例的后置') | |
def test01(self): | |
print('执行用例1') | |
def test02(self): | |
print('执行用例2') | |
if __name__ == '__main__': | |
unittest.main() |
运行结果
Ran 2 tests in 0.001s
OK
所有用例的前置
每个用例前置
执行用例1
每个用例的后置
每个用例前置
执行用例2
每个用例的后置
所有用例的后置
Process finished with exit code 0
若某个类下用例非常多,但又只想执行某一个,可以用以下方法
if __name__ == '__main__': | |
# 创建套件对象 | |
suit = unittest.TestSuite() | |
# 添加指定用例 | |
suit.addTest(TestCases("test02")) | |
run = unittest.TextTestRunner() | |
run.run(suit) |
运行结果
所有用例的前置
每个用例前置
执行用例2
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
<unittest.runner.TextTestResult run=1 errors=0 failures=0>
若某个类下用例非常多,以下运行方式可以执行多个用例
if __name__ == '__main__': | |
# 创建套件对象 | |
suit = unittest.TestSuite() | |
# 添加指定用例,多条 | |
suit.addTests([TestCases("test01"), TestCases("test02")]) | |
run = unittest.TextTestRunner() | |
run.run(suit) |
运行结果
所有用例的前置
每个用例前置
执行用例1
每个用例的后置
.每个用例前置
执行用例2
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
<unittest.runner.TextTestResult run=2 errors=0 failures=0>
当一个py文件下有多个类,需要执行某个类的时候,可以用以下方法执行
if __name__ == '__main__': | |
# 创建套件对象 | |
suit = unittest.TestSuite() | |
# 加载类 | |
load = unittest.TestLoader() | |
suit.addTest(load.loadTestsFromTestCase(TestCases)) #TestCases为 | |
run = unittest.TextTestRunner() | |
run.run(suit) |
运行结果
所有用例的前置
每个用例前置
执行用例1
每个用例的后置
.每个用例前置
执行用例2
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
<unittest.runner.TextTestResult run=2 errors=0 failures=0>
当有多个测试类的时候,可以用以下方法执行
from selenium import webdriver | |
import requests | |
import unittest | |
class TestCases1(unittest.TestCase): | |
@classmethod | |
def setUpClass(cls) -> None: | |
print('所有用例的前置') | |
@classmethod | |
def tearDownClass(cls) -> None: | |
print('所有用例的后置') | |
def setUp(self) -> None: | |
print('每个用例前置') | |
def tearDown(self) -> None: | |
print('每个用例的后置') | |
def test01(self): | |
print('执行用例1') | |
def test02(self): | |
print('执行用例2') | |
class TestCases2(unittest.TestCase): | |
@classmethod | |
def setUpClass(cls) -> None: | |
print('所有用例的前置') | |
@classmethod | |
def tearDownClass(cls) -> None: | |
print('所有用例的后置') | |
def setUp(self) -> None: | |
print('每个用例前置') | |
def tearDown(self) -> None: | |
print('每个用例的后置') | |
def test04(self): | |
print('执行用例4') | |
def test03(self): | |
print('执行用例3') | |
if __name__ == '__main__': | |
# 创建类加载对象 | |
load = unittest.TestLoader() | |
# 分别加载两个类 | |
suit1 = load.loadTestsFromTestCase(TestCases1) | |
suit2 = load.loadTestsFromTestCase(TestCases2) | |
# 放在套件里 | |
suits = unittest.TestSuite([suit1, suit2]) | |
run = unittest.TextTestRunner() | |
run.run(suits) |
运行结果
所有用例的前置
每个用例前置
执行用例1
每个用例的后置
.每个用例前置
执行用例2
每个用例的后置
.所有用例的后置
所有用例的前置
每个用例前置
执行用例3
每个用例的后置
.每个用例前置
执行用例4
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
<unittest.runner.TextTestResult run=4 errors=0 failures=0>
当需要执行多个py文件下的类的用例的时候可以用以下方法
文件结构
➜ unitTest pwd
/Users/lidong/Desktop/zhouyu/BILIBILI/笔记/unitTest,假设main.py执行testCase文件夹下的test*.py里的类
➜ unitTest tree
.
├── unitTest.md
├── __init__.py
├── main.py
└── testCase
├── test01.py
└── test02.py
1 directory, 5 files
test01.py
import unittest | |
class TestCases1(unittest.TestCase): | |
@classmethod | |
def setUpClass(cls) -> None: | |
print('所有用例的前置') | |
@classmethod | |
def tearDownClass(cls) -> None: | |
print('所有用例的后置') | |
def setUp(self) -> None: | |
print('每个用例前置') | |
def tearDown(self) -> None: | |
print('每个用例的后置') | |
def test01(self): | |
print('执行用例1') | |
def test02(self): | |
print('执行用例2') |
test02.py
import unittest | |
class TestCases2(unittest.TestCase): | |
@classmethod | |
def setUpClass(cls) -> None: | |
print('所有用例的前置') | |
@classmethod | |
def tearDownClass(cls) -> None: | |
print('所有用例的后置') | |
def setUp(self) -> None: | |
print('每个用例前置') | |
def tearDown(self) -> None: | |
print('每个用例的后置') | |
def test04(self): | |
print('执行用例4') | |
def test03(self): | |
print('执行用例3') |
main.py
# -*- coding: utf-8 -*- | |
# @File : main.py | |
# @Author : 李东 | |
# @Time : 2022/04/25 10:42:20 | |
import unittest | |
test_dir = "/Users/lidong/Desktop/zhouyu/BILIBILI/笔记/unitTest" | |
report_path = | |
dis = unittest.defaultTestLoader.discover(test_dir, pattern="test*.py") | |
# 创建套件 | |
suit = unittest.TestSuite() | |
# 添加套件用例 | |
suit.addTest(dis) | |
run = unittest.TextTestRunner() | |
run.run(suit) |
运行如下:
所有用例的前置
每个用例前置
执行用例1
每个用例的后置
.每个用例前置
执行用例2
每个用例的后置
.所有用例的后置
所有用例的前置
每个用例前置
执行用例3
每个用例的后置
.每个用例前置
执行用例4
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
<unittest.runner.TextTestResult run=4 errors=0 failures=0>
2、生成测试报告
进入网站,下载HTMLTestRunner文件
下载后修改文件,建议全部修改,如果报错,将不需要修改的地方还原即可。
94行,import StringI0 ||| import io | |
118行,self.fp.write(s) ||| self.fp.write(bytes(s,'UTF-8')) | |
539行,self.outputBuffer = StringI0.StringI0() ||| self.outputBuffer = io.BytesI0() | |
631行,print >>sys .stderr, '\nTime ELapsed: %s' % (self.stopTime-seLf.startTime) ||| print('\nTime Elapsed: %s' % (self.stopTime-self.startTime)) | |
642行,if not rmap.has_key(cls): ||| if not cls in rmap: | |
766行,uo = o.decode('latin-1') ||| uo = o | |
768行,uo = o ||| Uo = o.decode('utf-8') | |
772行,ue = e.decode('latin-1') ||| ue=e | |
774行,ue = e ||| ue = e.decode('utf-8') |
修改完成之后,将文件放入到python环境的lib目录下(windows)。mac 用户可以放在****/lib/python3.9/site-packages目录下。
创建报告存放的文件夹report,报告目录结构如下
main.py定义如下
import unittest | |
import HTMLTestRunner | |
test_dir = "/Users/lidong/Desktop/zhouyu/BILIBILI/笔记/unitTest/testCase" | |
# 报告存放的位置 | |
report_path = "/Users/lidong/Desktop/zhouyu/BILIBILI/笔记/unitTest/report/" | |
# 打开目录,生成html文件 | |
file = open(report_path+'result.html', 'wb') | |
# 文件格式生成 | |
run = HTMLTestRunner.HTMLTestRunner(stream=file, title='这是报告标题', description='这是报告描述') | |
# 加载用 | |
dis = unittest.defaultTestLoader.discover(test_dir, pattern="test*.py") | |
# 运行用例 | |
run.run(dis) |
6、运行main.py之后,会在report目录下生成html报告
7、 使用浏览器打开,可以看到如下报告
断言基本操作
import unittest | |
import requests | |
class Tess(unittest.TestCase): | |
def setUp(self): | |
res = requests.get('http://www.baidi.com') | |
return res.status_code | |
def test1(self): | |
# 判断获取的状态是否等于200 | |
self.assertEqual(self.setUp(), 200) | |
if __name__ == '__main__': | |
unittest.main() |
数据驱动 ddt data
import unittest | |
from ddt import ddt, data | |
@ddt | |
class TestCases2(unittest.TestCase): | |
@classmethod | |
def setUpClass(cls) -> None: | |
print('所有用例的前置') | |
@classmethod | |
def tearDownClass(cls) -> None: | |
print('所有用例的后置') | |
def setUp(self) -> None: | |
print('每个用例前置') | |
def tearDown(self) -> None: | |
print('每个用例的后置') | |
@data('username01', 'username02') | |
def test04(self, username): | |
"""冒烟用例""" | |
print('执行用例4,',username,'登陆成功') | |
def test03(self): | |
"""爆炸用例""" | |
print('执行用例3') | |
if __name__ == '__main__': | |
# 创建类加载对象 | |
load = unittest.TestLoader() | |
# 分别加载两个类 | |
suit2 = load.loadTestsFromTestCase(TestCases2) | |
# 放在套件里 | |
suits = unittest.TestSuite([suit2]) | |
run = unittest.TextTestRunner() | |
run.run(suits) |
运行结果
所有用例的前置
每个用例前置
执行用例3
每个用例的后置
.每个用例前置
执行用例4, username01 登陆成功
每个用例的后置
.每个用例前置
执行用例4, username02 登陆成功
每个用例的后置
.所有用例的后置
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
<unittest.runner.TextTestResult run=3 errors=0 failures=0>
巩固
# -*- coding: utf-8 -*-, | |
# @File : test_module.py, | |
# @Author : lidong, | |
# @IDEA: PyCharm | |
# @Time : 2022/4/25 16:57 | |
import unittest | |
class TestStringMethods(unittest.TestCase): | |
a = 67 | |
# 跳过被此装饰器装饰的测试。 reason 为测试被跳过的原因。 | |
def test_upper(self): | |
print('test_upper') | |
# 当condition为真时,跳过被装饰的测试。 | |
def test_upper2(self): | |
print('test_upper2') | |
# 跳过被装饰的测试,condition 为假 | |
def test_upper3(self): | |
print('test_upper3') | |
def test_upper5(self): | |
self.assertEqual('foo'.upper(), 'FOO') | |
def test_isupper(self): | |
self.assertTrue('FOO'.isupper()) | |
self.assertFalse('Foo'.isupper()) | |
def test_split(self): | |
s = 'hello world' | |
self.assertEqual(s.split(), ['hello', 'world']) | |
# check that s.split fails when the separator is not a string | |
with self.assertRaises(TypeError): | |
s.split(2) | |
if __name__ == '__main__': | |
unittest.main() |
运行
=============================================================================== | |
[SKIPPED] | |
取消测试 | |
unitTest.testCase.test_module.TestStringMethods.test_upper | |
unitTest.testCase.test_module.TestStringMethods.test_upper2 | |
=============================================================================== | |
[SKIPPED] | |
跳过被装饰的测试 | |
unitTest.testCase.test_module.TestStringMethods.test_upper3 | |
------------------------------------------------------------------------------- | |
Ran 6 tests in 0.093s | |
PASSED (skips=3, successes=3) | |
Process finished with exit code 0 | |
Skipped: 取消测试 | |
Skipped: 取消测试 | |
Skipped: 跳过被装饰的测试 |