unittest组成包括以下4个核心部分:
1.测试用例–继承unittest.TestCase
class 测试类名(unittest.Test):
#执行测试用例前的准备操作,每个测试用例执行前都会被执行
def setUp(self):
pass
#测试方法名需要以test开头
def test测试用例1(self):
pass
#执行完测试用例后的清理操作,每个测试用例执行完都会被执行
def tearDown(self):
pass
#被测试代码
class Calc(object):
def add(self, x, y):
# 加法计算
result = x + y
return result
def sub(self, x, y):
# 减法计算
result = x - y
return result
@classmethod
def mul(cls, x, y):
# 乘法计算
result = x * y
return result
if __name__=="__main__":
c=Calc()
print (c.add(1,2))
print (c.sub(5,2))
测试代码:
import unittest
import random
import Calc
class CalcTest(unittest.TestCase):
def setUp(self):
#生成被测试类的实例,存在实例变量中
self.cal = Calc.Calc()
print ("setup completed!")
def test_add(self):
result = self.cal.add(1,2)
self.assertTrue(result==3)
#assert 3==result
def test_sub(self):
result = self.cal.sub(5,1)
self.assertTrue(result==4)
def tearDown(self):
print ("tearDown completed")
if __name__ == '__main__':
unittest.main()
2.跳过测试用例
组织形式:
@unittest.skip(reason) #无条件跳过该测试用例
Unconditionally skip the decorated test. reason should describe why the test is being skipped.
@unittest.skipIf(condition, reason)#满足指定条件跳过该测试用例
Skip the decorated test if condition is true.
@unittest.skipUnless(condition, reason)#满足指定条件执行该测试用例
Skip the decorated test unless condition is true.
代码示例:
import unittest
import random
import Calc
class CalcTest(unittest.TestCase):
a = 1
def setUp(self):
#生成被测试类的实例,存在实例变量中
self.cal = Calc.Calc()
print ("setup completed!")
@unittest.skip("skipping") # 无条件忽略该测试方法
def test_add(self):
result = self.cal.add(1,2)
self.assertTrue(result==3)
#assert 3==result
# 如果变量a > 5,则忽略该测试方法
@unittest.skipIf(a > 5, "condition is not satisfied!")
def test_sub(self):
result = self.cal.sub(5,1)
self.assertTrue(result==4)
# 除非执行测试用例的平台是Linux平台,否则忽略该测试方法 win32是windows
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_mul(cls):
result = self.cal.mul(2,3)
self.assertTrue(result==6)
def tearDown(self):
print ("tearDown completed")
if __name__ == '__main__':
unittest.main()
3.测试套件
import unittest
from Calc import Calc
class TestCalc(unittest.TestCase):
代码略
def suite():
#生成测试套件实例
calcTestCase = unittest.TestSuite()
#使用实例的addTest方法,将测试类中TestCalc的测试方法test_add加入到测试套件中
calcTestCase.addTest(CalcTest("test_add"))
calcTestCase.addTest(CalcTest("test_sub"))
return calcTestCase
import unittest
from Calc import Calc
class CalcTestOne(unittest.TestCase):
代码略
class CalcTestTwo(unittest.TestCase):
代码略
class CalcTestThree(unittest.TestCase):
代码略
def suite():
# 根据给定的测试类,获取其中的所有以“test”开头的测试方法,并返回一个测试套件
suite1 = unittest.TestLoader().loadTestsFromTestCase(CalcTestOne)
suite2 = unittest.TestLoader().loadTestsFromTestCase(CalcTestTwo)
suite3 = unittest.TestLoader().loadTestsFromTestCase(CalcTestThree)
# 将多个测试类加载到测试套件中
#通过调整suit2和suite1的顺序,可以设定执行顺序
suite = unittest.TestSuite([suite2, suite1,suite3])
return suite
4.运行测试用例
import unittest
from Calc import Calc
class CalcTestOne(unittest.TestCase):
代码略
class CalcTestTwo(unittest.TestCase):
代码略
def suite():
代码略
if __name__=="__main__":
unittest.main()
import unittest
from Calc import Ca
class CalcTestOne(unittest.TestCase):
代码略
class CalcTestTwo(unittest.TestCase):
代码略
def suite():
代码略
if __name__=="__main__":
runner = unittest.TextTestRunner()
runner.run(suite())
5.断言
Method | Checks that |
---|---|
assertEqual(a, b) | a == b |
assertNotEqual(a, b) | a != b |
assertTrue(x) | bool(x) is True |
assertFalse(x) | bool(x) is False |
assertIs(a, b) | a is b |
assertIsNot(a, b) | a is not b |
assertIsNone(x) | x is None |
assertIsNot(x) | x is not None |
assertIn(a, b) | a in b |
assertNotIn(a, b) | a not in b |
assertIsInstance(a, b) | isinstance(a, b) |
assertNotIsInstance(a, b) | not isinstance(a, b) |
assertMultiLineEqual(a, b) | strings |
assertSequenceEqual(a, b) | sequences |
assertListEqual(a, b) | lists |
assertTupleEqual(a, b) | tuples |
assertSetEqual(a, b) | sets or frozensets |
assertDictEqual(a, b) | dicts |
assertRaises(exc, fun, *args, **kwds) | fun(*args, **kwds) raises exc |
assertRaisesRegex(exc, r, fun, *args, **kwds) | fun(*args, **kwds) raises exc and the message matches regex r |
assertWarns(warn, fun, *args, **kwds) | fun(*args, **kwds) raises warn |
assertWarnsRegex(warn, r, fun, *args, **kwds) | fun(*args, **kwds) raises warn and the message matches regex r |
assertLogs(logger, level) | The with block logs on logger with minimum level |
assertAlmostEqual(a, b) | round(a-b, 7) == 0 |
assertNotAlmostEqual(a, b) | round(a-b, 7) != 0 |
assertGreater(a, b) | a > b |
assertGreaterEqual(a, b) | a >= b |
assertLess(a, b) | a < b |
assertLessEqual(a, b) | a <= b |
assertRegex(s, r) | r.search(s) |
assertNotRegex(s, r) | not r.search(s) |
assertCountEqual(a, b) | a and b have the same elements in the same number, regardless of their order. |
class MyTest(unittest.TestCase):
# assertEqual()方法实例
def test_assertEqual(self):
# 断言两数之和的结果
try:
a, b = 1, 2
sum = 3
self.assertEqual(a + b, sum, '断言失败,%s + %s != %s' %(a, b, sum))
except AssertionError as e:
print (e)
# assertNotEqual()方法实例
def test_assertNotEqual(self):
# 断言两数之差的结果
try:
a, b = 5, 2
res = 1
self.assertNotEqual(a - b, res, '断言失败,%s - %s != %s' %(a, b, res))
except AssertionError as e:
print (e)
# assertTrue()方法实例
def test_assertTrue(self):
# 断言表达式的为真
try:
self.assertTrue(1 == 1, "表达式为假")
except AssertionError as e:
print (e)
# assertFalse()方法实例
def test_assertFalse(self):
# 断言表达式为假
try:
self.assertFalse(3 == 2, "表达式为真")
except AssertionError as e:
print (e)
# assertIs()方法实例
def test_assertIs(self):
# 断言两变量类型属于同一对象
try:
a = 12
b = a
self.assertIs(a, b, "%s与%s不属于同一对象" %(a, b))
except AssertionError as e:
print (e)
# test_assertIsNot()方法实例
def test_assertIsNot(self):
# 断言两变量类型不属于同一对象
try:
a = 12
b = "test"
self.assertIsNot(a, b, "%s与%s属于同一对象" %(a, b))
except AssertionError as e:
print (e)
# assertIsNone()方法实例
def test_assertIsNone(self):
# 断言表达式结果为None
try:
result = MyClass.retrun_None()
self.assertIsNone(result, "not is None")
except AssertionError as e:
print (e)
# assertIsNotNone()方法实例
def test_assertIsNotNone(self):
# 断言表达式结果不为None
try:
result = MyClass.sum(2, 5)
self.assertIsNotNone(result, "is None")
except AssertionError as e:
print (e)
# assertIn()方法实例
def test_assertIn(self):
# 断言对象A是否包含在对象B中
try:
strA = "this is a test"
strB = "is"
self.assertIn(strB, strA, "%s不包含在%s中" %(strB, strA))
except AssertionError as e:
print (e)
# assertNotIn()方法实例
def test_assertNotIn(self):
# 断言对象A不包含在对象B中
try:
strA = "this is a test"
strB = "Selenium"
self.assertNotIn(strB, strA, "%s包含在%s中" %(strB, strA))
except AssertionError as e:
print (e)
# assertIsInstance()方法实例
def test_assertIsInstance(self):
# 测试对象A的类型是否值指定的类型
try:
x = MyClass
y = object
self.assertIsInstance(x, y, "%s的类型不是%s" %(x, y))
except AssertionError as e:
print (e)
# assertNotIsInstance()方法实例
def test_assertNotIsInstance(self):
# 测试对象A的类型不是指定的类型
try:
a = 123
b = str
self.assertNotIsInstance(a, b, "%s的类型是%s" %(a, b))
except AssertionError as e:
print (e)
# assertRaises()方法实例
def test_assertRaises(self):
# 测试抛出的指定的异常类型
# assertRaises(exception)
with self.assertRaises(TypeError) as cm:
random.sample([1,2,3,4,5], "j")
# 打印详细的异常信息
#print "===", cm.exception
# assertRaises(exception, callable, *args, **kwds)
try:
self.assertRaises(ZeroDivisionError, MyClass.div, 3, 0)
except ZeroDivisionError as e:
print (e)
# assertRaisesRegexp()方法实例
def test_assertRaisesRegexp(self):
# 测试抛出的指定异常类型,并用正则表达式具体验证
# assertRaisesRegexp(exception, regexp)
with self.assertRaisesRegex(ValueError, 'literal') as ar:
int("xyz")
# 打印详细的异常信息
#print ar.exception
# 打印正则表达式
#print "re:",ar.expected_regexp
# assertRaisesRegexp(exception, regexp, callable, *args, **kwds)
try:
self.assertRaisesRegexp(ValueError, "invalid literal for.*XYZ'$", int, 'XYZ')
except AssertionError as e:
print (e)
if __name__ == '__main__':
# 执行单元测试
unittest.main()
6.生成测试报告
事前准备
HTMLTestRunner扩展模块无法通过pip安装,下载完成后将HTMLTestRunner.py文件放到Python安装目录的lib文件下方可使用
代码示例
import unittest
from Calc import Ca
class CalcTestOne(unittest.TestCase):
代码略
class CalcTestTwo(unittest.TestCase):
代码略
if __name__=="__main__":
suite1 = unittest.TestLoader().loadTestsFromTestCase(CalcTestOne)
suite2 = unittest.TestLoader().loadTestsFromTestCase(CalcTestTwo)
suite = unittest.TestSuite([suite1, suite2])
#unittest.TextTestRunner(verbosity=2).run(suite)
filename = "e:\\pyScripts\\test.html" # 定义个报告存放路径,支持相对路径
# 以二进制方式打开文件,准备写
fp = open(filename, 'wb')
# 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
title = u'测试报告', description = u'测试报告内容')
# 运行测试集合
runner.run(suite)
7.执行顺序
setUpModule()
setUpClass()
setUp()
tearDown()
tearDownClass()
tearDownModule()
setUpClass()
A class method called before tests in an individual class are run. setUpClass is called with the class as the only argument and must be decorated as a classmethod():
@classmethod
def setUpClass(cls):
...
tearDownClass()
A class method called after tests in an individual class have run. tearDownClass is called with the class as the only argument and must be decorated as a classmethod():
@classmethod
def tearDownClass(cls):
...
import unittest
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._connection = createExpensiveConnectionObject()
@classmethod
def tearDownClass(cls):
cls._connection.destroy()