From 2cf2cd9cd4b55d9659ede09280c679e1d224c6b0 Mon Sep 17 00:00:00 2001 From: Jon Speicher Date: Sat, 27 Jul 2013 19:52:44 -0400 Subject: [PATCH] Add description and examples for Exceptions --- .../sw_engineering/SoftwareEngineering.ipynb | 844 ++++++++++++++---- 1 file changed, 670 insertions(+), 174 deletions(-) diff --git a/python/sw_engineering/SoftwareEngineering.ipynb b/python/sw_engineering/SoftwareEngineering.ipynb index bdfd763..de26100 100644 --- a/python/sw_engineering/SoftwareEngineering.ipynb +++ b/python/sw_engineering/SoftwareEngineering.ipynb @@ -21,7 +21,8 @@ "* Refactoring\n", "* Testing\n", "* Nose\n", - "* Test-driven development" + "* Test-driven development\n", + "* Exceptions" ] }, { @@ -116,7 +117,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 1 + "prompt_number": 4 }, { "cell_type": "markdown", @@ -136,13 +137,13 @@ "outputs": [ { "output_type": "pyout", - "prompt_number": 2, + "prompt_number": 5, "text": [ "117" ] } ], - "prompt_number": 2 + "prompt_number": 5 }, { "cell_type": "markdown", @@ -207,7 +208,7 @@ ] } ], - "prompt_number": 3 + "prompt_number": 6 }, { "cell_type": "markdown", @@ -259,7 +260,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 4 + "prompt_number": 7 }, { "cell_type": "markdown", @@ -289,7 +290,7 @@ ] } ], - "prompt_number": 5 + "prompt_number": 8 }, { "cell_type": "code", @@ -302,7 +303,7 @@ "outputs": [ { "output_type": "pyout", - "prompt_number": 6, + "prompt_number": 9, "text": [ "(['2011-04-22', '2011-04-23', '2011-04-23', '2011-04-23', '2011-04-23'],\n", " ['21:06', '14:12', '10:24', '20:08', '18:46'],\n", @@ -311,7 +312,7 @@ ] } ], - "prompt_number": 6 + "prompt_number": 9 }, { "cell_type": "markdown", @@ -344,7 +345,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 7 + "prompt_number": 10 }, { "cell_type": "markdown", @@ -364,13 +365,13 @@ "outputs": [ { "output_type": "pyout", - "prompt_number": 8, + "prompt_number": 11, "text": [ "117" ] } ], - "prompt_number": 8 + "prompt_number": 11 }, { "cell_type": "markdown", @@ -425,7 +426,7 @@ ] } ], - "prompt_number": 9 + "prompt_number": 12 }, { "cell_type": "markdown", @@ -454,7 +455,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 10 + "prompt_number": 13 }, { "cell_type": "markdown", @@ -479,7 +480,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 12 + "prompt_number": 14 }, { "cell_type": "markdown", @@ -509,13 +510,13 @@ "output_type": "pyerr", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32massert\u001b[0m \u001b[0;36m4\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0madd_two_plus_two\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"2 + 2 didn't equal 4\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0mtest_add_two_plus_two_equals_four\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m\u001b[0m in \u001b[0;36mtest_add_two_plus_two_equals_four\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mtest_add_two_plus_two_equals_four\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0;32massert\u001b[0m \u001b[0;36m4\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0madd_two_plus_two\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"2 + 2 didn't equal 4\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mtest_add_two_plus_two_equals_four\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32massert\u001b[0m \u001b[0;36m4\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0madd_two_plus_two\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"2 + 2 didn't equal 4\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0mtest_add_two_plus_two_equals_four\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mtest_add_two_plus_two_equals_four\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mtest_add_two_plus_two_equals_four\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0;32massert\u001b[0m \u001b[0;36m4\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0madd_two_plus_two\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"2 + 2 didn't equal 4\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mtest_add_two_plus_two_equals_four\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mAssertionError\u001b[0m: 2 + 2 didn't equal 4" ] } ], - "prompt_number": 13 + "prompt_number": 15 }, { "cell_type": "markdown", @@ -621,7 +622,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 14 + "prompt_number": 16 }, { "cell_type": "code", @@ -634,31 +635,37 @@ "outputs": [ { "html": [ - "
" + "
" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_d38e10d9d55741bd9baa798e352d80ea = $(\"#ipython_nose_d38e10d9d55741bd9baa798e352d80ea\");" + "document.ipython_nose_5e87717b84c447ad93143bde900e1715 = $(\"#ipython_nose_5e87717b84c447ad93143bde900e1715\");" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_d38e10d9d55741bd9baa798e352d80ea.append($(\".\"));" + "document.ipython_nose_5e87717b84c447ad93143bde900e1715.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_d38e10d9d55741bd9baa798e352d80ea.append($(\"F\"));" + "document.ipython_nose_5e87717b84c447ad93143bde900e1715.append($(\"E\"));" ], "output_type": "display_data" }, { "javascript": [ - "delete document.ipython_nose_d38e10d9d55741bd9baa798e352d80ea;" + "document.ipython_nose_5e87717b84c447ad93143bde900e1715.append($(\"F\"));" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "delete document.ipython_nose_5e87717b84c447ad93143bde900e1715;" ], "output_type": "display_data" }, @@ -760,16 +767,37 @@ " \n", " \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", "
\n", "  \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", - " 1/2 tests passed; 1 failed\n", + " 1/3 tests passed; 2 failed\n", + "
\n", + " \n", + "
\n", + "
\n", + " failed: __main__.test_mean_of_empty_function_raises_value_error\n", + " [toggle traceback]\n", + "
\n", + "
Traceback (most recent call last):\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n",
+        "    testMethod()\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n",
+        "    self.test(*self.arg)\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 60, in newfunc\n",
+        "    func(*arg, **kw)\n",
+        "  File \"<ipython-input-2-bc417f346267>\", line 5, in test_mean_of_empty_function_raises_value_error\n",
+        "    mean([])\n",
+        "NameError: global name 'mean' is not defined\n",
+        "
\n", "
\n", " \n", "
\n", @@ -782,9 +810,9 @@ " testMethod()\n", " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", " self.test(*self.arg)\n", - " File \"<ipython-input-13-2d797333ff4c>\", line 5, in test_add_two_plus_two_equals_four\n", " assert 4 == add_two_plus_two(), \"2 + 2 didn't equal 4\"\n", "AssertionError: 2 + 2 didn't equal 4\n", @@ -793,9 +821,23 @@ " " ], "output_type": "pyout", - "prompt_number": 15, + "prompt_number": 18, "text": [ - "1/2 tests passed; 1 failed\n", + "1/3 tests passed; 2 failed\n", + "========\n", + "__main__.test_mean_of_empty_function_raises_value_error\n", + "========\n", + "Traceback (most recent call last):\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n", + " testMethod()\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", + " self.test(*self.arg)\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 60, in newfunc\n", + " func(*arg, **kw)\n", + " File \"\", line 5, in test_mean_of_empty_function_raises_value_error\n", + " mean([])\n", + "NameError: global name 'mean' is not defined\n", + "\n", "========\n", "__main__.test_add_two_plus_two_equals_four\n", "========\n", @@ -804,14 +846,14 @@ " testMethod()\n", " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", " self.test(*self.arg)\n", - " File \"\", line 5, in test_add_two_plus_two_equals_four\n", + " File \"\", line 5, in test_add_two_plus_two_equals_four\n", " assert 4 == add_two_plus_two(), \"2 + 2 didn't equal 4\"\n", "AssertionError: 2 + 2 didn't equal 4\n", "\n" ] } ], - "prompt_number": 15 + "prompt_number": 18 }, { "cell_type": "markdown", @@ -841,7 +883,7 @@ ] } ], - "prompt_number": 16 + "prompt_number": 19 }, { "cell_type": "markdown", @@ -870,7 +912,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 17 + "prompt_number": 20 }, { "cell_type": "code", @@ -883,31 +925,37 @@ "outputs": [ { "html": [ - "
" + "
" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "document.ipython_nose_510c086cad7b476795575f3b317d1255 = $(\"#ipython_nose_510c086cad7b476795575f3b317d1255\");" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_b902caf7914c4fb3b2efaf1c540ce8e0 = $(\"#ipython_nose_b902caf7914c4fb3b2efaf1c540ce8e0\");" + "document.ipython_nose_510c086cad7b476795575f3b317d1255.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_b902caf7914c4fb3b2efaf1c540ce8e0.append($(\".\"));" + "document.ipython_nose_510c086cad7b476795575f3b317d1255.append($(\"E\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_b902caf7914c4fb3b2efaf1c540ce8e0.append($(\".\"));" + "document.ipython_nose_510c086cad7b476795575f3b317d1255.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "delete document.ipython_nose_b902caf7914c4fb3b2efaf1c540ce8e0;" + "delete document.ipython_nose_510c086cad7b476795575f3b317d1255;" ], "output_type": "display_data" }, @@ -1009,27 +1057,62 @@ " \n", " \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", "
\n", "  \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", - " 2/2 tests passed\n", + " 2/3 tests passed; 1 failed\n", + "
\n", + " \n", + "
\n", + "
\n", + " failed: __main__.test_mean_of_empty_function_raises_value_error\n", + " [toggle traceback]\n", + "
\n", + "
Traceback (most recent call last):\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n",
+        "    testMethod()\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n",
+        "    self.test(*self.arg)\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 60, in newfunc\n",
+        "    func(*arg, **kw)\n",
+        "  File \"<ipython-input-2-bc417f346267>\", line 5, in test_mean_of_empty_function_raises_value_error\n",
+        "    mean([])\n",
+        "NameError: global name 'mean' is not defined\n",
+        "
\n", "
\n", " " ], "output_type": "pyout", - "prompt_number": 18, + "prompt_number": 21, "text": [ - "2/2 tests passed\n" + "2/3 tests passed; 1 failed\n", + "========\n", + "__main__.test_mean_of_empty_function_raises_value_error\n", + "========\n", + "Traceback (most recent call last):\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n", + " testMethod()\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", + " self.test(*self.arg)\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 60, in newfunc\n", + " func(*arg, **kw)\n", + " File \"\", line 5, in test_mean_of_empty_function_raises_value_error\n", + " mean([])\n", + "NameError: global name 'mean' is not defined\n", + "\n" ] } ], - "prompt_number": 18 + "prompt_number": 21 }, { "cell_type": "markdown", @@ -1064,13 +1147,24 @@ "cell_type": "code", "collapsed": false, "input": [ - "def test_mean_of_zero():\n", + "def test_mean_of_zero_is_zero():\n", " assert 0 == mean([0])" ], "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 19 + "prompt_number": 22 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "***\n", + "**Aside: Test names**\n", + "\n", + "Naming tests well will help you to quickly resolve bugs that may crop up when running your tests. Imagine that you have 100 tests for the `mean` function. When you run your test suite, would you rather see a failure in `test_mean37` or in `test_mean_of_zero_is_zero`?\n", + "***" + ] }, { "cell_type": "code", @@ -1083,37 +1177,43 @@ "outputs": [ { "html": [ - "
" + "
" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "document.ipython_nose_880d0b5c63014ac78937ccad69cf89d2 = $(\"#ipython_nose_880d0b5c63014ac78937ccad69cf89d2\");" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197 = $(\"#ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197\");" + "document.ipython_nose_880d0b5c63014ac78937ccad69cf89d2.append($(\"E\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197.append($(\"E\"));" + "document.ipython_nose_880d0b5c63014ac78937ccad69cf89d2.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197.append($(\".\"));" + "document.ipython_nose_880d0b5c63014ac78937ccad69cf89d2.append($(\"E\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197.append($(\".\"));" + "document.ipython_nose_880d0b5c63014ac78937ccad69cf89d2.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "delete document.ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197;" + "delete document.ipython_nose_880d0b5c63014ac78937ccad69cf89d2;" ], "output_type": "display_data" }, @@ -1215,21 +1315,21 @@ " \n", " \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", "
\n", "  \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", - " 2/3 tests passed; 1 failed\n", + " 2/4 tests passed; 2 failed\n", "
\n", " \n", "
\n", "
\n", - " failed: __main__.test_mean_of_zero\n", + " failed: __main__.test_mean_of_zero_is_zero\n", " [toggle traceback]\n", "
\n", "
Traceback (most recent call last):\n",
@@ -1237,36 +1337,71 @@
         "    testMethod()\n",
         "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n",
         "    self.test(*self.arg)\n",
-        "  File \"<ipython-input-19-481e1c58db22>\", line 2, in test_mean_of_zero\n",
+        "  File \"<ipython-input-22-ee2ab148c1b0>\", line 2, in test_mean_of_zero_is_zero\n",
         "    assert 0 == mean([0])\n",
         "NameError: global name 'mean' is not defined\n",
         "
\n", "
\n", + " \n", + "
\n", + "
\n", + " failed: __main__.test_mean_of_empty_function_raises_value_error\n", + " [toggle traceback]\n", + "
\n", + "
Traceback (most recent call last):\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n",
+        "    testMethod()\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n",
+        "    self.test(*self.arg)\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 60, in newfunc\n",
+        "    func(*arg, **kw)\n",
+        "  File \"<ipython-input-2-bc417f346267>\", line 5, in test_mean_of_empty_function_raises_value_error\n",
+        "    mean([])\n",
+        "NameError: global name 'mean' is not defined\n",
+        "
\n", + "
\n", " " ], "output_type": "pyout", - "prompt_number": 20, + "prompt_number": 23, "text": [ - "2/3 tests passed; 1 failed\n", + "2/4 tests passed; 2 failed\n", "========\n", - "__main__.test_mean_of_zero\n", + "__main__.test_mean_of_zero_is_zero\n", "========\n", "Traceback (most recent call last):\n", " File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n", " testMethod()\n", " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", " self.test(*self.arg)\n", - " File \"\", line 2, in test_mean_of_zero\n", + " File \"\", line 2, in test_mean_of_zero_is_zero\n", " assert 0 == mean([0])\n", "NameError: global name 'mean' is not defined\n", + "\n", + "========\n", + "__main__.test_mean_of_empty_function_raises_value_error\n", + "========\n", + "Traceback (most recent call last):\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n", + " testMethod()\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", + " self.test(*self.arg)\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 60, in newfunc\n", + " func(*arg, **kw)\n", + " File \"\", line 5, in test_mean_of_empty_function_raises_value_error\n", + " mean([])\n", + "NameError: global name 'mean' is not defined\n", "\n" ] } ], - "prompt_number": 20 + "prompt_number": 23 }, { "cell_type": "code", @@ -1278,7 +1413,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 21 + "prompt_number": 24 }, { "cell_type": "code", @@ -1291,37 +1426,43 @@ "outputs": [ { "html": [ - "
" + "
" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_bbb38260de4a452086abb22e7db22dfd = $(\"#ipython_nose_bbb38260de4a452086abb22e7db22dfd\");" + "document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9 = $(\"#ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9\");" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_bbb38260de4a452086abb22e7db22dfd.append($(\"E\"));" + "document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9.append($(\"E\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_bbb38260de4a452086abb22e7db22dfd.append($(\".\"));" + "document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_bbb38260de4a452086abb22e7db22dfd.append($(\".\"));" + "document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9.append($(\"E\"));" ], "output_type": "display_data" }, { "javascript": [ - "delete document.ipython_nose_bbb38260de4a452086abb22e7db22dfd;" + "document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9.append($(\".\"));" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "delete document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9;" ], "output_type": "display_data" }, @@ -1423,21 +1564,21 @@ " \n", " \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", "
\n", "  \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", - " 2/3 tests passed; 1 failed\n", + " 2/4 tests passed; 2 failed\n", "
\n", " \n", "
\n", "
\n", - " failed: __main__.test_mean_of_zero\n", + " failed: __main__.test_mean_of_zero_is_zero\n", " [toggle traceback]\n", "
\n", "
Traceback (most recent call last):\n",
@@ -1445,36 +1586,71 @@
         "    testMethod()\n",
         "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n",
         "    self.test(*self.arg)\n",
-        "  File \"<ipython-input-19-481e1c58db22>\", line 2, in test_mean_of_zero\n",
+        "  File \"<ipython-input-22-ee2ab148c1b0>\", line 2, in test_mean_of_zero_is_zero\n",
         "    assert 0 == mean([0])\n",
         "TypeError: mean() takes no arguments (1 given)\n",
         "
\n", "
\n", + " \n", + "
\n", + "
\n", + " failed: __main__.test_mean_of_empty_function_raises_value_error\n", + " [toggle traceback]\n", + "
\n", + "
Traceback (most recent call last):\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n",
+        "    testMethod()\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n",
+        "    self.test(*self.arg)\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 60, in newfunc\n",
+        "    func(*arg, **kw)\n",
+        "  File \"<ipython-input-2-bc417f346267>\", line 5, in test_mean_of_empty_function_raises_value_error\n",
+        "    mean([])\n",
+        "TypeError: mean() takes no arguments (1 given)\n",
+        "
\n", + "
\n", " " ], "output_type": "pyout", - "prompt_number": 22, + "prompt_number": 25, "text": [ - "2/3 tests passed; 1 failed\n", + "2/4 tests passed; 2 failed\n", "========\n", - "__main__.test_mean_of_zero\n", + "__main__.test_mean_of_zero_is_zero\n", "========\n", "Traceback (most recent call last):\n", " File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n", " testMethod()\n", " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", " self.test(*self.arg)\n", - " File \"\", line 2, in test_mean_of_zero\n", + " File \"\", line 2, in test_mean_of_zero_is_zero\n", " assert 0 == mean([0])\n", "TypeError: mean() takes no arguments (1 given)\n", + "\n", + "========\n", + "__main__.test_mean_of_empty_function_raises_value_error\n", + "========\n", + "Traceback (most recent call last):\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n", + " testMethod()\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", + " self.test(*self.arg)\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 60, in newfunc\n", + " func(*arg, **kw)\n", + " File \"\", line 5, in test_mean_of_empty_function_raises_value_error\n", + " mean([])\n", + "TypeError: mean() takes no arguments (1 given)\n", "\n" ] } ], - "prompt_number": 22 + "prompt_number": 25 }, { "cell_type": "code", @@ -1486,7 +1662,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 23 + "prompt_number": 26 }, { "cell_type": "code", @@ -1499,37 +1675,43 @@ "outputs": [ { "html": [ - "
" + "
" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "document.ipython_nose_1e1bd17442294222a80f6cc462ac3176 = $(\"#ipython_nose_1e1bd17442294222a80f6cc462ac3176\");" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_183426a0661b43479529049b993ae958 = $(\"#ipython_nose_183426a0661b43479529049b993ae958\");" + "document.ipython_nose_1e1bd17442294222a80f6cc462ac3176.append($(\"F\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_183426a0661b43479529049b993ae958.append($(\"F\"));" + "document.ipython_nose_1e1bd17442294222a80f6cc462ac3176.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_183426a0661b43479529049b993ae958.append($(\".\"));" + "document.ipython_nose_1e1bd17442294222a80f6cc462ac3176.append($(\"F\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_183426a0661b43479529049b993ae958.append($(\".\"));" + "document.ipython_nose_1e1bd17442294222a80f6cc462ac3176.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "delete document.ipython_nose_183426a0661b43479529049b993ae958;" + "delete document.ipython_nose_1e1bd17442294222a80f6cc462ac3176;" ], "output_type": "display_data" }, @@ -1631,21 +1813,21 @@ " \n", " \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", "
\n", "  \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", - " 2/3 tests passed; 1 failed\n", + " 2/4 tests passed; 2 failed\n", "
\n", " \n", "
\n", "
\n", - " failed: __main__.test_mean_of_zero\n", + " failed: __main__.test_mean_of_zero_is_zero\n", " [toggle traceback]\n", "
\n", "
Traceback (most recent call last):\n",
@@ -1653,36 +1835,64 @@
         "    testMethod()\n",
         "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n",
         "    self.test(*self.arg)\n",
-        "  File \"<ipython-input-19-481e1c58db22>\", line 2, in test_mean_of_zero\n",
+        "  File \"<ipython-input-22-ee2ab148c1b0>\", line 2, in test_mean_of_zero_is_zero\n",
         "    assert 0 == mean([0])\n",
         "AssertionError\n",
         "
\n", "
\n", + " \n", + "
\n", + "
\n", + " failed: __main__.test_mean_of_empty_function_raises_value_error\n", + " [toggle traceback]\n", + "
\n", + "
Traceback (most recent call last):\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n",
+        "    testMethod()\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n",
+        "    self.test(*self.arg)\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 67, in newfunc\n",
+        "    raise AssertionError(message)\n",
+        "AssertionError: test_mean_of_empty_function_raises_value_error() did not raise ValueError\n",
+        "
\n", + "
\n", " " ], "output_type": "pyout", - "prompt_number": 24, + "prompt_number": 27, "text": [ - "2/3 tests passed; 1 failed\n", + "2/4 tests passed; 2 failed\n", "========\n", - "__main__.test_mean_of_zero\n", + "__main__.test_mean_of_zero_is_zero\n", "========\n", "Traceback (most recent call last):\n", " File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n", " testMethod()\n", " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", " self.test(*self.arg)\n", - " File \"\", line 2, in test_mean_of_zero\n", + " File \"\", line 2, in test_mean_of_zero_is_zero\n", " assert 0 == mean([0])\n", "AssertionError\n", + "\n", + "========\n", + "__main__.test_mean_of_empty_function_raises_value_error\n", + "========\n", + "Traceback (most recent call last):\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n", + " testMethod()\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", + " self.test(*self.arg)\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 67, in newfunc\n", + " raise AssertionError(message)\n", + "AssertionError: test_mean_of_empty_function_raises_value_error() did not raise ValueError\n", "\n" ] } ], - "prompt_number": 24 + "prompt_number": 27 }, { "cell_type": "code", @@ -1694,7 +1904,7 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 25 + "prompt_number": 28 }, { "cell_type": "code", @@ -1707,37 +1917,43 @@ "outputs": [ { "html": [ - "
" + "
" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "document.ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493 = $(\"#ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493\");" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_6748615aba7a4a3abecfdbad96ac3251 = $(\"#ipython_nose_6748615aba7a4a3abecfdbad96ac3251\");" + "document.ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_6748615aba7a4a3abecfdbad96ac3251.append($(\".\"));" + "document.ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_6748615aba7a4a3abecfdbad96ac3251.append($(\".\"));" + "document.ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493.append($(\"F\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_6748615aba7a4a3abecfdbad96ac3251.append($(\".\"));" + "document.ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "delete document.ipython_nose_6748615aba7a4a3abecfdbad96ac3251;" + "delete document.ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493;" ], "output_type": "display_data" }, @@ -1839,27 +2055,55 @@ " \n", " \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", "
\n", "  \n", "
\n", - "
\n", + "
\n", "  \n", "
\n", - " 3/3 tests passed\n", + " 3/4 tests passed; 1 failed\n", + "
\n", + " \n", + "
\n", + "
\n", + " failed: __main__.test_mean_of_empty_function_raises_value_error\n", + " [toggle traceback]\n", + "
\n", + "
Traceback (most recent call last):\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n",
+        "    testMethod()\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n",
+        "    self.test(*self.arg)\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 67, in newfunc\n",
+        "    raise AssertionError(message)\n",
+        "AssertionError: test_mean_of_empty_function_raises_value_error() did not raise ValueError\n",
+        "
\n", "
\n", " " ], "output_type": "pyout", - "prompt_number": 26, + "prompt_number": 29, "text": [ - "3/3 tests passed\n" + "3/4 tests passed; 1 failed\n", + "========\n", + "__main__.test_mean_of_empty_function_raises_value_error\n", + "========\n", + "Traceback (most recent call last):\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n", + " testMethod()\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", + " self.test(*self.arg)\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 67, in newfunc\n", + " raise AssertionError(message)\n", + "AssertionError: test_mean_of_empty_function_raises_value_error() did not raise ValueError\n", + "\n" ] } ], - "prompt_number": 26 + "prompt_number": 29 }, { "cell_type": "markdown", @@ -1899,7 +2143,7 @@ "source": [ "## Results\n", "\n", - "You probably wound up with something like this." + "When I first wrote this code, I wound up with something like this:" ] }, { @@ -1916,13 +2160,13 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 1 + "prompt_number": 30 }, { "cell_type": "markdown", "metadata": {}, "source": [ - "How good was your testing?" + "How good was my testing?" ] }, { @@ -1936,13 +2180,13 @@ "outputs": [ { "output_type": "pyout", - "prompt_number": 2, + "prompt_number": 31, "text": [ "0.0" ] } ], - "prompt_number": 2 + "prompt_number": 31 }, { "cell_type": "code", @@ -1955,13 +2199,13 @@ "outputs": [ { "output_type": "pyout", - "prompt_number": 5, + "prompt_number": 32, "text": [ "1.0" ] } ], - "prompt_number": 5 + "prompt_number": 32 }, { "cell_type": "code", @@ -1974,13 +2218,13 @@ "outputs": [ { "output_type": "pyout", - "prompt_number": 3, + "prompt_number": 33, "text": [ "3.0" ] } ], - "prompt_number": 3 + "prompt_number": 33 }, { "cell_type": "code", @@ -1993,13 +2237,13 @@ "outputs": [ { "output_type": "pyout", - "prompt_number": 4, + "prompt_number": 34, "text": [ "4.566666666666666" ] } ], - "prompt_number": 4 + "prompt_number": 34 }, { "cell_type": "code", @@ -2016,58 +2260,273 @@ "output_type": "pyerr", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmean\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m\u001b[0m in \u001b[0;36mmean\u001b[0;34m(numbers)\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mnumber\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mnumbers\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mtotal\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtotal\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mtotal\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0mfloat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnumbers\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmean\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mmean\u001b[0;34m(numbers)\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mnumber\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mnumbers\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mtotal\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtotal\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mtotal\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0mfloat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnumbers\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m: float division by zero" ] } ], - "prompt_number": 6 + "prompt_number": 35 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "***\n", + "# Exceptions\n", + "***\n", + "\n", + "An empty list has a length of zero. The loop doesn't iterate, so total stays at 0.0, which is what we initialized it to, and the code happily attempts to divide zero by zero, resulting in an error.\n", + "\n", + "`ZeroDivisionError` is called an \"exception\". Our code can raise exceptions as well, and we can even define our own exceptions if we want. While this exception works perfectly fine, it could be a bit more clear, and I obviously missed a test case, which means I missed implementing a piece of beneficial behavior in my `mean` function. So we need to add a test, and we need to update our `mean` function to die more gracefully in the event of an empty list. We'll start with the test." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import nose.tools\n", + "\n", + "@nose.tools.raises(ValueError)\n", + "def test_mean_of_empty_function_raises_value_error():\n", + " mean([])" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 36 }, { "cell_type": "code", "collapsed": false, "input": [ - "import nose.tools as nt" + "%nose" ], "language": "python", "metadata": {}, "outputs": [ { - "output_type": "stream", - "stream": "stdout", + "html": [ + "
" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab = $(\"#ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab\");" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab.append($(\".\"));" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab.append($(\".\"));" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab.append($(\"E\"));" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab.append($(\".\"));" + ], + "output_type": "display_data" + }, + { + "javascript": [ + "delete document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab;" + ], + "output_type": "display_data" + }, + { + "html": [ + " \n", + " \n", + " \n", + " \n", + "
\n", + "
\n", + "  \n", + "
\n", + "
\n", + "  \n", + "
\n", + "
\n", + "  \n", + "
\n", + " 3/4 tests passed; 1 failed\n", + "
\n", + " \n", + "
\n", + "
\n", + " failed: __main__.test_mean_of_empty_function_raises_value_error\n", + " [toggle traceback]\n", + "
\n", + "
Traceback (most recent call last):\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n",
+        "    testMethod()\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n",
+        "    self.test(*self.arg)\n",
+        "  File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 60, in newfunc\n",
+        "    func(*arg, **kw)\n",
+        "  File \"<ipython-input-36-bc417f346267>\", line 5, in test_mean_of_empty_function_raises_value_error\n",
+        "    mean([])\n",
+        "  File \"<ipython-input-30-16ccb79ef6d8>\", line 6, in mean\n",
+        "    return total/float(len(numbers))\n",
+        "ZeroDivisionError: float division by zero\n",
+        "
\n", + "
\n", + " " + ], + "output_type": "pyout", + "prompt_number": 37, "text": [ - "9.0\n", - "56\n" + "3/4 tests passed; 1 failed\n", + "========\n", + "__main__.test_mean_of_empty_function_raises_value_error\n", + "========\n", + "Traceback (most recent call last):\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/unittest/case.py\", line 331, in run\n", + " testMethod()\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/case.py\", line 197, in runTest\n", + " self.test(*self.arg)\n", + " File \"/Users/Jon/Applications/anaconda/lib/python2.7/site-packages/nose/tools/nontrivial.py\", line 60, in newfunc\n", + " func(*arg, **kw)\n", + " File \"\", line 5, in test_mean_of_empty_function_raises_value_error\n", + " mean([])\n", + " File \"\", line 6, in mean\n", + " return total/float(len(numbers))\n", + "ZeroDivisionError: float division by zero\n", + "\n" ] } ], - "prompt_number": 31 + "prompt_number": 37 }, { "cell_type": "code", "collapsed": false, "input": [ - "def test_mean1():\n", - " m = calc_mean([1, 2, 3])\n", - " assert m == 2\n", - " \n", - "def test_mean2():\n", - " m = calc_mean([1])\n", - " assert m == 1\n", - "\n", - "def test_mean3():\n", - " m = calc_mean([3.4, 3.5, 3.6])\n", - " assert m == 3.5\n", - "\n", - "@nt.raises(ValueError)\n", - "def test_mean4():\n", - " m = calc_mean([])" + "def mean(numbers):\n", + " '''Returns the mean of the provided list of numbers.'''\n", + " if len(numbers) == 0:\n", + " raise ValueError, \"Empty list received by mean\"\n", + " \n", + " total = 0.0\n", + " for number in numbers:\n", + " total = total + number\n", + " return total/float(len(numbers))" ], "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 28 + "prompt_number": 39 }, { "cell_type": "code", @@ -2080,49 +2539,43 @@ "outputs": [ { "html": [ - "
" + "
" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0 = $(\"#ipython_nose_78c80018c7cf4f79834c36da78624ba0\");" + "document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0 = $(\"#ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0\");" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\".\"));" + "document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\".\"));" + "document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\".\"));" + "document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\".\"));" + "document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0.append($(\".\"));" ], "output_type": "display_data" }, { "javascript": [ - "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\".\"));" - ], - "output_type": "display_data" - }, - { - "javascript": [ - "delete document.ipython_nose_78c80018c7cf4f79834c36da78624ba0;" + "delete document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0;" ], "output_type": "display_data" }, @@ -2233,18 +2686,61 @@ "
\n", "  \n", "
\n", - " 5/5 tests passed\n", + " 4/4 tests passed\n", "
\n", " " ], "output_type": "pyout", - "prompt_number": 31, + "prompt_number": 40, "text": [ - "5/5 tests passed\n" + "4/4 tests passed\n" ] } ], - "prompt_number": 31 + "prompt_number": 40 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "mean([])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "Empty list received by mean", + "output_type": "pyerr", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmean\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mmean\u001b[0;34m(numbers)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m'''Returns the mean of the provided list of numbers.'''\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnumbers\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"Empty list received by mean\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mtotal\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0.0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: Empty list received by mean" + ] + } + ], + "prompt_number": 47 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "***\n", + "**Aside: What are exceptions good for?**\n", + "\n", + "In addition to providing nice error messages, exceptions can be used to allow your program to handle unexpected - or *exceptional* - conditions gracefully. Python provides *exception handling*, which allows your code to respond to exceptions if they occur. Consider this example:\n", + "\n", + " while not success:\n", + " numbers = read_numbers_from_keyboard()\n", + " try:\n", + " result = mean(numbers)\n", + " success = True\n", + " except ValueError:\n", + " print 'Please try again'\n", + "\n", + "***" + ] }, { "cell_type": "code", -- 2.26.2