Files
jlengrand.github.io/_posts/2011-12-02-pythonunittest-assertraises-raises-error.markdown
julien lengrand-lambert 8ee4ff838d Highlights Python code
2014-02-09 17:23:00 +01:00

141 lines
5.0 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
layout: post
status: publish
published: true
title: ! 'Python/Unittest : assertRaises raises Error'
author: Julien Lengrand-Lambert
author_login: jlengrand
author_email: julien@lengrand.fr
author_url: http://www.lengrand.fr
wordpress_id: 327
wordpress_url: http://www.lengrand.fr/?p=327
date: 2011-12-02 13:49:49.000000000 +01:00
categories:
- Python
tags:
- tippy
- unittest
- unit tests
- agile
- TDD
- test driven development
comments:
- id: 828
author: md
author_email: md@pmcd-cons.com
author_url: ''
date: !binary |-
MjAxMi0wNC0xOSAyMTo1MzowNSArMDIwMA==
date_gmt: !binary |-
MjAxMi0wNC0xOSAyMDo1MzowNSArMDIwMA==
content: ! "test_square_vlaue gives an eroror because assertRaises wants for 2nd
arg a callable not a function call.\r\nthis should do:\r\nself.assertRaises(TypeError,
df.square_value, 'A')"
- id: 873
author: Julien Lengrand-Lambert
author_email: julien@lengrand.fr
author_url: http://www.lengrand.fr
date: !binary |-
MjAxMi0wNC0yNCAxMjo0MToyNCArMDIwMA==
date_gmt: !binary |-
MjAxMi0wNC0yNCAxMTo0MToyNCArMDIwMA==
content: ! "Thanks for the info, I'll try this way of doing next time. \r\nIt is
prettier than my current solution :)"
---
Hi all,
Today, a small hint about <strong>unit tests</strong> in Python I discovered while working on <strong><a title="tippy on github" href="https://github.com/jlengrand/Tippy" target="_blank">Tippy</a></strong>.
In order to get as reliable code as possible, I am currently experiencing <strong><a title="agile" href="http://en.wikipedia.org/wiki/Agile_software_development" target="_blank">Agile</a></strong> techniques, and especially <strong><a title="TDD" href="http://fr.wikipedia.org/wiki/Test_Driven_Development" target="_blank">TDD</a></strong>. I develop <strong>Tippy</strong> in Python, and test methods with the excellent <a title="unittest framework" href="http://docs.python.org/library/unittest.html" target="_blank">unittest</a> framework.One of (in my mind at least) the most important tips Agile provides is the "<a title="fail fast" href="http://en.wikipedia.org/wiki/Fail-fast" target="_blank">fail fast</a>" rule. And to fit with this rule, all my methods check their inputs before performing anything else.
It implies a lot of <strong>assertRaises</strong> assertions in my tests. Here is an example of how it could be used :
Let's say I want to create a (dum) function calculating the square value of a number. I will have to test that the input can really be multiplied.
<ul>
<li>First, here is the corresponding (still dum :p) function in file dum_function.py :</li>
</ul>
{% highlight python %}
def square_value(a):
"""
Returns the square value of a.
"""
try:
out = a*a
except TypeError:
raise TypeError("Input should be a string:")
return out
{% endhighlight %}
<ul>
<li>Here is the test to be performed (only this test is inserted):</li>
</ul>
{% highlight python %}
import dum_function as df # import function module
import unittest
class Test(unittest.TestCase):
"""
The class inherits from unittest
"""
def setUp(self):
"""
This method is called before each test
"""
self.false_int = "A"
def tearDown(self):
"""
This method is called after each test
"""
pass
#---
## TESTS
def test_square_value(self):
# assertRaises(excClass, callableObj) prototype
self.assertRaises(TypeError, df.square_value(self.false_int))
if __name__ == "__main__":
unittest.main()
{% endhighlight %}
<ul>
<li>We are now ready to test our function! Here is what happens when trying to run the test :</li>
</ul>
{% highlight python %}
======================================================================
ERROR: test_square_value (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_dum_function.py", line 22, in test_square_value
self.assertRaises(TypeError, df.square_value(self.false_int))
File "/home/jlengrand/Desktop/function.py", line 8, in square_value
raise TypeError("Input should be a string:")
TypeError: Input should be a string:
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (errors=1)
{% endhighlight %}
The <strong>TypeError</strong> is actullay raised, and generates a test failure. The problem is that this is <strong>exactly the behavior</strong> we wanted :s.
To avoid this error, simply run the function using lambda in the test call :
{% highlight python %}
self.assertRaises(TypeError, lambda: df.square_value(self.false_int))
{% endhighlight %}
The final output :
{% highlight python %}
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
{% endhighlight %}
Perfect !
<em><strong>Note :</strong> For the purpose of this article, I did not work "backwards" (created test before the function). I think this would have been counter productive for the effect I wanted to highlight.</em>