创建demo.py
# 1.导包
import unittest
# 2.自定义测试类,需要继承unittest模块中的TestCase类
class TestDemo(unittest.TestCase):
# 3.书写测试方法
# 书写要求:测试方法必须以test_开头
def test_method1(self):
print('测试方法1')
def test_method2(self):
print('测试方法2')
# 4.执行用例(方法)
# 4.1将光标放在类名的后边运行
# 4.2将光标放在方法名的后边运行,只执行当前的方法
创建demo1.py,demo2.py
创建suite_runner.py
# 1.导包
import unittest
from demo1 import TestDemo1
from demo2 import TestDemo2
# 2.实例化(创建对象)套件对象
suite = unittest.TestSuite()
# 3.使用套件对象添加用例方法
# 方式1:套件对象.addTest(测试类名('方法名'))
suite.addTest(TestDemo1('test_method1'))
suite.addTest(TestDemo1('test_method2'))
suite.addTest(TestDemo2('test_method1'))
suite.addTest(TestDemo2('test_method2'))
# 方式2:将一个测试类中的所有方法进行添加 套件对象.addTest(unittest.makeSuite(测试类名))
suite.addTest(unittest.makeSuite(TestDemo1))
suite.addTest(unittest.makeSuite(TestDemo2))
# 4.实例化运行对象
runner = unittest.TextTestRunner()
# 5.使用运行对象去执行套件对象
runner.run(suite)
运行结果中 . 用例通过,F 用例不通过, E error 用例代码有问题
创建tools.py
def add(a, b):
return a + b
创建test,test1,test2
import unittest
from tools import add
class TestAdd(unittest.TestCase):
def test_method1(self):
if add(1, 2) == 3:
print('测试通过1')
else:
print('测试不通过2')
def test_method2(self):
if add(10, 20) == 30:
print('测试通过1')
else:
print('测试不通过2')
def test_method3(self):
if add(2, 2) == 5:
print('测试通过1')
else:
print('测试不通过2')
创建testloader.py
# 1.导包
import unittest
# 2.实例化加载对象并添加用例
# unittest.TestLoader().discover('用例所在的路径','用例的代码文件名')
suite = unittest.TestLoader().discover('./case', '*.py')
# 3.实例化运行对象
# runner = unittest.TextTestRunner()
# 4.执行
# runner.run(suite)
# 可以将3.4.5变为一步
unittest.TextTestRunner().run(suite)
使用默认对象的写法:
# 1.导包
import unittest
# 2.使用默认的加载对象并加载用例
suite=unittest.defaultTestLoader.discover('case','*.py')
# 可以将3.4.5变为一步
unittest.TextTestRunner().run(suite)
方法级别和类级别,前后的方法,不需要同时出现,根据用例代码的需要自行选择使用
在每个测试方法(用例代码)执行前后都会自动调用的结果
# 方法执行之前
def setUp(self):
每个测试方法执行前都会执行
pass
# 方法执行之后
def tearDown(self):
每个测试方法执行之后都会执行
pass
在每个测试类中所有方法执行前后都会自动调用的结构(在整个类中执行之前执行之后各一次)
# 类级别的Fixture方法,是一个类方法
# 类中所有方法之前
@classmethod
def setUpClass(cls):
pass
@classmethod
def tearDownClass(cls):
pass
在每个代码文件执行前后执行的代码结构
# 模块级别的需要写在类的外边直接定义函数即可
# 代码文件之前
def setUpModule():
pass
# 代码文件之后
def tearDownModule():
pass
1.打开浏览器(整个测试过程中只打开一次浏览器) 类级别
2.输入网址 (每个测试方法都要一次) 方法级别
3.输入用户名密码验证码点击登录(不同的测试数据)测试方法
4.关闭当前页面(每个测试方法都要一次) 方法级别
5.关闭浏览器 (整个测试过程中只关闭一次浏览器)类级别
创建fixture.py
import unittest
class TestLogin(unittest.TestCase):
def setUp(self):
'''每个测试方法执行前都会先调用的方法'''
print('输入网址...')
def tearDown(self) -> None:
'''每个测试方法执行后都会调用的方法'''
print('关闭当前页面...')
@classmethod
def setUpClass(cls) -> None:
print('...1.打开浏览器')
@classmethod
def tearDownClass(cls) -> None:
print('...5。关闭浏览器')
def test_1(self):
print('输入用户名密码验证码,点击登录 1')
def test_2(self):
print('输入用户名密码验证码,点击登录 2')
创建tools.py:
def login(username, password):
if username == 'admin' and password == '123456':
return '登录成功'
else:
return '登录失败'
创建login_test.py:
import unittest
from tools import login
class TestLogin(unittest.TestCase):
def test_username_password_ok(self):
if login('admin', '123456') == '登录成功':
print('pass')
else:
print('fail')
def test_username_error(self):
if login('root', '123456') == '登录失败':
print('pass')
else:
print('fail')
def test_password_error(self):
if login('admin', '123123') == '登录失败':
print('pass')
else:
print('fail')
def test_username_password_error(self):
if login('root', '123123') == '登录失败':
print('pass')
else:
print('fail')
断言结果有两种:true 用例通过 ; false 代码抛出异常,用例不通过
在unittest中使用断言,都要通过self. 断言方法
assertEqual
:判断预期结果和实际结果是否相等
self.assertEqual(预期结果,实际结果)
assertIn
:判断预期结果是否包含在实际结果中
self.assertIn(预期结果,实际结果)
创建assert.py
import unittest
from tools import login
class TestLogin(unittest.TestCase):
def test_username_password_ok(self):
self.assertEqual('登录成功',login('admin', '123456'))
'''
if login('admin', '123456') == '登录成功':
print('pass')
else:
print('fail')
'''
def test_username_error(self):
self.assertEqual('登录失败', login('root', '123456'))
def test_password_error(self):
self.assertEqual('登录失败', login('admin', '123123'))
def test_username_password_error(self):
#self.assertEqual('登录失败', login('root', '123123'))
self.assertIn('失败', login('root', '123123'))
在测试方法中,使用变量来代替具体的测试数据,然后使用传参的方法将测试数据传递给方法的变量
好处:相似的代码不需要多次书写
安装插件:pip install parameterized
,使用pip list
查看已安装插件
1.导包:unittest/ pa
2.定义测试类
3.书写测试方法(测试数据使用变量代替)
4.组织测试数据并传参
创建pa.py
# 1.导包:unittest/ pa
import unittest
from parameterized import parameterized
from tools import login
# 2.定义测试类
# 组织测试数据 [(),(),()] or [[],[],[]]
data = [
('admin', '123456', '登录成功'), # 与测试方法中参数顺序保持一致
('root', '123456', '登录失败'),
('admin', '123123', '登录失败')
]
class TestLogin(unittest.TestCase):
# 3.书写测试方法(测试数据使用变量代替)
@parameterized.expand(data) # 4.组织测试数据并传参(装饰器@)
def test_login(self, username, password, expect):
self.assertEqual(expect, login(username, password))
创建data.json
[
{
"desc": "正确的用户名和密码",
"username": "admin",
"password": "123456",
"expect": "登录成功"
},
{
"desc": "错误的用户名和密码",
"username": "root",
"password": "123123",
"expect": "登录失败"
},
{
"desc": "错误的用户名",
"username": "root",
"password": "123456",
"expect": "登录失败"
}
]
修改pa.py
# 1.导包:unittest/ pa
import json
import unittest
from parameterized import parameterized
from tools import login
# 2.定义测试类
# 组织测试数据 [(),(),()] or [[],[],[]] 列表套元组 或 列表套列表
def build_data():
with open('data.json', encoding='utf-8') as f:
result = json.load(f) # [{},{},{}]
data = []
for i in result: # i 是每一个字典
data.append((i.get('username'), i.get('password'), i.get('expect')))
return data
class TestLogin(unittest.TestCase):
# 3.书写测试方法(测试数据使用变量代替)
@parameterized.expand(build_data())
def test_login(self, username, password, expect):
self.assertEqual(expect, login(username, password))
# 4.组织测试数据并传参(装饰器@)
对于一些未完成的或者不满足测试条件的测试函数和测试类,不想执行,可以跳过
书写在TestCase文件中:
@unittest.skip('跳过的原因')
直接将测试函数标记成跳过
@unittest.skipIf(判断条件,'跳过原因')
根据条件判断测试函数是否跳过
import unittest
version = 30
class TestDemo(unittest.TestCase):
@unittest.skip('没有原因,跳过')
def test_1(self):
print('测试方法1')
@unittest.skipIf(version >= 30, '版本大于等于30,不用测试')
def test_2(self):
print('测试方法2')
def test_3(self):
print('测试方法3')
HTMLTestRunner
1.获取第三方的测试运行类模块,放入代码目录
2.导包unittest
3.使用套件对象,加载对象 添加用例方法
4.实例化第三方的运行对象,并运行套件对象
创建test.py
# 1.获取第三方的测试运行类模块,放入代码目录
# 2.导包unittest
import unittest
from HTMLTestRunner import HTMLTestRunner
# 3.使用套件对象,加载对象 添加用例方法
suite = unittest.defaultTestLoader.discover('.', 'paj.py')
# 4.实例化第三方的运行对象,并运行套件对象
#HTMLTestRunner()
# stream=sys.stdout, 测试报告的文件对象(open),要使用wb打开
# verbosity=1, 可选,报告的详细程度,默认 1 简略,2 详细
# title=None, 可选,测试报告标题
# description=None 描述信息,python版本等等
file = 'report.html' # 报告的后缀是.html
with open(file, 'wb') as f:
runner = HTMLTestRunner(f,2,'测试报告','python 3.7') # 运行对象
# 运行对象执行套件
runner.run(suite)
创建report_ch.py
import unittest
from HTMLTestRunnerCN import HTMLTestReportCN
suite = unittest.defaultTestLoader.discover('.', 'paj.py')
# HTMLTestReportCN()
# stream=sys.stdout, verbosity=1,title=None,description=None,tester=None
with open('report_cn.html', 'wb') as f:
runner = HTMLTestReportCN(f)
runner.run(suite)