boom
.Write tests the same way
You can write tests using unittest
from the Python standard library. Read more about that here.
Let's make some bomb tests. I'm going to lay out the directory structure like this:
boom/
boom/__init__.py
boom/test
boom/test/__init__.py
boom/test/test_game.py
We'll make a really simple test for creating a Bomb
:
from unittest import TestCase
from boom.game import Bomb
class BombTest(TestCase):
def test_init(self):
bomb = Bomb(3, 4)
self.assertEqual(bomb.fuse, 3)
self.assertEqual(bomb.size, 4)
Trial
Twisted comes with an executable for running tests named trial
. You can tell it to run tests found in files:
trial boom/test/test_game.py
Or tests found in modules/packages.
trial boom.test.test_game
Running either of the above will result in something like this:
boom
test
test_game ... [ERROR]
===============================================================================
[ERROR]
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/twisted/trial/runner.py", line 677, in loadByNames
things.append(self.findByName(name))
File "/usr/local/lib/python2.7/dist-packages/twisted/trial/runner.py", line 487, in findByName
return reflect.namedAny(name)
File "/usr/local/lib/python2.7/dist-packages/twisted/python/reflect.py", line 464, in namedAny
topLevelPackage = _importAndCheckStack(trialname)
File "/home/matt/iffycan.git/tx-bite-3-testing/boom/test/test_game.py", line 3, in <module>
from boom.game import Bomb
exceptions.ImportError: No module named game
boom.test.test_game
-------------------------------------------------------------------------------
Ran 1 tests in 0.071s
FAILED (errors=1)
Let's fix the test. This post isn't about testing as much as the tools Twisted provides, so I'm going to skip the iterations I went through to arrive at this file:
class Bomb:
def __init__(self, fuse, size):
self.fuse = fuse
self.size = size
And now the tests pass. Yay!
boom.test.test_game
BombTest
test_init ... [OK]
-------------------------------------------------------------------------------
Ran 1 tests in 0.056s
PASSED (successes=1)
Trial finds tests
As our program grows, it will be tedious to test if we have to type out the filename or module name for each of our test files. trial
alleviates this by searching for things that look like tests. Generally, files with the word "test" in them are considered tests. We can run all of the boom
tests just by specifying the root package (e.g trial boom
):
boom.test.test_game
BombTest
test_init ... [OK]
-------------------------------------------------------------------------------
Ran 1 tests in 0.058s
PASSED (successes=1)
Temporary files are easy
Twisted includes a subclass of unittest.TestCase
which provides some very nice features. For instance, making temporary files and directories is easy using self.mktemp()
.
from twisted.trial.unittest import TestCase
class MkTempTest(TestCase):
def test_writeable(self):
filename = self.mktemp()
open(filename, 'w').write('foo')
You can skip irrelevant tests
Sometimes you only want to run certain tests under certain conditions. Perhaps your code has optional features, or perhaps some tests only apply to certain operating systems. Twisted provides ways of skipping tests.
Skip entire TestCase
s by setting a skip
attribute:
from twisted.trial.unittest import TestCase
class SkipTest1(TestCase):
skip = "Don't run these tests. They don't do anything"
def test_nothing(self):
pass
test_skip1
SkipTest1
test_nothing ... [SKIPPED]
===============================================================================
[SKIPPED]
Don't run these tests. They don't do anything
test_skip1.SkipTest1.test_nothing
-------------------------------------------------------------------------------
Ran 1 tests in 0.002s
PASSED (skips=1)
Skip individual tests by raising twisted.trial.unittest.SkipTest
:
from twisted.trial.unittest import TestCase, SkipTest
class SkipTest2(TestCase):
def test_nothing(self):
raise SkipTest("Waste of time")
test_skip2
SkipTest2
test_nothing ... [SKIPPED]
===============================================================================
[SKIPPED]
Waste of time
test_skip2.SkipTest2.test_nothing
-------------------------------------------------------------------------------
Ran 1 tests in 0.028s
PASSED (skips=1)
Test runs are logged and saved
When you run trial
, it creates or recreates a special directory named _trial_temp
. Inside, you'll find test.log
(a log of the test run). And you can inspect any files created with self.mktemp()
.
For instance, here's the test.log
from running trial test_mktemp.py
:
2012-06-02 17:20:27-0600 [-] Log opened.
2012-06-02 17:20:27-0600 [-] --> test_mktemp.MkTempTest.test_writeable <--
2012-06-02 17:20:27-0600 [-] using set_wakeup_fd
And there's a temporary file with foo
in it, created by the test:
$ cat _trial_temp/test_mktemp/MkTempTest/test_writeable/d31a0y/temp
foo
On this run, the file happened to end up in a directory named d31a0y/
. This will vary from run to run and won't be the same when you run it.
Keep reading
I've highlighted just a few of my favorite trial
features. All of the features described here do not involve the reactor
and are a perfectly useable for testing synchronous code. A future post will discuss asynchronous testing features provided by Twisted. Read more about trial here.
I've created a GitHub repo for this Bomberman clone. The files used in this post are in the tx-testing-1 branch.
No comments:
Post a Comment