软件工程慕课第三章编程题—对game_map.py进行单元测试

一、编程思路

  1、采用unittest库对代码进行单元测试

  2、用coverage库对测试代码进行覆盖率测试

二、代码实现

  1、unittest

首先要读懂game_map.py这个文件,里面包含了地图相关的接口,每读一个方法我就会进行一些测试,简单调用可以帮助更好的理解代码,下面是我读代码的时候进行的一些尝试:

 

读完代码后就知道这些方法是做什么的了,然后就学习了unittest这个库怎么使用,参考了很多csdn上的博客,对使用有一个大概理解,有几个重要的语法:

assertEqual用来判断函数的输入值和返回值是否一致来对函数进行测试,assertRaises用来判断函数对不正确的输入是否能正确抛出异常,mock.patch用来模拟还未编写完成的函数返回值,或者模拟你需要返回特定值的函数,下面贴出代码
 1 '''测试game_map.py'''
 2 import unittest
 3 
 4 from unittest import mock
 5 
 6 from game_map import *
 7 
 8 import HTMLTestRunner
 9 
10 from itertools import cycle
11 
12 class TestGameMap(unittest.TestCase):
13     '''测试 GameMap'''
14     def setUp(self):
15         self.game_map = GameMap(5, 4)
16 
17     def test_init(self):
18         self.assertRaises(TypeError, GameMap, (1.2,4))
19         self.assertRaises(TypeError, GameMap, (4,1.3))
20 
21     def test_rows(self):
22         self.assertEqual(5,self.game_map.rows)
23         self.assertEqual(4,self.game_map.cols)
24 
25     @mock.patch('random.random', new = mock.Mock(side_effect = cycle([0.4, 0.6])))
26     def test_reset_get_set(self):
27         self.assertRaises(TypeError,self.game_map.reset,(4))
28         self.game_map.reset()
29         self.assertEqual([[1,0,1,0],[1,0,1,0],[1,0,1,0],[1,0,1,0],[1,0,1,0]], self.game_map.cells)
30         self.assertEqual(1, self.game_map.get(0,0))
31         self.assertRaises(TypeError,self.game_map.get,(1.2,2))
32         self.assertRaises(TypeError,self.game_map.get,(2,1.2))
33         self.game_map.set(0,0,0)
34         self.assertEqual(0, self.game_map.get(0,0))
35         self.assertRaises(TypeError,self.game_map.set,(6,0,0))
36         self.assertRaises(TypeError,self.game_map.set,(0,4,0))
37         self.assertRaises(TypeError,self.game_map.set,(0,0,2))
38     @mock.patch('random.random', new = mock.Mock(side_effect = cycle([0.4])))
39     def test_get_neighbor_count_and_map(self):
40         self.game_map.reset()
41         for i in range(0,self.game_map.rows):
42             for j in range(0,self.game_map.cols):
43                 self.assertEqual(8, self.game_map.get_neighbor_count(i,j))
44         self.assertEqual([[8,8,8,8],[8,8,8,8],[8,8,8,8],[8,8,8,8],[8,8,8,8]], self.game_map.get_neighbor_count_map())
45         self.assertRaises(TypeError,self.game_map.get_neighbor_count,(5,0))
46         self.assertRaises(TypeError,self.game_map.get_neighbor_count,(0,5))
47 
48     def test_set_map(self):
49         self.game_map.set_map([[0,0,0,0],[1,1,1,1],[0,1,0,1],[1,0,1,0],[1,1,0,0]])
50         self.assertEqual([[0,0,0,0],[1,1,1,1],[0,1,0,1],[1,0,1,0],[1,1,0,0]], self.game_map.cells)
51         self.assertRaises(TypeError,self.game_map.set_map,(5))
52         self.assertRaises(AssertionError,self.game_map.set_map,([[0]*4]*4))
53         self.assertRaises(TypeError,self.game_map.set_map,([0]*5))
54         self.assertRaises(AssertionError,self.game_map.set_map,([[0]*3]*4))
55         self.assertRaises(TypeError,self.game_map.set_map,([[0.1]*4]*5))
56         self.assertRaises(AssertionError,self.game_map.set_map,([[2]*4]*5))
57     
58     def test_print_map(self):
59         self.assertRaises(TypeError,self.game_map.print_map,(1))
60         self.assertRaises(TypeError,self.game_map.print_map,([1,2],1))
61         self.game_map.print_map = mock.Mock()
62         self.game_map.print_map(['2'])
63         self.game_map.print_map.assert_called_with(['2'])
64 
65 
66 def main():
67     filepath = 'F:/multisim/VsCode/软件工程学习/test_game_map_report.html'
68     ftp=open(filepath,'wb')
69 
70     suite = unittest.makeSuite(TestGameMap)
71     
72     # unittest.main(verbosity=2)
73     runner=HTMLTestRunner.HTMLTestRunner(stream=ftp,title='test_game_map')
74     runner.run(suite)
75     
76 if __name__ == '__main__':
77     
78     main()
79     
80     
81     

 每一个方法的测试用例涵盖了所有路径,能起到一个比较好的测试作用,最后用HTMLTestRunner生成html报告,可以在报告里看到测试情况:

 
 

  2、coverage

用coverage可以测试代码的覆盖率,用来测试测试代码的话,可以看到测试文件和被测文件的覆盖情况,coverage有两种用法,一种是命令行,一种是API,两种用法都很简单方便:官方文档 https://coverage.readthedocs.io/en/latest/api.html#api,两种方法我都试了:
命令行操作起来稍微麻烦一些,要一次一次的输命令,下面是API的方式:
只需要在cov.start和cov.stop之间贴上需要测试的代码即可,这里有一个问题如果在unittest中采用的是unittest.main方法的话,这里不能正确导入测试用例,原因目前还不清楚,解决方法是采用其他的运行测试用例的方法,coverag还可以生成html报告:
非常简洁明了,测试文件调用的所有子文件也会进行覆盖率测试,点击进去可以看到每行代码的详细测试信息:
总共两个py文件,4个测试报告已经上传github:https://github.com/dbefb/nickYang/tree/master/GameMap单元测试、覆盖率测试
 
posted @ 2020-03-06 11:10  认真学习的小朋友  阅读(348)  评论(0编辑  收藏  举报