Introduction
In a Test Driven
Development (TDD) approach to software
development writing
testcases is part of
detail design and detail planning activities. What is sometimes missing
in discussions about
agility
in particular about early phases, is an explorative element in software
construction happening within live sessions. Those are available in
languages supporting a REPL ( read-eval-print-loop) such as Lisp, Ruby,
Python but also OCaml, Haskell or Scala. Instead of wasting information
gained in these sessions after shutting them down an EE console uses a
simple ( and optional ) session recorder and (re-)player and intercepts
certain selected commands during re-play. This enables dirty
testscripts and throwaway tests. EE console tests might apply when
using a Python
testframework
is still too heavyweight.
Console tests are based on recording and replaying
interactive sessions. These sessions can be interrupted and continued.
The report
files might be edited.
A console test has just minimal overhead. Well it's
actually just the usuall assert statement and a single function to
check for exceptions.
1. Recorder & Player
EasyExtend consoles provide two options, one for recording sessions and
one for re-playing them:
usage: python fiber.py [options]
options:
--rec
use recording console to record interactive session
--rep SESSION replays an interactive session
Recorded sessions are placed into the directory
-
Path
EasyExtend/fibers/<fiber-name>/fibercon
and they are equipped with the extension:
Recorded sessions are placed into the directory
-
Extension
ees
1.1 Recorder options
A peculiarity of the --rec option is that it keeps optional parameters.
This is implemented by an optparse callback which is not shown in the
optparse help for the same reason.
-
Command
Recorded console
file
python
fiber.py --rec
<fiber-name>.ees
Console name is used as report name.
python
fiber.py --rec enum
<fiber-name>_<count>.ees
where count is the current
number of ees files in the fibercon directory + 1.
python fiber.py --rec +suffix
<fiber-name>_suffix.ees
Freely selectable suffix that is appended to the console name.
python fiber.py --rec prefix+
prefix_<fiber-name>.ees
Freely selectable prefix that is prepended to the console name.
python fiber.py --rec name
name
Arbitrary name without any restrictions.
1.2 Replaying a session
A session gets replayed when the --rep option is used. The --rep option
requires a single mandatory parameter. The parameter is complementary
to the parameter used for recording.
If for example
python fiber.py --rec
foo+
was used to create <fiber-name>_foo.ees
then
python fiber.py --rep
foo+
replays the recorded session. If
enum
was the option for --rec you need to know which report <fiber-name>_<
count>.ees
accordingly has been generated. The appropriate value for count is
always displayed in the session header.
So if you start Gallery with the option --rec enum. The session will
look like
__________________________________________________________________________________________________________
Gallery
On Python 2.4.3 Stackless 3.1b3 060516 (#69, Sep 7
2006, 12:45:31) [MSC v.1310 32 bit (Intel)]
Fiber documentation:
www.fiber-space.de/EasyExtend/doc/gallery/gallery.html
Creates session report
Gallery_4.ees
__________________________________________________________________________________________________________
gal>
1.2.1 Interruption and continuation
Two commands are provided for interruption of a replayed session as
well as its continuation.
-
Interrupt
replay
(without command execution)
?
placed before prompt as in
?>>>
1+2
-
No
execution of command
1+2
Continue replay
!
first character typed on the prompt
>>> !
Interrupt replay
(with command execution)
?!
placed before prompt as in
?!>>>
1+2
Command 1+2 is executed before
switching in interactive mode
The
? character works like a
breakpoint. You can continue typing commands and proceed by typing
! Note that the recorded
console is not implemented as a fiber and the singular '!' character is
parsed as user input.
1.3 Record and replay
It is possible to record and replay a session at the same time. This is
usefull when you interrupt a session using
? and continue edditing it.
Note that the --rec option must not have a parameter in this case but
the --rep option only.
-
Command
Recorded and
replayed console
file
python
fiber.py --rec --rep option
<fiber-name>_<option>.ees
Replays console session and re-records it.
This enables extending an existing recorded
session by new commands.
2. Tests
Console tests do not require a particular setup, a test suite or
anything like
this. Exceptions are captured by the REPL so everything that is needed
is to extract and display testinformation. An obvious selection for
this purpose are assert
statements. Not that they are treated special within an interactive
session. No magics is applied. Just the session player looks for assert and notifies whether
an AssertionError or any other exception is raised. All assertions and
their effects are listed
after
the replayed session.
__________________________________________________________________________________________________________
Gallery
On Python 2.4.3 Stackless 3.1b3 060516 (#69, Sep 7
2006, 12:45:31) [MSC v.1310 32 bit (Intel)]
Fiber documentation:
www.fiber-space.de/EasyExtend/doc/gallery/gallery.html
Replay session Gallery.ees
__________________________________________________________________________________________________________
gal> import sys
gal> sys.last_value
Traceback (most recent call last):
File "<input>", line 1, in ?
AttributeError: 'module' object has no attribute 'last_value'
?!gal> assert raises(AttributeError, lambda:
1/0)
# assertion 1
Traceback (most recent call last):
File "<input>", line 1, in ?
File
"C:\lang\python24\lib\site-packages\EasyExtend\eeconsole.py", line 482,
in raises
func(*args, **kwd)
File "<input>", line 1, in <lambda>
ZeroDivisionError: integer division or modulo by zero
gal> !
gal> assert raises(ZeroDivisionError, lambda:
1/0)
# assertion
2
gal>
__________________________________________________________________________________________________
--------------------.
Recorded assertions |
-------------------------------------------------------------------------------------------------
Status |ees ln |repl ln| Assertion
-------+-------+-------+-------------------------------------------------------------------------
ERROR | 11 | 14 | assert
raises(AttributeError, lambda: 1/0)
OK | 12 |
21 | assert raises(ZeroDivisionError, lambda: 1/0)
-------+-------+-------+--------------------------------------------------------------------------
In the
Recorded assertions report
section two types of line information is displayed
- ees ln - line of assertion
in the recorded ees report that gets replayed
- repl ln - line of assertion
in the replayed ees report
2.1 Test aid
Some additional test aids are usefull. These can be used in the process
of evaluating assertions.The above example already shows the use of the
function
raises.
2.1.1 The function raises
-
raises(
exception,
func, *args, **kwd)
- Returns True if func(*args, **kwd) raises exception otherwise
False.
The raises function is used to turn a raised exception into a boolean
value. It's counterpart in combination with assertions is the
assertRaises method of the class TestCase in Pythons unittest framework.
2.1.2 __ a.k.a. double underscore
In console applications a single underscore command _ can be used to
retrieve the last value. A double underscore command is used for
similar purposes but it is used to retrieve the last
relevant textual output in string
form. It does not make a distinction between values and exceptions.
With
relevance some
exclusions are justified e.g. console prompts or certain line breaks.