"* Refactoring\n",
"* Testing\n",
"* Nose\n",
- "* Test-driven development"
+ "* Test-driven development\n",
+ "* Exceptions"
]
},
{
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 1
+ "prompt_number": 4
},
{
"cell_type": "markdown",
"outputs": [
{
"output_type": "pyout",
- "prompt_number": 2,
+ "prompt_number": 5,
"text": [
"117"
]
}
],
- "prompt_number": 2
+ "prompt_number": 5
},
{
"cell_type": "markdown",
]
}
],
- "prompt_number": 3
+ "prompt_number": 6
},
{
"cell_type": "markdown",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 4
+ "prompt_number": 7
},
{
"cell_type": "markdown",
]
}
],
- "prompt_number": 5
+ "prompt_number": 8
},
{
"cell_type": "code",
"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",
]
}
],
- "prompt_number": 6
+ "prompt_number": 9
},
{
"cell_type": "markdown",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 7
+ "prompt_number": 10
},
{
"cell_type": "markdown",
"outputs": [
{
"output_type": "pyout",
- "prompt_number": 8,
+ "prompt_number": 11,
"text": [
"117"
]
}
],
- "prompt_number": 8
+ "prompt_number": 11
},
{
"cell_type": "markdown",
]
}
],
- "prompt_number": 9
+ "prompt_number": 12
},
{
"cell_type": "markdown",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 10
+ "prompt_number": 13
},
{
"cell_type": "markdown",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 12
+ "prompt_number": 14
},
{
"cell_type": "markdown",
"output_type": "pyerr",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-13-2d797333ff4c>\u001b[0m in \u001b[0;36m<module>\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<ipython-input-13-2d797333ff4c>\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<ipython-input-15-2d797333ff4c>\u001b[0m in \u001b[0;36m<module>\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<ipython-input-15-2d797333ff4c>\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",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 14
+ "prompt_number": 16
},
{
"cell_type": "code",
"outputs": [
{
"html": [
- "<div id=\"ipython_nose_d38e10d9d55741bd9baa798e352d80ea\"></div>"
+ "<div id=\"ipython_nose_5e87717b84c447ad93143bde900e1715\"></div>"
],
"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($(\"<span>.</span>\"));"
+ "document.ipython_nose_5e87717b84c447ad93143bde900e1715.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_d38e10d9d55741bd9baa798e352d80ea.append($(\"<span>F</span>\"));"
+ "document.ipython_nose_5e87717b84c447ad93143bde900e1715.append($(\"<span>E</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "delete document.ipython_nose_d38e10d9d55741bd9baa798e352d80ea;"
+ "document.ipython_nose_5e87717b84c447ad93143bde900e1715.append($(\"<span>F</span>\"));"
+ ],
+ "output_type": "display_data"
+ },
+ {
+ "javascript": [
+ "delete document.ipython_nose_5e87717b84c447ad93143bde900e1715;"
],
"output_type": "display_data"
},
" </script>\n",
" \n",
" <div class=\"noseresults\">\n",
- " <div class=\"nosebar fail leftmost\" style=\"width: 50%\">\n",
+ " <div class=\"nosebar fail leftmost\" style=\"width: 66%\">\n",
" \n",
" </div>\n",
" <div class=\"nosebar skip\" style=\"width: 0%\">\n",
" \n",
" </div>\n",
- " <div class=\"nosebar pass rightmost\" style=\"width: 50%\">\n",
+ " <div class=\"nosebar pass rightmost\" style=\"width: 34%\">\n",
" \n",
" </div>\n",
- " 1/2 tests passed; 1 failed\n",
+ " 1/3 tests passed; 2 failed\n",
+ " </div>\n",
+ " \n",
+ " <div class=\"nosefailure\">\n",
+ " <div class=\"nosefailbanner\">\n",
+ " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_empty_function_raises_value_error</span>\n",
+ " [<a class=\"nosefailtoggle\" href=\"#\">toggle traceback</a>]\n",
+ " </div>\n",
+ " <pre class=\"nosetraceback\">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 \"<<a href=\"#ipython-input-2-bc417f346267\">ipython-input-2-bc417f346267</a><script>\n",
+ " $(\"div.prompt.input_prompt:contains([2])\")\n",
+ " .attr(\"id\", \"ipython-input-2-bc417f346267\");\n",
+ " </script>>\", line 5, in test_mean_of_empty_function_raises_value_error\n",
+ " mean([])\n",
+ "NameError: global name 'mean' is not defined\n",
+ "</pre>\n",
" </div>\n",
" \n",
" <div class=\"nosefailure\">\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 \"<<a href=\"#ipython-input-13-2d797333ff4c\">ipython-input-13-2d797333ff4c</a><script>\n",
- " $(\"div.prompt.input_prompt:contains([13])\")\n",
- " .attr(\"id\", \"ipython-input-13-2d797333ff4c\");\n",
+ " File \"<<a href=\"#ipython-input-15-2d797333ff4c\">ipython-input-15-2d797333ff4c</a><script>\n",
+ " $(\"div.prompt.input_prompt:contains([15])\")\n",
+ " .attr(\"id\", \"ipython-input-15-2d797333ff4c\");\n",
" </script>>\", 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",
" "
],
"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 \"<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",
"__main__.test_add_two_plus_two_equals_four\n",
"========\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 \"<ipython-input-13-2d797333ff4c>\", line 5, in test_add_two_plus_two_equals_four\n",
+ " File \"<ipython-input-15-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",
"\n"
]
}
],
- "prompt_number": 15
+ "prompt_number": 18
},
{
"cell_type": "markdown",
]
}
],
- "prompt_number": 16
+ "prompt_number": 19
},
{
"cell_type": "markdown",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 17
+ "prompt_number": 20
},
{
"cell_type": "code",
"outputs": [
{
"html": [
- "<div id=\"ipython_nose_b902caf7914c4fb3b2efaf1c540ce8e0\"></div>"
+ "<div id=\"ipython_nose_510c086cad7b476795575f3b317d1255\"></div>"
+ ],
+ "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($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_b902caf7914c4fb3b2efaf1c540ce8e0.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_510c086cad7b476795575f3b317d1255.append($(\"<span>E</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_b902caf7914c4fb3b2efaf1c540ce8e0.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_510c086cad7b476795575f3b317d1255.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "delete document.ipython_nose_b902caf7914c4fb3b2efaf1c540ce8e0;"
+ "delete document.ipython_nose_510c086cad7b476795575f3b317d1255;"
],
"output_type": "display_data"
},
" </script>\n",
" \n",
" <div class=\"noseresults\">\n",
- " <div class=\"nosebar fail leftmost\" style=\"width: 0%\">\n",
+ " <div class=\"nosebar fail leftmost\" style=\"width: 33%\">\n",
" \n",
" </div>\n",
" <div class=\"nosebar skip\" style=\"width: 0%\">\n",
" \n",
" </div>\n",
- " <div class=\"nosebar pass rightmost\" style=\"width: 100%\">\n",
+ " <div class=\"nosebar pass rightmost\" style=\"width: 67%\">\n",
" \n",
" </div>\n",
- " 2/2 tests passed\n",
+ " 2/3 tests passed; 1 failed\n",
+ " </div>\n",
+ " \n",
+ " <div class=\"nosefailure\">\n",
+ " <div class=\"nosefailbanner\">\n",
+ " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_empty_function_raises_value_error</span>\n",
+ " [<a class=\"nosefailtoggle\" href=\"#\">toggle traceback</a>]\n",
+ " </div>\n",
+ " <pre class=\"nosetraceback\">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 \"<<a href=\"#ipython-input-2-bc417f346267\">ipython-input-2-bc417f346267</a><script>\n",
+ " $(\"div.prompt.input_prompt:contains([2])\")\n",
+ " .attr(\"id\", \"ipython-input-2-bc417f346267\");\n",
+ " </script>>\", line 5, in test_mean_of_empty_function_raises_value_error\n",
+ " mean([])\n",
+ "NameError: global name 'mean' is not defined\n",
+ "</pre>\n",
" </div>\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 \"<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"
]
}
],
- "prompt_number": 18
+ "prompt_number": 21
},
{
"cell_type": "markdown",
"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",
"outputs": [
{
"html": [
- "<div id=\"ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197\"></div>"
+ "<div id=\"ipython_nose_880d0b5c63014ac78937ccad69cf89d2\"></div>"
+ ],
+ "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($(\"<span>E</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197.append($(\"<span>E</span>\"));"
+ "document.ipython_nose_880d0b5c63014ac78937ccad69cf89d2.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_880d0b5c63014ac78937ccad69cf89d2.append($(\"<span>E</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_880d0b5c63014ac78937ccad69cf89d2.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "delete document.ipython_nose_a3c3d168eb2c4a988da0f4a492cbd197;"
+ "delete document.ipython_nose_880d0b5c63014ac78937ccad69cf89d2;"
],
"output_type": "display_data"
},
" </script>\n",
" \n",
" <div class=\"noseresults\">\n",
- " <div class=\"nosebar fail leftmost\" style=\"width: 33%\">\n",
+ " <div class=\"nosebar fail leftmost\" style=\"width: 50%\">\n",
" \n",
" </div>\n",
" <div class=\"nosebar skip\" style=\"width: 0%\">\n",
" \n",
" </div>\n",
- " <div class=\"nosebar pass rightmost\" style=\"width: 67%\">\n",
+ " <div class=\"nosebar pass rightmost\" style=\"width: 50%\">\n",
" \n",
" </div>\n",
- " 2/3 tests passed; 1 failed\n",
+ " 2/4 tests passed; 2 failed\n",
" </div>\n",
" \n",
" <div class=\"nosefailure\">\n",
" <div class=\"nosefailbanner\">\n",
- " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_zero</span>\n",
+ " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_zero_is_zero</span>\n",
" [<a class=\"nosefailtoggle\" href=\"#\">toggle traceback</a>]\n",
" </div>\n",
" <pre class=\"nosetraceback\">Traceback (most recent call last):\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 \"<<a href=\"#ipython-input-19-481e1c58db22\">ipython-input-19-481e1c58db22</a><script>\n",
- " $(\"div.prompt.input_prompt:contains([19])\")\n",
- " .attr(\"id\", \"ipython-input-19-481e1c58db22\");\n",
- " </script>>\", line 2, in test_mean_of_zero\n",
+ " File \"<<a href=\"#ipython-input-22-ee2ab148c1b0\">ipython-input-22-ee2ab148c1b0</a><script>\n",
+ " $(\"div.prompt.input_prompt:contains([22])\")\n",
+ " .attr(\"id\", \"ipython-input-22-ee2ab148c1b0\");\n",
+ " </script>>\", line 2, in test_mean_of_zero_is_zero\n",
" assert 0 == mean([0])\n",
"NameError: global name 'mean' is not defined\n",
"</pre>\n",
" </div>\n",
+ " \n",
+ " <div class=\"nosefailure\">\n",
+ " <div class=\"nosefailbanner\">\n",
+ " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_empty_function_raises_value_error</span>\n",
+ " [<a class=\"nosefailtoggle\" href=\"#\">toggle traceback</a>]\n",
+ " </div>\n",
+ " <pre class=\"nosetraceback\">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 \"<<a href=\"#ipython-input-2-bc417f346267\">ipython-input-2-bc417f346267</a><script>\n",
+ " $(\"div.prompt.input_prompt:contains([2])\")\n",
+ " .attr(\"id\", \"ipython-input-2-bc417f346267\");\n",
+ " </script>>\", line 5, in test_mean_of_empty_function_raises_value_error\n",
+ " mean([])\n",
+ "NameError: global name 'mean' is not defined\n",
+ "</pre>\n",
+ " </div>\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 \"<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",
+ "__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 \"<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"
]
}
],
- "prompt_number": 20
+ "prompt_number": 23
},
{
"cell_type": "code",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 21
+ "prompt_number": 24
},
{
"cell_type": "code",
"outputs": [
{
"html": [
- "<div id=\"ipython_nose_bbb38260de4a452086abb22e7db22dfd\"></div>"
+ "<div id=\"ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9\"></div>"
],
"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($(\"<span>E</span>\"));"
+ "document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9.append($(\"<span>E</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_bbb38260de4a452086abb22e7db22dfd.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_bbb38260de4a452086abb22e7db22dfd.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9.append($(\"<span>E</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "delete document.ipython_nose_bbb38260de4a452086abb22e7db22dfd;"
+ "document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9.append($(\"<span>.</span>\"));"
+ ],
+ "output_type": "display_data"
+ },
+ {
+ "javascript": [
+ "delete document.ipython_nose_c2735c7e3d0c4677b88a8a5cd4cdf4a9;"
],
"output_type": "display_data"
},
" </script>\n",
" \n",
" <div class=\"noseresults\">\n",
- " <div class=\"nosebar fail leftmost\" style=\"width: 33%\">\n",
+ " <div class=\"nosebar fail leftmost\" style=\"width: 50%\">\n",
" \n",
" </div>\n",
" <div class=\"nosebar skip\" style=\"width: 0%\">\n",
" \n",
" </div>\n",
- " <div class=\"nosebar pass rightmost\" style=\"width: 67%\">\n",
+ " <div class=\"nosebar pass rightmost\" style=\"width: 50%\">\n",
" \n",
" </div>\n",
- " 2/3 tests passed; 1 failed\n",
+ " 2/4 tests passed; 2 failed\n",
" </div>\n",
" \n",
" <div class=\"nosefailure\">\n",
" <div class=\"nosefailbanner\">\n",
- " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_zero</span>\n",
+ " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_zero_is_zero</span>\n",
" [<a class=\"nosefailtoggle\" href=\"#\">toggle traceback</a>]\n",
" </div>\n",
" <pre class=\"nosetraceback\">Traceback (most recent call last):\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 \"<<a href=\"#ipython-input-19-481e1c58db22\">ipython-input-19-481e1c58db22</a><script>\n",
- " $(\"div.prompt.input_prompt:contains([19])\")\n",
- " .attr(\"id\", \"ipython-input-19-481e1c58db22\");\n",
- " </script>>\", line 2, in test_mean_of_zero\n",
+ " File \"<<a href=\"#ipython-input-22-ee2ab148c1b0\">ipython-input-22-ee2ab148c1b0</a><script>\n",
+ " $(\"div.prompt.input_prompt:contains([22])\")\n",
+ " .attr(\"id\", \"ipython-input-22-ee2ab148c1b0\");\n",
+ " </script>>\", line 2, in test_mean_of_zero_is_zero\n",
" assert 0 == mean([0])\n",
"TypeError: mean() takes no arguments (1 given)\n",
"</pre>\n",
" </div>\n",
+ " \n",
+ " <div class=\"nosefailure\">\n",
+ " <div class=\"nosefailbanner\">\n",
+ " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_empty_function_raises_value_error</span>\n",
+ " [<a class=\"nosefailtoggle\" href=\"#\">toggle traceback</a>]\n",
+ " </div>\n",
+ " <pre class=\"nosetraceback\">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 \"<<a href=\"#ipython-input-2-bc417f346267\">ipython-input-2-bc417f346267</a><script>\n",
+ " $(\"div.prompt.input_prompt:contains([2])\")\n",
+ " .attr(\"id\", \"ipython-input-2-bc417f346267\");\n",
+ " </script>>\", line 5, in test_mean_of_empty_function_raises_value_error\n",
+ " mean([])\n",
+ "TypeError: mean() takes no arguments (1 given)\n",
+ "</pre>\n",
+ " </div>\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 \"<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",
+ "__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 \"<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"
]
}
],
- "prompt_number": 22
+ "prompt_number": 25
},
{
"cell_type": "code",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 23
+ "prompt_number": 26
},
{
"cell_type": "code",
"outputs": [
{
"html": [
- "<div id=\"ipython_nose_183426a0661b43479529049b993ae958\"></div>"
+ "<div id=\"ipython_nose_1e1bd17442294222a80f6cc462ac3176\"></div>"
+ ],
+ "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($(\"<span>F</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_183426a0661b43479529049b993ae958.append($(\"<span>F</span>\"));"
+ "document.ipython_nose_1e1bd17442294222a80f6cc462ac3176.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_183426a0661b43479529049b993ae958.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_1e1bd17442294222a80f6cc462ac3176.append($(\"<span>F</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_183426a0661b43479529049b993ae958.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_1e1bd17442294222a80f6cc462ac3176.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "delete document.ipython_nose_183426a0661b43479529049b993ae958;"
+ "delete document.ipython_nose_1e1bd17442294222a80f6cc462ac3176;"
],
"output_type": "display_data"
},
" </script>\n",
" \n",
" <div class=\"noseresults\">\n",
- " <div class=\"nosebar fail leftmost\" style=\"width: 33%\">\n",
+ " <div class=\"nosebar fail leftmost\" style=\"width: 50%\">\n",
" \n",
" </div>\n",
" <div class=\"nosebar skip\" style=\"width: 0%\">\n",
" \n",
" </div>\n",
- " <div class=\"nosebar pass rightmost\" style=\"width: 67%\">\n",
+ " <div class=\"nosebar pass rightmost\" style=\"width: 50%\">\n",
" \n",
" </div>\n",
- " 2/3 tests passed; 1 failed\n",
+ " 2/4 tests passed; 2 failed\n",
" </div>\n",
" \n",
" <div class=\"nosefailure\">\n",
" <div class=\"nosefailbanner\">\n",
- " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_zero</span>\n",
+ " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_zero_is_zero</span>\n",
" [<a class=\"nosefailtoggle\" href=\"#\">toggle traceback</a>]\n",
" </div>\n",
" <pre class=\"nosetraceback\">Traceback (most recent call last):\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 \"<<a href=\"#ipython-input-19-481e1c58db22\">ipython-input-19-481e1c58db22</a><script>\n",
- " $(\"div.prompt.input_prompt:contains([19])\")\n",
- " .attr(\"id\", \"ipython-input-19-481e1c58db22\");\n",
- " </script>>\", line 2, in test_mean_of_zero\n",
+ " File \"<<a href=\"#ipython-input-22-ee2ab148c1b0\">ipython-input-22-ee2ab148c1b0</a><script>\n",
+ " $(\"div.prompt.input_prompt:contains([22])\")\n",
+ " .attr(\"id\", \"ipython-input-22-ee2ab148c1b0\");\n",
+ " </script>>\", line 2, in test_mean_of_zero_is_zero\n",
" assert 0 == mean([0])\n",
"AssertionError\n",
"</pre>\n",
" </div>\n",
+ " \n",
+ " <div class=\"nosefailure\">\n",
+ " <div class=\"nosefailbanner\">\n",
+ " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_empty_function_raises_value_error</span>\n",
+ " [<a class=\"nosefailtoggle\" href=\"#\">toggle traceback</a>]\n",
+ " </div>\n",
+ " <pre class=\"nosetraceback\">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",
+ "</pre>\n",
+ " </div>\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 \"<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",
+ "__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",
"language": "python",
"metadata": {},
"outputs": [],
- "prompt_number": 25
+ "prompt_number": 28
},
{
"cell_type": "code",
"outputs": [
{
"html": [
- "<div id=\"ipython_nose_6748615aba7a4a3abecfdbad96ac3251\"></div>"
+ "<div id=\"ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493\"></div>"
+ ],
+ "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($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_6748615aba7a4a3abecfdbad96ac3251.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_6748615aba7a4a3abecfdbad96ac3251.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493.append($(\"<span>F</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_6748615aba7a4a3abecfdbad96ac3251.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "delete document.ipython_nose_6748615aba7a4a3abecfdbad96ac3251;"
+ "delete document.ipython_nose_fe9e7f6480d54f919bfa6edad2ce0493;"
],
"output_type": "display_data"
},
" </script>\n",
" \n",
" <div class=\"noseresults\">\n",
- " <div class=\"nosebar fail leftmost\" style=\"width: 0%\">\n",
+ " <div class=\"nosebar fail leftmost\" style=\"width: 25%\">\n",
" \n",
" </div>\n",
" <div class=\"nosebar skip\" style=\"width: 0%\">\n",
" \n",
" </div>\n",
- " <div class=\"nosebar pass rightmost\" style=\"width: 100%\">\n",
+ " <div class=\"nosebar pass rightmost\" style=\"width: 75%\">\n",
" \n",
" </div>\n",
- " 3/3 tests passed\n",
+ " 3/4 tests passed; 1 failed\n",
+ " </div>\n",
+ " \n",
+ " <div class=\"nosefailure\">\n",
+ " <div class=\"nosefailbanner\">\n",
+ " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_empty_function_raises_value_error</span>\n",
+ " [<a class=\"nosefailtoggle\" href=\"#\">toggle traceback</a>]\n",
+ " </div>\n",
+ " <pre class=\"nosetraceback\">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",
+ "</pre>\n",
" </div>\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",
"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:"
]
},
{
"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?"
]
},
{
"outputs": [
{
"output_type": "pyout",
- "prompt_number": 2,
+ "prompt_number": 31,
"text": [
"0.0"
]
}
],
- "prompt_number": 2
+ "prompt_number": 31
},
{
"cell_type": "code",
"outputs": [
{
"output_type": "pyout",
- "prompt_number": 5,
+ "prompt_number": 32,
"text": [
"1.0"
]
}
],
- "prompt_number": 5
+ "prompt_number": 32
},
{
"cell_type": "code",
"outputs": [
{
"output_type": "pyout",
- "prompt_number": 3,
+ "prompt_number": 33,
"text": [
"3.0"
]
}
],
- "prompt_number": 3
+ "prompt_number": 33
},
{
"cell_type": "code",
"outputs": [
{
"output_type": "pyout",
- "prompt_number": 4,
+ "prompt_number": 34,
"text": [
"4.566666666666666"
]
}
],
- "prompt_number": 4
+ "prompt_number": 34
},
{
"cell_type": "code",
"output_type": "pyerr",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-6-e9e2222d800d>\u001b[0m in \u001b[0;36m<module>\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<ipython-input-1-16ccb79ef6d8>\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<ipython-input-35-e9e2222d800d>\u001b[0m in \u001b[0;36m<module>\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<ipython-input-30-16ccb79ef6d8>\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": [
+ "<div id=\"ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab\"></div>"
+ ],
+ "output_type": "display_data"
+ },
+ {
+ "javascript": [
+ "document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab = $(\"#ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab\");"
+ ],
+ "output_type": "display_data"
+ },
+ {
+ "javascript": [
+ "document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab.append($(\"<span>.</span>\"));"
+ ],
+ "output_type": "display_data"
+ },
+ {
+ "javascript": [
+ "document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab.append($(\"<span>.</span>\"));"
+ ],
+ "output_type": "display_data"
+ },
+ {
+ "javascript": [
+ "document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab.append($(\"<span>E</span>\"));"
+ ],
+ "output_type": "display_data"
+ },
+ {
+ "javascript": [
+ "document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab.append($(\"<span>.</span>\"));"
+ ],
+ "output_type": "display_data"
+ },
+ {
+ "javascript": [
+ "delete document.ipython_nose_5ceb566dc2db4a1cbddaa43327f83fab;"
+ ],
+ "output_type": "display_data"
+ },
+ {
+ "html": [
+ " <style type=\"text/css\">\n",
+ " span.nosefailedfunc {\n",
+ " font-family: monospace;\n",
+ " font-weight: bold;\n",
+ " }\n",
+ " div.noseresults {\n",
+ " width: 100%;\n",
+ " }\n",
+ " div.nosebar {\n",
+ " float: left;\n",
+ " padding: 1ex 0px 1ex 0px;\n",
+ " }\n",
+ " div.nosebar.fail {\n",
+ " background: #ff3019; /* Old browsers */\n",
+ " /* FF3.6+ */\n",
+ " background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 100%);\n",
+ " /* Chrome,Safari4+ */\n",
+ " background: -webkit-gradient(linear, left top, left bottom,\n",
+ " color-stop(0%,#ff3019),\n",
+ " color-stop(100%,#cf0404));\n",
+ " /* Chrome10+,Safari5.1+ */\n",
+ " background: -webkit-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+ " /* Opera 11.10+ */\n",
+ " background: -o-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+ " /* IE10+ */\n",
+ " background: -ms-linear-gradient(top, #ff3019 0%,#cf0404 100%);\n",
+ " /* W3C */\n",
+ " background: linear-gradient(to bottom, #ff3019 0%,#cf0404 100%);\n",
+ " }\n",
+ " div.nosebar.pass {\n",
+ " background: #52b152;\n",
+ " background: -moz-linear-gradient(top, #52b152 1%, #008a00 100%);\n",
+ " background: -webkit-gradient(linear, left top, left bottom,\n",
+ " color-stop(1%,#52b152),\n",
+ " color-stop(100%,#008a00));\n",
+ " background: -webkit-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+ " background: -o-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+ " background: -ms-linear-gradient(top, #52b152 1%,#008a00 100%);\n",
+ " background: linear-gradient(to bottom, #52b152 1%,#008a00 100%);\n",
+ " }\n",
+ " div.nosebar.skip {\n",
+ " background: #f1e767;\n",
+ " background: -moz-linear-gradient(top, #f1e767 0%, #feb645 100%);\n",
+ " background: -webkit-gradient(linear, left top, left bottom,\n",
+ " color-stop(0%,#f1e767),\n",
+ " color-stop(100%,#feb645));\n",
+ " background: -webkit-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+ " background: -o-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+ " background: -ms-linear-gradient(top, #f1e767 0%,#feb645 100%);\n",
+ " background: linear-gradient(to bottom, #f1e767 0%,#feb645 100%);\n",
+ " }\n",
+ " div.nosebar.leftmost {\n",
+ " border-radius: 4px 0 0 4px;\n",
+ " }\n",
+ " div.nosebar.rightmost {\n",
+ " border-radius: 0 4px 4px 0;\n",
+ " }\n",
+ " div.nosefailbanner {\n",
+ " border-radius: 4px 0 0 4px;\n",
+ " border-left: 10px solid #cf0404;\n",
+ " padding: 0.5ex 0em 0.5ex 1em;\n",
+ " margin-top: 1ex;\n",
+ " margin-bottom: 0px;\n",
+ " }\n",
+ " div.nosefailbanner.expanded {\n",
+ " border-radius: 4px 4px 0 0;\n",
+ " border-top: 10px solid #cf0404;\n",
+ " }\n",
+ " pre.nosetraceback {\n",
+ " border-radius: 0 4px 4px 4px;\n",
+ " border-left: 10px solid #cf0404;\n",
+ " padding: 1em;\n",
+ " margin-left: 0px;\n",
+ " margin-top: 0px;\n",
+ " display: none;\n",
+ " }\n",
+ " </style>\n",
+ " \n",
+ " <script>\n",
+ " setTimeout(function () {\n",
+ " $('.nosefailtoggle').bind(\n",
+ " 'click',\n",
+ " function () {\n",
+ " $(\n",
+ " $(this)\n",
+ " .parent().toggleClass('expanded')\n",
+ " .parent()\n",
+ " .children()\n",
+ " .filter('.nosetraceback')\n",
+ " ).toggle();\n",
+ " }\n",
+ " );},\n",
+ " 0);\n",
+ " </script>\n",
+ " \n",
+ " <div class=\"noseresults\">\n",
+ " <div class=\"nosebar fail leftmost\" style=\"width: 25%\">\n",
+ " \n",
+ " </div>\n",
+ " <div class=\"nosebar skip\" style=\"width: 0%\">\n",
+ " \n",
+ " </div>\n",
+ " <div class=\"nosebar pass rightmost\" style=\"width: 75%\">\n",
+ " \n",
+ " </div>\n",
+ " 3/4 tests passed; 1 failed\n",
+ " </div>\n",
+ " \n",
+ " <div class=\"nosefailure\">\n",
+ " <div class=\"nosefailbanner\">\n",
+ " failed: <span class=\"nosefailedfunc\">__main__.test_mean_of_empty_function_raises_value_error</span>\n",
+ " [<a class=\"nosefailtoggle\" href=\"#\">toggle traceback</a>]\n",
+ " </div>\n",
+ " <pre class=\"nosetraceback\">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 \"<<a href=\"#ipython-input-36-bc417f346267\">ipython-input-36-bc417f346267</a><script>\n",
+ " $(\"div.prompt.input_prompt:contains([36])\")\n",
+ " .attr(\"id\", \"ipython-input-36-bc417f346267\");\n",
+ " </script>>\", line 5, in test_mean_of_empty_function_raises_value_error\n",
+ " mean([])\n",
+ " File \"<<a href=\"#ipython-input-30-16ccb79ef6d8\">ipython-input-30-16ccb79ef6d8</a><script>\n",
+ " $(\"div.prompt.input_prompt:contains([30])\")\n",
+ " .attr(\"id\", \"ipython-input-30-16ccb79ef6d8\");\n",
+ " </script>>\", line 6, in mean\n",
+ " return total/float(len(numbers))\n",
+ "ZeroDivisionError: float division by zero\n",
+ "</pre>\n",
+ " </div>\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 \"<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"
]
}
],
- "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",
"outputs": [
{
"html": [
- "<div id=\"ipython_nose_78c80018c7cf4f79834c36da78624ba0\"></div>"
+ "<div id=\"ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0\"></div>"
],
"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($(\"<span>.</span>\"));"
+ "document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\"<span>.</span>\"));"
+ "document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0.append($(\"<span>.</span>\"));"
],
"output_type": "display_data"
},
{
"javascript": [
- "document.ipython_nose_78c80018c7cf4f79834c36da78624ba0.append($(\"<span>.</span>\"));"
- ],
- "output_type": "display_data"
- },
- {
- "javascript": [
- "delete document.ipython_nose_78c80018c7cf4f79834c36da78624ba0;"
+ "delete document.ipython_nose_cd36649ad3264c26a9a1ce96cf0984c0;"
],
"output_type": "display_data"
},
" <div class=\"nosebar pass rightmost\" style=\"width: 100%\">\n",
" \n",
" </div>\n",
- " 5/5 tests passed\n",
+ " 4/4 tests passed\n",
" </div>\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<ipython-input-47-e9e2222d800d>\u001b[0m in \u001b[0;36m<module>\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<ipython-input-39-9120caace96b>\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",