|
150 | 150 | " 4. THEN we see steam escaping" |
151 | 151 | ] |
152 | 152 | }, |
153 | | - { |
154 | | - "cell_type": "code", |
155 | | - "execution_count": 13, |
156 | | - "id": "aa37aafc", |
157 | | - "metadata": {}, |
158 | | - "outputs": [], |
159 | | - "source": [ |
160 | | - "from typing import Optional, List" |
161 | | - ] |
162 | | - }, |
163 | | - { |
164 | | - "cell_type": "code", |
165 | | - "execution_count": 14, |
166 | | - "id": "1e758601", |
167 | | - "metadata": {}, |
168 | | - "outputs": [], |
169 | | - "source": [ |
170 | | - "def average(data: List[Optional[int]]) -> float:\n", |
171 | | - " \"\"\"\n", |
172 | | - " GIVEN a list, data = [1, 2, None, 3, 4]\n", |
173 | | - " WHEN we compute m = average(data)\n", |
174 | | - " THEN the result, m is 2.5\n", |
175 | | - " \n", |
176 | | - " Finds and returns average of a List of optional integers.\n", |
177 | | - " \n", |
178 | | - " Assumptions:\n", |
179 | | - " - Ignore None.\n", |
180 | | - " - Throw ZeroDivisionError if data is an empty list.\n", |
181 | | - " \"\"\"\n", |
182 | | - " tmp: float = 0\n", |
183 | | - " len_data: int = len(data)\n", |
184 | | - " for x in data:\n", |
185 | | - " try:\n", |
186 | | - " tmp += x\n", |
187 | | - " except TypeError:\n", |
188 | | - " len_data -= 1\n", |
189 | | - " \n", |
190 | | - " return tmp/len_data\n" |
191 | | - ] |
192 | | - }, |
193 | 153 | { |
194 | 154 | "cell_type": "markdown", |
195 | 155 | "id": "e9e0ec4f", |
|
214 | 174 | "\n", |
215 | 175 | "1. test the boundary values: 1 and 1000\n", |
216 | 176 | "2. test data just below the extreme values: 0 and 999\n", |
217 | | - "3. test data just above the extreme values: 2 and 1001" |
| 177 | + "3. test data just above the extreme values: 2 and 1001\n", |
| 178 | + "\n", |
| 179 | + "\n", |
| 180 | + "### Example of Test Driven Development (TDD)\n", |
| 181 | + "\n", |
| 182 | + "- write a function that finds the average of a list of numbers\n", |
| 183 | + "- input assumptions:\n", |
| 184 | + " - input is a list of integers\n", |
| 185 | + " - list can be empty\n", |
| 186 | + " - list may contain None for missing values\n", |
| 187 | + "- output assumptions:\n", |
| 188 | + " - output is a float\n", |
| 189 | + " - if the list is empty or contains only None throw DivisionByZeroError exception\n", |
| 190 | + " - answer should be correct to 7 decimal places" |
| 191 | + ] |
| 192 | + }, |
| 193 | + { |
| 194 | + "cell_type": "code", |
| 195 | + "execution_count": 1, |
| 196 | + "id": "8ff412e9", |
| 197 | + "metadata": {}, |
| 198 | + "outputs": [], |
| 199 | + "source": [ |
| 200 | + "from typing import Optional, List\n", |
| 201 | + "\n", |
| 202 | + "def average(data: List[Optional[int]]) -> float:\n", |
| 203 | + " \"\"\"\n", |
| 204 | + " GIVEN a list, data = [1, 2, None, 3, 4]\n", |
| 205 | + " WHEN we compute m = average(data)\n", |
| 206 | + " THEN the result, m is 2.5\n", |
| 207 | + " \n", |
| 208 | + " Finds and returns average of a List of optional integers.\n", |
| 209 | + " \n", |
| 210 | + " Assumptions:\n", |
| 211 | + " - Ignore None.\n", |
| 212 | + " - Throw ZeroDivisionError if data is an empty list.\n", |
| 213 | + " \"\"\"" |
218 | 214 | ] |
219 | 215 | }, |
220 | 216 | { |
|
281 | 277 | }, |
282 | 278 | { |
283 | 279 | "cell_type": "code", |
284 | | - "execution_count": 26, |
285 | | - "id": "c5ab7a9e", |
286 | | - "metadata": {}, |
287 | | - "outputs": [ |
288 | | - { |
289 | | - "data": { |
290 | | - "text/plain": [ |
291 | | - "2.6666666666666665" |
292 | | - ] |
293 | | - }, |
294 | | - "execution_count": 26, |
295 | | - "metadata": {}, |
296 | | - "output_type": "execute_result" |
297 | | - } |
298 | | - ], |
299 | | - "source": [ |
300 | | - "average([1, 3, 4])" |
301 | | - ] |
302 | | - }, |
303 | | - { |
304 | | - "cell_type": "code", |
305 | | - "execution_count": 39, |
| 280 | + "execution_count": null, |
306 | 281 | "id": "477fdb48", |
307 | 282 | "metadata": {}, |
308 | 283 | "outputs": [], |
309 | 284 | "source": [ |
310 | 285 | "def test_average6():\n", |
311 | 286 | " # float literal comparison or code comparison\n", |
312 | 287 | " # float literal comparison may require tolerance (error less than 0.0001 or 10^-4, e.g.)\n", |
| 288 | + " # average([1, 3, 4]) = 2.6666666666666665...\n", |
313 | 289 | " assert abs(average([1, 3, 4]) - 2.6666666) < 10**-7" |
314 | 290 | ] |
315 | 291 | }, |
|
327 | 303 | }, |
328 | 304 | { |
329 | 305 | "cell_type": "code", |
330 | | - "execution_count": 29, |
331 | | - "id": "b62bc7f7", |
332 | | - "metadata": {}, |
333 | | - "outputs": [], |
334 | | - "source": [ |
335 | | - "test_average1()" |
336 | | - ] |
337 | | - }, |
338 | | - { |
339 | | - "cell_type": "code", |
340 | | - "execution_count": 30, |
341 | | - "id": "59c6d5ac", |
342 | | - "metadata": {}, |
343 | | - "outputs": [], |
344 | | - "source": [ |
345 | | - "test_average2()" |
346 | | - ] |
347 | | - }, |
348 | | - { |
349 | | - "cell_type": "code", |
350 | | - "execution_count": 31, |
351 | | - "id": "466f4670", |
352 | | - "metadata": {}, |
353 | | - "outputs": [], |
354 | | - "source": [ |
355 | | - "test_average3()" |
356 | | - ] |
357 | | - }, |
358 | | - { |
359 | | - "cell_type": "code", |
360 | | - "execution_count": 32, |
361 | | - "id": "fd5bade7", |
362 | | - "metadata": {}, |
363 | | - "outputs": [], |
364 | | - "source": [ |
365 | | - "test_average4()" |
366 | | - ] |
367 | | - }, |
368 | | - { |
369 | | - "cell_type": "code", |
370 | | - "execution_count": 33, |
371 | | - "id": "c5044622", |
372 | | - "metadata": {}, |
373 | | - "outputs": [], |
374 | | - "source": [ |
375 | | - "test_average5()" |
376 | | - ] |
377 | | - }, |
378 | | - { |
379 | | - "cell_type": "code", |
380 | | - "execution_count": 40, |
381 | | - "id": "3151739e", |
| 306 | + "execution_count": null, |
| 307 | + "id": "c603e248", |
382 | 308 | "metadata": {}, |
383 | 309 | "outputs": [], |
384 | 310 | "source": [ |
385 | | - "test_average6()" |
| 311 | + "def run_all_tests():\n", |
| 312 | + " test_average1()\n", |
| 313 | + " test_average2()\n", |
| 314 | + " test_average3()\n", |
| 315 | + " test_average4()\n", |
| 316 | + " test_average5()\n", |
| 317 | + " test_average6()\n", |
| 318 | + " test_average7()" |
386 | 319 | ] |
387 | 320 | }, |
388 | 321 | { |
389 | 322 | "cell_type": "code", |
390 | 323 | "execution_count": null, |
391 | | - "id": "33dad625", |
| 324 | + "id": "b62bc7f7", |
392 | 325 | "metadata": {}, |
393 | 326 | "outputs": [], |
394 | 327 | "source": [ |
395 | | - "test_average7()" |
| 328 | + "run_all_tests()" |
396 | 329 | ] |
397 | 330 | }, |
398 | 331 | { |
|
501 | 434 | ], |
502 | 435 | "metadata": { |
503 | 436 | "kernelspec": { |
504 | | - "display_name": "Python 3 (ipykernel)", |
| 437 | + "display_name": "Python 3", |
505 | 438 | "language": "python", |
506 | 439 | "name": "python3" |
507 | 440 | }, |
|
515 | 448 | "name": "python", |
516 | 449 | "nbconvert_exporter": "python", |
517 | 450 | "pygments_lexer": "ipython3", |
518 | | - "version": "3.10.8" |
519 | | - }, |
520 | | - "vscode": { |
521 | | - "interpreter": { |
522 | | - "hash": "1a1af0ee75eeea9e2e1ee996c87e7a2b11a0bebd85af04bb136d915cefc0abce" |
523 | | - } |
| 451 | + "version": "3.9.6" |
524 | 452 | } |
525 | 453 | }, |
526 | 454 | "nbformat": 4, |
|
0 commit comments