Skip to content

Instantly share code, notes, and snippets.

@ethanwhite
Created November 1, 2012 20:56
Show Gist options
  • Save ethanwhite/3996485 to your computer and use it in GitHub Desktop.
Save ethanwhite/3996485 to your computer and use it in GitHub Desktop.
Testing in an IPython Notebook
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "testing_in_ipynb"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Testing inside an IPython Notebook\n",
"===================================\n",
"\n",
"In my courses and as part of [Software Carpentry](http://software-carpentry.org)\n",
"I'm teaching more and more in IPython notebooks. One of the things I/we teach\n",
"is testing, so I wondered if I could teach it in a notebook as well. With quite\n",
"a lot of help from [Matthias Bussonnier](https://twitter.com/Mbussonn) I got it\n",
"working so I thought I'd share."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An example\n",
"----------------\n",
"\n",
"We will test a function that caluculates the GC-content of a DNA sequence.\n",
"The GC-content is simply the percentage of bases in the DNA sequence that\n",
"are either G's or C's. So, for example, the GC-content of 'ATTGC' is 40%.\n",
"\n",
"The function we are testing is ``get_gc_content()`` and it takes a single\n",
"argument, which is a string represting a sequence. This function is in\n",
"a custom module called ``dna_analysis.py``.\n",
"\n",
"### Create the module to test\n",
"We can use the ``%%file`` magic to save a block of code to a file, so we\n",
"can use that to create the module that we're going to test."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file dna_analysis.py\n",
"\n",
"\"\"\"Code for analyzing DNA sequences\"\"\"\n",
"\n",
"from __future__ import division\n",
"\n",
"def get_gc_content(seq):\n",
" \"\"\"Determine the GC content of a sequence\"\"\"\n",
" seq = seq.upper()\n",
" gc_content = 100 * (seq.count('G') + seq.count('C')) / len(seq)\n",
" return gc_content"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Writing dna_analysis.py\n"
]
}
],
"prompt_number": 1
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Create the test module\n",
"1. To use nosetests we need to save the test code to a Python file starting with the word *test*\n",
"2. We then need to import the function(s) we are going to test\n",
"3. Then we right a simple function (whose name starts with *test*) that calls the function and\n",
"checks to see if it returns the right value"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%file test_dna.py\n",
"\n",
"from dna_analysis import get_gc_content\n",
"\n",
"def test_get_gc_content_zero():\n",
" assert get_gc_content('ATTATTAAA') == 0\n",
" \n",
"def test_get_gc_content_lowercase():\n",
" assert get_gc_content('atgcatgc') == 50\n",
" \n",
"def test_get_gc_content_multiline():\n",
" sequence = \"\"\"atta\n",
"gccg\n",
"attt\n",
"cccg\"\"\"\n",
" assert get_gc_content(sequence) == 50"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Writing test_dna.py\n"
]
}
],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Run nosetests\n",
"We would normally run nosetests from the command line, so in IPython we can just call ``!nosetests``."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"!nosetests"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"..F\r\n",
"======================================================================\r\n",
"FAIL: test_dna.test_get_gc_content_multiline\r\n",
"----------------------------------------------------------------------\r\n",
"Traceback (most recent call last):\r\n",
" File \"/usr/lib/python2.7/dist-packages/nose/case.py\", line 197, in runTest\r\n",
" self.test(*self.arg)\r\n",
" File \"/home/ethan/Dropbox/Teaching/ProgBiol/repo/ipynbs/test_dna.py\", line 15, in test_get_gc_content_multiline\r\n",
" assert get_gc_content(sequence) == 50\r\n",
"AssertionError\r\n",
"\r\n",
"----------------------------------------------------------------------\r\n",
"Ran 3 tests in 0.018s\r\n",
"\r\n",
"FAILED (failures=1)\r\n"
]
}
],
"prompt_number": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is exactly we output we want since the original function handles most basic cases,\n",
"but not multiline strings."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Value?\n",
"------\n",
"I wonder a bit about how valuable this is in the sense that we probably wouldn't\n",
"normally run tests this way (at least I don't at the moment). But, I think at\n",
"least for a short workshop where we're teaching all of the Python in a notebook\n",
"that the value of reducing the cognitive load relative to switching environments\n",
"for the testing portion might outweigh doing something in a way that might not be exactly\n",
"how we would do it in day to day work."
]
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment