~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/script.py

Fixed as per Martin's review.

* doc/developers/testing.txt: 
Add a shelli-like tests section.

* bzrlib/tests/test_script.py:
Update scripts for new prefixes and fix echo tests.

* bzrlib/tests/script.py: Move doc to doc/developers/testing.txt.
(_script_to_commands): Commands are prefixed by '$', expected
output are not prefixed anymore.
(ScriptRunner.do_echo): Put spaces between arguments.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
16
17
"""Shell-like test scripts.
17
18
 
18
 
This allows users to write tests in a syntax very close to a shell session,
19
 
using a restricted and limited set of commands that should be enough to mimic
20
 
most of the behaviours.
21
 
 
22
 
A script is a set of commands, each command is composed of:
23
 
- one mandatory command line,
24
 
- one optional set of input lines to feed the command,
25
 
- one optional set of output expected lines,
26
 
- one optional set of error expected lines.
27
 
 
28
 
The optional lines starts with a special string (mnemonic: shell redirection):
29
 
- '<' for input,
30
 
- '>' for output,
31
 
- '2>' for errors,
32
 
 
33
 
The execution stops as soon as an expected output or an expected error is not
34
 
matched. 
35
 
 
36
 
When no output is specified, any ouput from the command is accepted
37
 
and let the execution continue. 
38
 
 
39
 
If an error occurs and no expected error is specified, the execution stops.
40
 
 
41
 
An error is defined by a returned status different from zero, not by the
42
 
presence of text on the error stream.
43
 
 
44
 
The matching is done on a full string comparison basis unless '...' is used, in
45
 
which case expected output/errors can be lees precise.
46
 
 
47
 
Examples:
48
 
 
49
 
The following will succeeds only if 'bzr add' outputs 'adding file'.
50
 
 
51
 
  bzr add file
52
 
  >adding file
53
 
 
54
 
If you want the command to succeed for any output, just use:
55
 
 
56
 
  bzr add file
57
 
 
58
 
The following will stop with an error:
59
 
 
60
 
  bzr not-a-command
61
 
 
62
 
If you want it to succeed, use:
63
 
 
64
 
  bzr not-a-command
65
 
  2> bzr: ERROR: unknown command "not-a-command"
66
 
 
67
 
You can use ellipsis (...) to replace any piece of text you don't want to be
68
 
matched exactly:
69
 
 
70
 
  bzr branch not-a-branch
71
 
  2>bzr: ERROR: Not a branch...not-a-branch/".
72
 
 
73
 
 
74
 
This can be used to ignore entire lines too:
75
 
 
76
 
cat
77
 
<first line
78
 
<second line
79
 
<third line
80
 
<fourth line
81
 
<last line
82
 
>first line
83
 
>...
84
 
>last line
85
 
 
86
 
You can check the content of a file with cat:
87
 
 
88
 
  cat <file
89
 
  >expected content
90
 
 
91
 
You can also check the existence of a file with cat, the following will fail if
92
 
the file doesn't exist:
93
 
 
94
 
  cat file
95
 
 
 
19
See developpers/testing.html for more explanations.
96
20
"""
97
21
 
98
22
import doctest
158
82
        if line == '':
159
83
            # Ignore empty lines
160
84
            continue
161
 
        if line.startswith('<'):
 
85
        if line.startswith('$'):
 
86
            # Time to output the current command
 
87
            add_command(cmd_cur, input, output, error)
 
88
            # And start a new one
 
89
            cmd_cur = list(split(line[1:]))
 
90
            cmd_line = lineno
 
91
            input, output, error = None, None, None
 
92
        elif line.startswith('<'):
162
93
            if input is None:
163
94
                if cmd_cur is None:
164
95
                    raise SyntaxError('No command for that input',
165
96
                                      (file_name, lineno, 1, orig))
166
97
                input = []
167
98
            input.append(line[1:] + '\n')
168
 
            continue
169
 
        elif line.startswith('>'):
170
 
            if output is None:
171
 
                if cmd_cur is None:
172
 
                    raise SyntaxError('No command for that output',
173
 
                                      (file_name, lineno, 1, orig))
174
 
                output = []
175
 
            output.append(line[1:] + '\n')
176
 
            continue
177
99
        elif line.startswith('2>'):
178
100
            if error is None:
179
101
                if cmd_cur is None:
181
103
                                      (file_name, lineno, 1, orig))
182
104
                error = []
183
105
            error.append(line[2:] + '\n')
184
 
            continue
185
106
        else:
186
 
            # Time to output the current command
187
 
            add_command(cmd_cur, input, output, error)
188
 
            # And start a new one
189
 
            cmd_cur = list(split(line))
190
 
            cmd_line = lineno
191
 
            input, output, error = None, None, None
 
107
            if output is None:
 
108
                if cmd_cur is None:
 
109
                    raise SyntaxError('No command for that output',
 
110
                                      (file_name, lineno, 1, orig))
 
111
                output = []
 
112
            output.append(line + '\n')
192
113
    # Add the last seen command
193
114
    add_command(cmd_cur, input, output, error)
194
115
    return commands
359
280
        if input and args:
360
281
                raise SyntaxError('Specify parameters OR use redirection')
361
282
        if args:
362
 
            input = ''.join(args)
 
283
            input = ' '.join(args)
363
284
        try:
364
285
            input = self._read_input(input, in_name)
365
286
        except IOError, e: