python单元测试框架unittest基本用法案例

unittest是python单元测试框架,类似于JUnit框架

意义:

  • 灵活的组织ui接口测试自动化用例
  • 让用例高效的执行
  • 方便验证测试用例的结果
  • 集成html形式测试报告
  1. 一个class继承unittest.TestCase类,即是一个个具体的TestCase(类方法名称必须以test开头,否则不能被unittest识别)
  2. 每一个用例执行的结果的标识,成功是. ,失败为F,出错是E
  3. 每一个测试以test01、test02…依次写下去,unittest才可按照编号执行
  4. versity参数控制输出结果,0是简单报告、1是一般报告、2是详情报告。
  5. 用setUp()、terUpClass()以及tearDownClass()可以在用例执行前布置环境,以及在用例执行后清理环境。
  6. 参数中加stream,可以讲报告输出到文件:可以用HTMLTestRunner输出html报告。
  7. 多个单元的测试用例集合在一起,就是TestSuite。

案例1

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

from selenium import webdriver

import requests

def test01():

    '''

    用例1

    :return:

    '''

    url = "http://www.ynhousedata.cn/house/assessment/assess_public?token=9a5008072cfd7336350306fdd9ea9485&timestamp=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出错,后边的代码无法执行,而且测试报告,不便于查阅。

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

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

若某个类下用例非常多,但又只想执行某一个,可以用以下方法

1

2

3

4

5

6

7

8

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>

若某个类下用例非常多,以下运行方式可以执行多个用例

1

2

3

4

5

6

7

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文件下有多个类,需要执行某个类的时候,可以用以下方法执行

1

2

3

4

5

6

7

8

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>

当有多个测试类的时候,可以用以下方法执行

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

46

47

48

49

50

51

52

53

54

55

56

57

58

59

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

# -*- 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文件

下载HTMLTestRunner链接

下载HTMLTestRunner链接

下载后修改文件,建议全部修改,如果报错,将不需要修改的地方还原即可。

1

2

3

4

5

6

7

8

9

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定义如下

1

2

3

4

5

6

7

8

9

10

11

12

13

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、 使用浏览器打开,可以看到如下报告

断言基本操作

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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

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

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>

巩固

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

# -*- 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 为测试被跳过的原因。

    @unittest.skip('取消测试')

    def test_upper(self):

        print('test_upper')

   # 当condition为真时,跳过被装饰的测试。

    @unittest.skipIf(a>5, '取消测试')

    def test_upper2(self):

        print('test_upper2')

    #  跳过被装饰的测试,condition 为假

    @unittest.skipUnless(a > 88, '跳过被装饰的测试')

    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()

运行

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

===============================================================================

[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: 跳过被装饰的测试

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走! 希望能帮助到你!【100%无套路免费领取】

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码小怡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值