目录
示例2:setUpClass()和tearDownClass()
示例3:通过在测试用例方法名中添加数字test_N指定执行顺序
转载于文章Python必会的单元测试框架 —— unittest
unittest中最核心的四个概念是:test case, test suite, test runner, test fixture。

- 一个TestCase的实例就是一个测试用例。什么是测试用例呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。单元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。
- 而多个测试用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite。
- TestLoader是用来加载TestCase到TestSuite中的,其中有几个loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例。
- TextTestRunner是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法。
- 测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。
- 而对一个测试用例环境的搭建和销毁,是一个Fixture。
一个class继承了unittest.TestCase,便是一个测试用例,但如果其中有多个以 test 开头的方法,那么每有一个这样的方法,在load的时候便会生成一个TestCase实例,如:一个class中有四个test_xxx方法,最后在load到suite中时也有四个测试用例。
到这里整个流程就清楚了:
写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,我们通过命令行或者unittest.main()执行时,main会调用TextTestRunner中的run来执行,或者我们可以直接通过TextTestRunner来执行用例。这里加个说明,在Runner执行时,默认将执行结果输出到控制台,我们可以设置其输出到文件,在文件中查看结果(你可能听说过HTMLTestRunner,是的,通过它可以将结果输出到HTML中,生成漂亮的报告,它跟TextTestRunner是一样的,从名字就能看出来)。
- #encoding=utf-8
- import unittest
- import random
- class TestSequenceFunctions(unittest.TestCase):
- def setUp(self):
- # 初始化一个递增序列
- self.seq = list(range(10))
- print ("setup completed!")
-
- def test_run(self):
- # 从序列seq中随机选取一个元素
- element = random.choice(self.seq)
- # 验证随机元素确实属于列表中
- self.assertTrue(element in self.seq)
-
- def test_sth(self):
- assert 1==2
-
- def tearDown(self):
- print ("tearDown completed")
-
- class TestDictValueFormatFunctions(unittest.TestCase):
- def setUp(self):
- self.seq = list(range(10))
- print("setup is ready!")
-
- def test_shuffle(self):
- # 随机打乱原seq的顺序
- random.shuffle(self.seq)
- self.seq.sort()
- self.assertEqual(self.seq, list(range(10)))
- # 验证执行函数时抛出了TypeError异常
- self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
-
- def tearDown(self):
- print ("tearDown is Done!")
-
- if __name__ == '__main__':
- unittest.main()
执行结果:
- setup is ready!
- tearDown is Done!
- .setup completed!
- tearDown completed
- .setup completed!
- tearDown completed
- F
- ======================================================================
- FAIL: test_sth (__main__.TestSequenceFunctions)
- ----------------------------------------------------------------------
- Traceback (most recent call last):
- File "F:\unittest\e1_unittest_demo.py", line 17, in test_sth
- assert 1==2
- AssertionError
-
- ----------------------------------------------------------------------
- Ran 3 tests in 0.027s
-
- FAILED (failures=1)
说明:
- 可以看到一共运行了3个测试用例,2个成功,1个失败,并给出失败原因:1==2
- 每一个用例执行的结果的标识,成功是
.,失败是F,出错是E,跳过是S- setUp()和tearDown()分别执行了3次,在每个测试用例执行前后分别执行了setUp和tearDown方法
- 每个测试方法均以
test开头,否则是不被unittest识别的- 可以看到测试的执行跟方法写的位置顺序没有关系,测试用例的默认执行顺序是根据用例名的字母顺序来的,先执行了TestDictValueFormatFunctions类中的test_shuffle,然后执行了TestSequenceFunctions类中的test_run,最后执行了TestSequenceFunctions中类的test_sth
- #encoding=utf-8
- import unittest
-
- # 被测试类
- class myclass(object):
- @classmethod
- def sum(self, a, b):
- return a + b #将两个传入参数进行相加操作
-
- @classmethod
- def sub(self, a, b):
- return a - b #将两个传入参数进行相减操作
-
-
- class mytest(unittest.TestCase):
- @classmethod
- def setUpClass(cls):#每个测试类的setUpClass方法,只会执行一次
- "初始化类固件"
- print ( "----setUpClass")
-
- @classmethod
- def tearDownClass(cls):#每个测试类的tearDownClass方法,只会执行一次
- "重构类固件"
- print ( "----tearDownClass")
-
- # 初始化工作
- def setUp(self):#每个测试方法均会执行一次
- self.a = 3
- self.b = 1
- print ( "--setUp")
-
- # 退出清理工作
- def tearDown(self):#每个测试方法均会执行一次
- print ( "--tearDown")
-
- # 具体的测试用例,一定要以test开头
- def testsum(self):
- # 断言两数之和的结果是否是4
- self.assertEqual(myclass.sum(self.a, self.b), 4, 'test sum fail')
-
- def testsub(self):
- # 断言两数之差的结果是否是2
- self.assertEqual(myclass.sub(self.a, self.b), 2, 'test sub fail')
-
-
- if __name__ == '__main__':
- unittest.main() # 启动单元测试
执行结果:
- ----setUpClass
- --setUp
- --tearDown
- .--setUp
- --tearDown
- .----tearDownClass
-
- ----------------------------------------------------------------------
- Ran 2 tests in 0.011s
-
- OK
说明:
setUpClass()和tearDownClass()分别在每个测试类执行前后各执行一次(不管这个测试类中有多少个测试方法,它们都仅执行一次);而setUp()和tearDown()分别在每个测试方法执行前后各执行一次。
Calc.py
- # coding=utf-8
- class Calc(object):
-
- def add(self, x, y, *d):
- # 加法计算
- result = x + y
- for i in d:
- result += i
- return result
-
- def sub(self, x, y, *d):
- # 减法计算
- result = x - y
- for i in d:
- result -= i
- return result
-
- @classmethod
- def mul(cls, x, y, *d):
- # 乘法计算
- result = x * y
- for i in d:
- result *= i
- return result
-
- @staticmethod
- def div(x, y, *d):
- # 除法计算
- if y != 0:
- result = x / y
- else:
- raise ZeroDivisionError
- return -1
- for i in d:
- if i != 0:
- result /= i
- else:
- raise ZeroDivisionError
- return -1
- return result
-
- if __name__=="__main__":
- c=Calc()
- print (c.add(1,2,3,4))
- #print c.add(1,2,[3,4],5,a=3))
- print (c.sub(1,2,3,4))
- print (c.mul(2,3,4))
- print (c.div(10,5,1))
- print (c.div(1,0,0))
- print (c.div(1,1,0))
- print (Calc.mul(1,2,3,4))
- print (Calc.div(100,10,5,1))
e3_Test_Calc_by_specific_order.py
- #encoding=utf-8
- import unittest
- from Calc import Calc
-
- class MyTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(self):
- print ("单元测试前,创建Calc类的实例")
- self.c = Calc()
-
- def test_3div(self):
- print ("run div()")
- self.assertEqual(Calc.div(8, 2, 4), 1, 'test div fail')
-
- # 具体的测试用例,一定要以test开头,执行顺序按照字母顺序开头
- def test_0add(self):
- print ("run add()")
- self.assertEqual(self.c.add(1, 2, 12), 15, 'test add fail')
-
- def test_1sub(self):
- print ("run sub()")
- self.assertEqual(self.c.sub(2, 1, 3), -2, 'test sub fail')
-
- def test_2mul(self):
- print ("run mul()")
- self.assertEqual(Calc.mul(2, 3, 5), 30, 'test mul fail')
-
-
- if __name__ == '__main__':
- unittest.main()# 启动单元测试
执行结果:
- 单元测试前,创建Calc类的实例
- run add()
- .run sub()
- .run mul()
- .run div()
- .
- ----------------------------------------------------------------------
- Ran 4 tests in 0.020s
-
- OK
可以发现执行顺序变成我们指定的0add-1sub-2mul-3div顺序
- # coding=utf-8
- import random
- import unittest
- import sys
-
- class TestSequenceFunctions(unittest.TestCase):
- a = 6
-
- def setUp(self):
- self.seq = list(range(10))
-
- @unittest.skip("skipping") # 无条件忽略该测试方法
- def test_shuffle(self):
- random.shuffle(self.seq)
- self.seq.sort()
- self.assertEqual(self.seq, list(range(10)))
- self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
-
- # 如果变量a > 5,则忽略该测试方法
- @unittest.skipIf(a > 5, "condition is not satisfied!")
- def test_choice(self):
- element = random.choice(self.seq)
- self.assertTrue(element in self.seq)
-
- # 除非执行测试用例的平台是Linux平台,否则忽略该测试方法 win32是windows
- @unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
- def test_sample(self):
- with self.assertRaises(ValueError):
- random.sample(self.seq, 20)
- for element in random.sample(self.seq, 5):
- self.assertTrue(element in self.seq)
-
-
- if __name__ == '__main__':
- # unittest.main()
- suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)# 加载TestSequenceFunctions测试类
- suite = unittest.TestSuite(suite)#
- unittest.TextTestRunner(verbosity = 2).run(suite)
执行结果:
- test_choice (__main__.TestSequenceFunctions) ... skipped 'condition is not satisfied!'
- test_sample (__main__.TestSequenceFunctions) ... skipped 'requires Linux'
- test_shuffle (__main__.TestSequenceFunctions) ... skipped 'skipping'
-
- ----------------------------------------------------------------------
- Ran 3 tests in 0.001s
-
- OK (skipped=3)
可以看到上面3个测试方法都被跳过。并打印了自定义的跳过原因信息
- skip装饰器一共有三个 unittest.skip(reason)、unittest.skipIf(condition, reason)、unittest.skipUnless(condition, reason),skip无条件跳过,skipIf当condition为True时跳过,skipUnless当condition为False时跳过。
- verbosity 参数可以控制输出的错误报告的详细程度,默认是 1,如果设为 0,则不输出每一用例的执行结果,即没有. F S E这种结果输出;如果设为 2,则输出详细的执行结果
testCalc.py
- #encoding=utf-8
- import unittest
- import random
- from Calc import Calc
-
- class TestCalcFunctions(unittest.TestCase):
- def setUp(self):
- self.c=Calc()
- print ("setup completed!")
-
- def test_sum(self):
- """TestCalcFunctions.test_sum()"""
- self.assertTrue(self.c.add(1,2,3,4)==10)
-
- def test_sub(self):
- self.assertTrue(self.c.sub(100,20,30,40)==10)
-
- def test_mul(self):
- self.assertTrue(self.c.mul(1,2,3,40)==240)
-
- def test_div(self):
- self.assertTrue(self.c.div(100,10,2)==5)
-
- def tearDown(self):
- print ("test completed!")
-
- def tearDown(self):
- print ("tearDown completed")
-
- if __name__ == '__main__':
- unittest.main()
e5_unittest_suite.py
- #encoding=utf-8
- import random
- import unittest
- from TestCalc import TestCalcFunctions
-
- class TestSequenceFunctions(unittest.TestCase):
- def setUp(self):
- self.seq = list(range(10))
-
- def tearDown(self):
- pass
-
- def test_choice(self):
- """TestSequenceFunctions.test_choice()"""
- # 从序列seq中随机选取一个元素
- element = random.choice(self.seq)
- # 验证随机元素确实属于列表中
- self.assertTrue(element in self.seq)
-
- def test_sample(self):
- """TestSequenceFunctions.test_sample()"""
- # 验证执行的语句是否抛出了异常
- with self.assertRaises(ValueError):
- random.sample(self.seq, 20)
- for element in random.sample(self.seq, 5):
- self.assertTrue(element in self.seq)
-
-
- class TestDictValueFormatFunctions(unittest.TestCase):
- def setUp(self):
- self.seq = list(range(10))
-
- def tearDown(self):
- pass
-
- def test_shuffle(self):
- """TestDictValueFormatFunctions.test_shuffle()"""
- # 随机打乱原seq的顺序
- random.shuffle(self.seq)
- self.seq.sort()
- self.assertEqual(self.seq, list(range(10)))
- # 验证执行函数时抛出了TypeError异常
- self.assertRaises(TypeError, random.shuffle, (1, 2, 3))
-
- if __name__ == '__main__':
- # 根据给定的测试类,获取其中的所有以“test”开头的测试方法,并返回一个测试套件
- suite1 = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
- suite2 = unittest.TestLoader().loadTestsFromTestCase(TestDictValueFormatFunctions)
- suite3 = unittest.TestLoader().loadTestsFromTestCase(TestCalcFunctions)
- # 加载当前目录下所有有效的测试模块(以test开头的文件),“.”表示当前目录
- # testSuite = unittest.TestLoader().discover('.') #.可以改为绝对路径
- # 将多个测试类加载到测试套件中
- suite = unittest.TestSuite([suite2, suite1,suite3]) #通过调整suit2和suite1的顺序,可以设定执行顺序
- # 设置verbosity = 2,可以打印出更详细的执行信息
- unittest.TextTestRunner(verbosity = 2).run(suite)
执行结果:
- test_shuffle (__main__.TestDictValueFormatFunctions)
- TestDictValueFormatFunctions.test_shuffle() ... ok
- test_choice (__main__.TestSequenceFunctions)
- TestSequenceFunctions.test_choice() ... ok
- test_sample (__main__.TestSequenceFunctions)
- TestSequenceFunctions.test_sample() ... ok
- test_div (TestCalc.TestCalcFunctions) ... setup completed!
- tearDown completed
- ok
- test_mul (TestCalc.TestCalcFunctions) ... setup completed!
- tearDown completed
- ok
- test_sub (TestCalc.TestCalcFunctions) ... setup completed!
- tearDown completed
- ok
- test_sum (TestCalc.TestCalcFunctions)
- TestCalcFunctions.test_sum() ... setup completed!
- tearDown completed
- ok
-
- ----------------------------------------------------------------------
- Ran 7 tests in 0.011s
-
- OK
说明:
- 我们添加到TestSuite中的case是会按照添加的顺序执行的。通过调整suite2和suite1的顺序,指定了执行的顺序。先执行的是TestDictValueFormatFunctions.test_shuffle(),然后依次执行的TestSequenceFunctions类中的test_choice()和test_sample(),最后执行的TestCalcFunctions类中的test_div()、test_mul()、test_sub()、test_sum()
- 在测试方法下加代码示例中的”“”Doc String”“”,在用例执行时,会将该字符串作为此用例的描述并输出,加合适的注释能够使输出的测试报告更加便于阅读
- #encoding=utf-8
- import unittest
- import random
-
- # 被测试类
- class MyClass(object):
- @classmethod
- def sum(self, a, b):
- return a + b
-
- @classmethod
- def div(self, a, b):
- return a / b
-
- @classmethod
- def retrun_None(self):
- return None
-
- # 单元测试类
- class MyTest(unittest.TestCase):
- # assertEqual()方法实例
- def test_assertEqual(self):
- # 断言两数之和的结果
- a, b = 1, 2
- sum = 4
- self.assertEqual(a + b, sum, '断言失败,%s + %s != %s' %(a, b, sum))
-
- # assertNotEqual()方法实例
- def test_assertNotEqual(self):
- # 断言两数之差的结果
- a, b = 5, 2
- res = 1
- self.assertNotEqual(a - b, res, '断言失败,%s - %s != %s' %(a, b, res))
-
- # assertTrue()方法实例
- def test_assertTrue(self):
- # 断言表达式的为真
- self.assertTrue(1 == 1, "表达式为假")
-
- # assertFalse()方法实例
- def test_assertFalse(self):
- # 断言表达式为假
- self.assertFalse(3 == 2, "表达式为真")
-
- # assertIs()方法实例
- def test_assertIs(self):
- # 断言两变量类型属于同一对象
- a = 12
- b = a
- self.assertIs(a, b, "%s与%s不属于同一对象" %(a, b))
-
- # test_assertIsNot()方法实例
- def test_assertIsNot(self):
- # 断言两变量类型不属于同一对象
- a = 12
- b = "test"
- self.assertIsNot(a, b, "%s与%s属于同一对象" %(a, b))
-
- # assertIsNone()方法实例
- def test_assertIsNone(self):
- # 断言表达式结果为None
- result = MyClass.retrun_None()
- self.assertIsNone(result, "not is None")
-
- # assertIsNotNone()方法实例
- def test_assertIsNotNone(self):
- # 断言表达式结果不为None
- result = MyClass.sum(2, 5)
- self.assertIsNotNone(result, "is None")
-
- # assertIn()方法实例
- def test_assertIn(self):
- # 断言对象A是否包含在对象B中
- strA = "this is a test"
- strB = "is"
- self.assertIn(strB, strA, "%s不包含在%s中" %(strB, strA))
-
- # assertNotIn()方法实例
- def test_assertNotIn(self):
- # 断言对象A不包含在对象B中
- strA = "this is a test"
- strB = "Selenium"
- self.assertNotIn(strB, strA, "%s包含在%s中" %(strB, strA))
-
- # assertIsInstance()方法实例
- def test_assertIsInstance(self):
- # 测试对象x的类型是否是指定的类型y
- x = MyClass
- y = object
- self.assertIsInstance(x, y, "%s的类型不是%s" %(x, y))
-
- # assertNotIsInstance()方法实例
- def test_assertNotIsInstance(self):
- # 测试对象A的类型不是指定的类型
- a = 123
- b = str
- self.assertNotIsInstance(a, b, "%s的类型是%s" %(a, b))
-
- # 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)
- self.assertRaises(ZeroDivisionError, MyClass.div, 3, 0)
-
- # assertRaisesRegex()方法实例
- def test_assertRaisesRegex(self):
- # 测试抛出的指定异常类型,并用正则表达式具体验证
- # assertRaisesRegexp(exception, regexp)
- # with self.assertRaisesRegex(ValueError, 'literal') as ar:
- # int("xyz")
- # 打印详细的异常信息
- # print(ar.exception)
- # 打印正则表达式
- # print("re:",ar.expected_regex)
-
- # assertRaisesRegexp(exception, regexp, callable, *args, **kwds)
- # try:
- self.assertRaisesRegex(ValueError, "invalid literal for.*XYZ'$", int, 'XYZ')
- # except AssertionError as e:
- # print (e)
-
-
- if __name__ == '__main__':
- # 执行单元测试
- unittest.main(verbosity=2)
执行结果:
- test_assertEqual (__main__.MyTest) ... FAIL
- test_assertFalse (__main__.MyTest) ... ok
- test_assertIn (__main__.MyTest) ... ok
- test_assertIs (__main__.MyTest) ... ok
- test_assertIsInstance (__main__.MyTest) ... ok
- test_assertIsNone (__main__.MyTest) ... ok
- test_assertIsNot (__main__.MyTest) ... ok
- test_assertIsNotNone (__main__.MyTest) ... ok
- test_assertNotEqual (__main__.MyTest) ... ok
- test_assertNotIn (__main__.MyTest) ... ok
- test_assertNotIsInstance (__main__.MyTest) ... ok
- test_assertRaises (__main__.MyTest) ... ok
- test_assertRaisesRegex (__main__.MyTest) ... ok
- test_assertTrue (__main__.MyTest) ... ok
-
- ======================================================================
- FAIL: test_assertEqual (__main__.MyTest)
- ----------------------------------------------------------------------
- Traceback (most recent call last):
- File "F:\unittest\e6_unittest_assert-2.py", line 26, in test_assertEqual
- self.assertEqual(a + b, sum, '断言失败,%s + %s != %s' %(a, b, sum))
- AssertionError: 3 != 4 : 断言失败,1 + 2 != 4
-
- ----------------------------------------------------------------------
- Ran 14 tests in 0.013s
-
- FAILED (failures=1)
| 断言方法 | 断言描述 | 备注 |
| assertEqual(arg1, arg2, msg=None) | 验证arg1=arg2,不等则fail | arg1 = arg2 |
| assertNotEqual(arg1, arg2, msg=None) | 验证arg1 != arg2, 相等则fail | arg1 != arg2 |
| assertTrue(expr, msg=None) | 验证expr是true,如果为false,则fail | bool(expr) IS true |
| assertFalse(expr,msg=None) | 验证expr是false,如果为true,则fail | bool(expr) IS false |
| assertIs(arg1, arg2, msg=None) | 验证arg1、arg2是同一个对象,不是则fail | arg1 is arg2 |
| assertIsNot(arg1, arg2, msg=None) | 验证arg1、arg2不是同一个对象,是则fail | arg1 not is arg2 |
| assertIsNone(expr, msg=None) | 验证expr是None,不是则fail | expr is one |
| assertIsNotNone(expr, msg=None) | 验证expr不是None,是则fail | expr not is one |
| assertIn(arg1, arg2, msg=None) | 验证arg1是arg2的子串,不是则fail | arg1 in arg2 |
| assertNotIn(arg1, arg2, msg=None) | 验证arg1不是arg2的子串,是则fail | arg1 not in arg2 |
| assertIsInstance(obj, cls, msg=None) | 验证obj是cls的实例,不是则fail | IsInstance(obj,cls) |
| assertNotIsInstance(obj, cls, msg=None) | 验证obj不是cls的实例,是则fail | not IsInstance(obj,cls) |
更多方法说明请参考python的unittest单元测试框架断言整理汇总
HTMLTestRunner是一个第三方的unittest HTML报告库,首先我们下载HTMLTestRunner.py,并放到当前目录下,或者你的’C:\Python310\Lib’下,就可以导入运行了。
下载地址:
- # coding=utf-8
- import unittest
- import HTMLTestRunner
- import math
-
- class Calc(object):
-
- def add(self, x, y, *d):
- # 加法计算
- result = x + y
- for i in d:
- result += i
- return result
-
- def sub(self, x, y, *d):
- # 减法计算
- result = x - y
- for i in d:
- result -= i
- return result
-
- class SuiteTestCalc(unittest.TestCase):
- def setUp(self):
- self.c = Calc()
-
- @unittest.skip("skipping")
- def test_Sub(self):
- print ("sub")
- self.assertEqual(self.c.sub(100, 34, 6), 61, u'求差结果错误!')
-
- def testAdd(self):
- print ("add")
- self.assertEqual(self.c.add(1, 32, 56), 89, u'求和结果错误!')
-
-
- class SuiteTestPow(unittest.TestCase):
- def setUp(self):
- self.seq = list(range(10))
-
- # @unittest.skipIf()
- def test_Pow(self):
- print ("Pow")
- self.assertEqual(pow(6, 3), 2161, u'求幂结果错误!')
-
- def test_hasattr(self):
- print ("hasattr")
- # 检测math模块是否存在pow属性
- self.assertTrue(hasattr(math, 'pow1'), u"检测的属性不存在!")
-
- if __name__ == "__main__":
- suite1 = unittest.TestLoader().loadTestsFromTestCase(SuiteTestCalc)
- suite2 = unittest.TestLoader().loadTestsFromTestCase(SuiteTestPow)
- suite = unittest.TestSuite([suite1, suite2])
- #unittest.TextTestRunner(verbosity=2).run(suite)
- filename = "test.html" # 定义个报告存放路径,支持相对路径。
- # 以二进制方式打开文件,准备写
- fp = open(filename, 'wb')
- # 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
- runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
- title = '测试报告', description = '测试报告内容')
- # 运行测试集合
- runner.run(suite)
- fp.close()
执行结果:

