title: Testing students' code in Jupyter with a unittest
body: <p>I'd like my students to be able to check their code as they write it in a Jupyter Notebook by calling a function from an imported module which runs a unittest. This works fine unless the function needs to be checked against objects which are to be picked up in the global scope of the Notebook.</p>
  
  <p>Here's my <code>check_test</code> module:</p>
  
  <pre><code>import unittest
  from IPython.display import Markdown, display
  
  def printmd(string):
      display(Markdown(string))
  
  class Tests(unittest.TestCase):
  
      def check_add_2(self, add_2):
          val = 5
          self.assertAlmostEqual(add_2(val), 7)
  
      def check_add_n(self, add_n):
          n = 6
          val = 5
          self.assertAlmostEqual(add_n(val), 11)
  
  
  check = Tests()
  def run_check(check_name, func, hint=False):
      try:
          getattr(check, check_name)(func)
      except check.failureException as e:
          printmd('**&lt;span style="color: red;"&gt;FAILED&lt;/span&gt;**')
          if hint:
              print('Hint:',  e)
          return
      printmd('**&lt;span style="color: green;"&gt;PASSED&lt;/span&gt;**')
  </code></pre>
  
  <p>If the Notebook is:</p>
  
  <pre><code>In [1]: def add_2(val):
              return val + 2
  
  In [2]: def add_n(val):
              return val + n
  
  In [3]: import test_checks
  
  In [4]: test_checks.run_check('check_add_2', add_2)
          PASSED
  
  In [5]: test_checks.run_check('check_add_n', add_n)
          !!! ERROR !!!
  </code></pre>
  
  <p>The error here is not suprising: <code>add_n</code> doesn't know about the <code>n</code> I defined in <code>check_add_n</code>.</p>
  
  <p>So I got to thinking I could do something like:</p>
  
  <pre><code>In [6]: def add_n(val, default_n=None):
              if default_n:
                  n = default_n
              return val + n
  </code></pre>
  
  <p>in the Notebook, and then passing <code>n</code> in the test:</p>
  
  <pre><code>    def check_add_n(self, add_n):
          val = 5
          self.assertAlmostEqual(add_n(val, 6), 11)
  </code></pre>
  
  <p>But this is causing me <code>UnboundLocalError</code> headaches down the line because of the assignment of <code>n</code>, even within an <code>if</code> clause: this is apparently stopping the Notebook from picking up <code>n</code> in global scope when it's needed.</p>
  
  <p>For the avoidance of doubt, I don't want insist that <code>n</code> is passed as an argument to <code>add_n</code>: there could be many such objects used but not changed by the function being tested and I want them resolved in the outer scope.</p>
  
  <p>Any ideas how to go about this?</p>