Skip to content

Commit b059e14

Browse files
committed
整理文件
1 parent 2fe3a60 commit b059e14

4 files changed

Lines changed: 630 additions & 0 deletions

File tree

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {
6+
"toc": true
7+
},
8+
"source": [
9+
"<h1>Table of Contents<span class=\"tocSkip\"></span></h1>\n",
10+
"<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#14.2-在测试单元中给对象打补丁\" data-toc-modified-id=\"14.2-在测试单元中给对象打补丁-1\"><span class=\"toc-item-num\">1&nbsp;&nbsp;</span>14.2 在测试单元中给对象打补丁</a></span></li><li><span><a href=\"#14.3-在单元测试中测试是否抛出异常\" data-toc-modified-id=\"14.3-在单元测试中测试是否抛出异常-2\"><span class=\"toc-item-num\">2&nbsp;&nbsp;</span>14.3 在单元测试中测试是否抛出异常</a></span></li></ul></div>"
11+
]
12+
},
13+
{
14+
"cell_type": "markdown",
15+
"metadata": {},
16+
"source": [
17+
"###### 14.2 在测试单元中给对象打补丁\n",
18+
"你写的单元测试中需要给指定的对象打补丁, 用来断言它们在测试中的期望行为(比如,断言被调用时的参数个数,访问指定的属性等)"
19+
]
20+
},
21+
{
22+
"cell_type": "code",
23+
"execution_count": null,
24+
"metadata": {
25+
"ExecuteTime": {
26+
"end_time": "2020-10-05T07:14:17.408938Z",
27+
"start_time": "2020-10-05T07:14:17.405880Z"
28+
},
29+
"run_control": {
30+
"marked": true
31+
}
32+
},
33+
"outputs": [],
34+
"source": [
35+
"# %load example.py\n",
36+
"# example.py\n",
37+
"from urllib.request import urlopen\n",
38+
"import csv\n",
39+
"\n",
40+
"def dowprices():\n",
41+
" u = urlopen('http://finance.yahoo.com/d/quotes.csv?s=@^DJI&f=sl1')\n",
42+
" lines = (line.decode('utf-8') for line in u)\n",
43+
" rows = (row for row in csv.reader(lines) if len(row) == 2)\n",
44+
" prices = { name:float(price) for name, price in rows }\n",
45+
" return prices\n"
46+
]
47+
},
48+
{
49+
"cell_type": "code",
50+
"execution_count": 28,
51+
"metadata": {
52+
"ExecuteTime": {
53+
"end_time": "2020-10-05T07:40:46.295780Z",
54+
"start_time": "2020-10-05T07:40:46.292384Z"
55+
}
56+
},
57+
"outputs": [],
58+
"source": [
59+
"# 解决方案: 用 unittest.mock.pathch 装饰器函数\n",
60+
"import unittest\n",
61+
"from unittest.mock import patch\n",
62+
"import io\n",
63+
"import example\n",
64+
"\n",
65+
"sample_data = io.BytesIO(b'''\\\n",
66+
"\"IBM\",91.1\\r\n",
67+
"\"AA\",13.25\\r\n",
68+
"\"MSFT\",27.72\\r\n",
69+
"\\r\n",
70+
"''')"
71+
]
72+
},
73+
{
74+
"cell_type": "code",
75+
"execution_count": 29,
76+
"metadata": {
77+
"ExecuteTime": {
78+
"end_time": "2020-10-05T07:40:46.926439Z",
79+
"start_time": "2020-10-05T07:40:46.922066Z"
80+
}
81+
},
82+
"outputs": [],
83+
"source": [
84+
"class Tests(unittest.TestCase):\n",
85+
" @patch('example.urlopen', return_value=sample_data) # 1, 2\n",
86+
" def test_dowprices(self, mock_urlopen):\n",
87+
" p = example.dowprices()\n",
88+
" self.assertTrue(mock_urlopen.called)\n",
89+
" self.assertEqual(p, {'IBM': 91.1,\n",
90+
" 'AA': 13.25,\n",
91+
" 'MSFT': 27.72})"
92+
]
93+
},
94+
{
95+
"cell_type": "markdown",
96+
"metadata": {},
97+
"source": [
98+
"1. 位于 example 模块中的 urlopen() 函数被一个mock对象替代, 该对象会返回一个包含测试数据的 ByteIO(). \n",
99+
"2. 在打补丁时我们使用了 example.urlopen 来代替 urllib.request.urlopen 。 当你创建补丁的时候,你必须使用它们在测试代码中的名称。 由于测试代码使用了 from urllib.request import urlopen ,那么 dowprices() 函数 中使用的 urlopen() 函数实际上就位于 example 模块了。"
100+
]
101+
},
102+
{
103+
"cell_type": "code",
104+
"execution_count": 30,
105+
"metadata": {
106+
"ExecuteTime": {
107+
"end_time": "2020-10-05T07:40:50.527670Z",
108+
"start_time": "2020-10-05T07:40:50.520727Z"
109+
}
110+
},
111+
"outputs": [
112+
{
113+
"name": "stderr",
114+
"output_type": "stream",
115+
"text": [
116+
"test_dowprices (__main__.Tests) ... ok\n",
117+
"\n",
118+
"----------------------------------------------------------------------\n",
119+
"Ran 1 test in 0.002s\n",
120+
"\n",
121+
"OK\n"
122+
]
123+
},
124+
{
125+
"data": {
126+
"text/plain": [
127+
"<unittest.main.TestProgram at 0x7f928c1a7f60>"
128+
]
129+
},
130+
"execution_count": 30,
131+
"metadata": {},
132+
"output_type": "execute_result"
133+
}
134+
],
135+
"source": [
136+
"unittest.main(verbosity=2, exit=False, defaultTest=['Tests'], argv=[''])"
137+
]
138+
},
139+
{
140+
"cell_type": "markdown",
141+
"metadata": {},
142+
"source": [
143+
"###### 14.3 在单元测试中测试是否抛出异常"
144+
]
145+
},
146+
{
147+
"cell_type": "code",
148+
"execution_count": 31,
149+
"metadata": {
150+
"ExecuteTime": {
151+
"end_time": "2020-10-05T07:40:54.500929Z",
152+
"start_time": "2020-10-05T07:40:54.496735Z"
153+
}
154+
},
155+
"outputs": [],
156+
"source": [
157+
"# 解决方案: 用 assertRaises 方法.\n",
158+
"import unittest\n",
159+
"\n",
160+
"\n",
161+
"def parse_int(s):\n",
162+
" return int(s)\n",
163+
"\n",
164+
"class TestConversion(unittest.TestCase):\n",
165+
" def test_bad_int(self):\n",
166+
" with self.assertRaises(ValueError):\n",
167+
" parse_int('N?A')"
168+
]
169+
},
170+
{
171+
"cell_type": "code",
172+
"execution_count": 32,
173+
"metadata": {
174+
"ExecuteTime": {
175+
"end_time": "2020-10-05T07:40:55.197409Z",
176+
"start_time": "2020-10-05T07:40:55.188152Z"
177+
}
178+
},
179+
"outputs": [
180+
{
181+
"name": "stderr",
182+
"output_type": "stream",
183+
"text": [
184+
"test_bad_int (__main__.TestConversion) ... ok\n",
185+
"\n",
186+
"----------------------------------------------------------------------\n",
187+
"Ran 1 test in 0.002s\n",
188+
"\n",
189+
"OK\n"
190+
]
191+
},
192+
{
193+
"data": {
194+
"text/plain": [
195+
"<unittest.main.TestProgram at 0x7f928c1adcc0>"
196+
]
197+
},
198+
"execution_count": 32,
199+
"metadata": {},
200+
"output_type": "execute_result"
201+
}
202+
],
203+
"source": [
204+
"unittest.main(verbosity=2, exit=False, defaultTest=['TestConversion'], argv=[''])"
205+
]
206+
},
207+
{
208+
"cell_type": "code",
209+
"execution_count": 33,
210+
"metadata": {
211+
"ExecuteTime": {
212+
"end_time": "2020-10-05T07:46:06.337060Z",
213+
"start_time": "2020-10-05T07:46:06.333064Z"
214+
}
215+
},
216+
"outputs": [],
217+
"source": [
218+
"# 如果你想测试异常的具体值, 那么需要另外一种方法.\n",
219+
"import errno\n",
220+
"\n",
221+
"class TestIO(unittest.TestCase):\n",
222+
" def test_file_not_found(self):\n",
223+
" try:\n",
224+
" f = open('file/not/found')\n",
225+
" except IOError as e:\n",
226+
" self.assertEqual(e.errno, errno.ENOENT)\n",
227+
" else:\n",
228+
" self.fail('IOError not raised.')"
229+
]
230+
},
231+
{
232+
"cell_type": "code",
233+
"execution_count": 34,
234+
"metadata": {
235+
"ExecuteTime": {
236+
"end_time": "2020-10-05T07:46:19.960219Z",
237+
"start_time": "2020-10-05T07:46:19.953290Z"
238+
}
239+
},
240+
"outputs": [
241+
{
242+
"name": "stderr",
243+
"output_type": "stream",
244+
"text": [
245+
"test_file_not_found (__main__.TestIO) ... ok\n",
246+
"\n",
247+
"----------------------------------------------------------------------\n",
248+
"Ran 1 test in 0.001s\n",
249+
"\n",
250+
"OK\n"
251+
]
252+
},
253+
{
254+
"data": {
255+
"text/plain": [
256+
"<unittest.main.TestProgram at 0x7f928be2b240>"
257+
]
258+
},
259+
"execution_count": 34,
260+
"metadata": {},
261+
"output_type": "execute_result"
262+
}
263+
],
264+
"source": [
265+
"unittest.main(verbosity=2, exit=False, defaultTest=['TestIO'], argv=[''])"
266+
]
267+
},
268+
{
269+
"cell_type": "code",
270+
"execution_count": null,
271+
"metadata": {},
272+
"outputs": [],
273+
"source": []
274+
}
275+
],
276+
"metadata": {
277+
"kernelspec": {
278+
"display_name": "Python 3",
279+
"language": "python",
280+
"name": "python3"
281+
},
282+
"language_info": {
283+
"codemirror_mode": {
284+
"name": "ipython",
285+
"version": 3
286+
},
287+
"file_extension": ".py",
288+
"mimetype": "text/x-python",
289+
"name": "python",
290+
"nbconvert_exporter": "python",
291+
"pygments_lexer": "ipython3",
292+
"version": "3.6.7"
293+
},
294+
"toc": {
295+
"base_numbering": 1,
296+
"nav_menu": {},
297+
"number_sections": true,
298+
"sideBar": true,
299+
"skip_h1_title": true,
300+
"title_cell": "Table of Contents",
301+
"title_sidebar": "Contents",
302+
"toc_cell": true,
303+
"toc_position": {},
304+
"toc_section_display": true,
305+
"toc_window_display": false
306+
}
307+
},
308+
"nbformat": 4,
309+
"nbformat_minor": 2
310+
}

0 commit comments

Comments
 (0)