- #encoding=utf-8
- import unittest
- from selenium import webdriver
- from selenium.webdriver.common.by import By
- from selenium.webdriver.common.keys import Keys
- import time
- import HTMLTestRunner
-
- class GloryRoad(unittest.TestCase):
- def setUp(self):
- # 启动Firefox浏览器
- self.driver = webdriver.Chrome(executable_path = r"E:\Programs\Driver\chromedriver")
-
- def testSoGou(self):
- # 访问搜狗首页
- self.driver.get("http://sogou.com")
- # 清空搜索输入框默认内容
- self.driver.find_element(By.ID,"query").clear()
- # 在搜索输入框中输入“光荣之路自动化测试”
- self.driver.find_element(By.ID,"query").send_keys("WebDriver实战宝典")
- # 单击“搜索”按钮
- self.driver.find_element(By.ID,"stb").click()
- # 等待3秒
- time.sleep(3)
- assert "吴晓华" in self.driver.page_source, "页面中不存在要寻找的关键字!".encode("gbk")
-
-
- def testBing(self):
- # 访问bing首页
- self.driver.get("http://cn.bing.com")
- # 清空搜索输入框默认内容
- self.driver.find_element(By.ID, "sb_form_q").clear()
- # 在搜索输入框中输入“光荣之路自动化测试”
- self.driver.find_element(By.ID, "sb_form_q").send_keys("WebDriver实战宝典")
- # 单击“搜索”按钮,目前已经不能点击该label
- # self.driver.find_element(By.ID, "sb_form_go").click()
- # 按"回车"搜索
- self.driver.find_element(By.ID, "sb_form_q").send_keys(Keys.ENTER)
- # 等待3秒
- time.sleep(3)
- assert "吴晓华" in self.driver.page_source, "页面中不存在要寻找的关键字!".encode("gbk")
-
-
- def tearDown(self):
- # 退出浏览器
- self.driver.quit()
-
- if __name__ == '__main__':
- # unittest.main()
- suite = unittest.TestLoader().loadTestsFromTestCase(GloryRoad)
- suite = unittest.TestSuite(suite)
- #unittest.TextTestRunner(verbosity=2).run(suite)
- filename = "e9_test.html" # 定义个报告存放路径,支持相对路径。
- # 以二进制方式打开文件,准备写
- fp = open(filename, 'wb')
- # 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
- runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
- title = '测试报告', description = '测试报告内容')
- # 运行测试集合
- runner.run(suite)
- fp.close()
执行结果:

安装:
py -3 -m pip install ddt
- import unittest
- import ddt
-
-
- @ddt.ddt
- class Praddt(unittest.TestCase):
-
- def setUp(self):
- print("my test start!")
-
- def tearDown(self):
- print("my test complete!")
-
- @ddt.data(["wulaoshi","pass123", "success"],
- ["lilaoshi","pwd123", "success"],
- ["zhanglaoshi", "1qaz", "ERROR"]) #一个方括号是一组测试数据
-
- @ddt.unpack
- def test_ddt(self, user, passwd, expect_value):
- login_info = {"wulaoshi":"pass123","lilaoshi":"pwd123"}
- print(user,passwd,expect_value)
- if user in login_info:
- if passwd == login_info[user]:
- result = "success"
- else:
- result = "ERROR"
- else:
- result = "ERROR"
-
- assert result==expect_value
-
-
- if __name__ == '__main__':
- # 执行单元测试
- unittest.main()
执行结果:
- my test start!
- wulaoshi pass123 success
- my test complete!
- .my test start!
- lilaoshi pwd123 success
- my test complete!
- .my test start!
- zhanglaoshi 1qaz ERROR
- my test complete!
- .
- ----------------------------------------------------------------------
- Ran 3 tests in 0.026s
-
- OK