Rev 4685: Fixed as per Martin's review. in file:///home/vila/src/bzr/experimental/shell-like-tests/

Vincent Ladeuil v.ladeuil+lp at free.fr
Thu Sep 17 15:15:15 BST 2009


At file:///home/vila/src/bzr/experimental/shell-like-tests/

------------------------------------------------------------
revno: 4685
revision-id: v.ladeuil+lp at free.fr-20090917141515-6e3yzx8v0oirgeyd
parent: v.ladeuil+lp at free.fr-20090911141915-spdcayvr91ighbzs
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: shell-like-tests
timestamp: Thu 2009-09-17 16:15:15 +0200
message:
  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.
-------------- next part --------------
=== modified file 'bzrlib/tests/script.py'
--- a/bzrlib/tests/script.py	2009-09-11 14:19:15 +0000
+++ b/bzrlib/tests/script.py	2009-09-17 14:15:15 +0000
@@ -13,86 +13,10 @@
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
 """Shell-like test scripts.
 
-This allows users to write tests in a syntax very close to a shell session,
-using a restricted and limited set of commands that should be enough to mimic
-most of the behaviours.
-
-A script is a set of commands, each command is composed of:
-- one mandatory command line,
-- one optional set of input lines to feed the command,
-- one optional set of output expected lines,
-- one optional set of error expected lines.
-
-The optional lines starts with a special string (mnemonic: shell redirection):
-- '<' for input,
-- '>' for output,
-- '2>' for errors,
-
-The execution stops as soon as an expected output or an expected error is not
-matched. 
-
-When no output is specified, any ouput from the command is accepted
-and let the execution continue. 
-
-If an error occurs and no expected error is specified, the execution stops.
-
-An error is defined by a returned status different from zero, not by the
-presence of text on the error stream.
-
-The matching is done on a full string comparison basis unless '...' is used, in
-which case expected output/errors can be lees precise.
-
-Examples:
-
-The following will succeeds only if 'bzr add' outputs 'adding file'.
-
-  bzr add file
-  >adding file
-
-If you want the command to succeed for any output, just use:
-
-  bzr add file
-
-The following will stop with an error:
-
-  bzr not-a-command
-
-If you want it to succeed, use:
-
-  bzr not-a-command
-  2> bzr: ERROR: unknown command "not-a-command"
-
-You can use ellipsis (...) to replace any piece of text you don't want to be
-matched exactly:
-
-  bzr branch not-a-branch
-  2>bzr: ERROR: Not a branch...not-a-branch/".
-
-
-This can be used to ignore entire lines too:
-
-cat
-<first line
-<second line
-<third line
-<fourth line
-<last line
->first line
->...
->last line
-
-You can check the content of a file with cat:
-
-  cat <file
-  >expected content
-
-You can also check the existence of a file with cat, the following will fail if
-the file doesn't exist:
-
-  cat file
-
+See developpers/testing.html for more explanations.
 """
 
 import doctest
@@ -158,22 +82,20 @@
         if line == '':
             # Ignore empty lines
             continue
-        if line.startswith('<'):
+        if line.startswith('$'):
+            # Time to output the current command
+            add_command(cmd_cur, input, output, error)
+            # And start a new one
+            cmd_cur = list(split(line[1:]))
+            cmd_line = lineno
+            input, output, error = None, None, None
+        elif line.startswith('<'):
             if input is None:
                 if cmd_cur is None:
                     raise SyntaxError('No command for that input',
                                       (file_name, lineno, 1, orig))
                 input = []
             input.append(line[1:] + '\n')
-            continue
-        elif line.startswith('>'):
-            if output is None:
-                if cmd_cur is None:
-                    raise SyntaxError('No command for that output',
-                                      (file_name, lineno, 1, orig))
-                output = []
-            output.append(line[1:] + '\n')
-            continue
         elif line.startswith('2>'):
             if error is None:
                 if cmd_cur is None:
@@ -181,14 +103,13 @@
                                       (file_name, lineno, 1, orig))
                 error = []
             error.append(line[2:] + '\n')
-            continue
         else:
-            # Time to output the current command
-            add_command(cmd_cur, input, output, error)
-            # And start a new one
-            cmd_cur = list(split(line))
-            cmd_line = lineno
-            input, output, error = None, None, None
+            if output is None:
+                if cmd_cur is None:
+                    raise SyntaxError('No command for that output',
+                                      (file_name, lineno, 1, orig))
+                output = []
+            output.append(line + '\n')
     # Add the last seen command
     add_command(cmd_cur, input, output, error)
     return commands
@@ -359,7 +280,7 @@
         if input and args:
                 raise SyntaxError('Specify parameters OR use redirection')
         if args:
-            input = ''.join(args)
+            input = ' '.join(args)
         try:
             input = self._read_input(input, in_name)
         except IOError, e:

=== modified file 'bzrlib/tests/test_script.py'
--- a/bzrlib/tests/test_script.py	2009-09-11 14:19:15 +0000
+++ b/bzrlib/tests/test_script.py	2009-09-17 14:15:15 +0000
@@ -32,29 +32,30 @@
 
     def test_simple_command(self):
         self.assertEquals([(['cd', 'trunk'], None, None, None)],
-                           script._script_to_commands('cd trunk'))
+                           script._script_to_commands('$ cd trunk'))
 
     def test_command_with_single_quoted_param(self):
-        story = """bzr commit -m 'two words'"""
+        story = """$ bzr commit -m 'two words'"""
         self.assertEquals([(['bzr', 'commit', '-m', "'two words'"],
                             None, None, None)],
                            script._script_to_commands(story))
 
     def test_command_with_double_quoted_param(self):
-        story = """bzr commit -m "two words" """
+        story = """$ bzr commit -m "two words" """
         self.assertEquals([(['bzr', 'commit', '-m', '"two words"'],
                             None, None, None)],
                            script._script_to_commands(story))
 
     def test_command_with_input(self):
-        self.assertEquals([(['cat', '>file'], 'content\n', None, None)],
-                           script._script_to_commands('cat >file\n<content\n'))
+        self.assertEquals(
+            [(['cat', '>file'], 'content\n', None, None)],
+            script._script_to_commands('$ cat >file\n<content\n'))
 
     def test_command_with_output(self):
         story = """
-bzr add
->adding file
->adding file2
+$ bzr add
+adding file
+adding file2
 """
         self.assertEquals([(['bzr', 'add'], None,
                             'adding file\nadding file2\n', None)],
@@ -62,7 +63,7 @@
 
     def test_command_with_error(self):
         story = """
-bzr branch foo
+$ bzr branch foo
 2>bzr: ERROR: Not a branch: "foo"
 """
         self.assertEquals([(['bzr', 'branch', 'foo'],
@@ -77,7 +78,7 @@
 
     def test_command_with_backquotes(self):
         story = """
-foo = `bzr file-id toto`
+$ foo = `bzr file-id toto`
 """
         self.assertEquals([(['foo', '=', '`bzr file-id toto`'],
                             None, None, None)],
@@ -124,24 +125,24 @@
 
     def test_stops_on_unexpected_output(self):
         story = """
-mkdir dir
-cd dir
->The cd command ouputs nothing
+$ mkdir dir
+$ cd dir
+The cd command ouputs nothing
 """
         self.assertRaises(AssertionError, self.run_script, story)
 
 
     def test_stops_on_unexpected_error(self):
         story = """
-cat
+$ cat
 <Hello
-bzr not-a-command
+$ bzr not-a-command
 """
         self.assertRaises(AssertionError, self.run_script, story)
 
     def test_continue_on_expected_error(self):
         story = """
-bzr not-a-command
+$ bzr not-a-command
 2>..."not-a-command"
 """
         self.run_script(story)
@@ -149,33 +150,33 @@
     def test_continue_on_error_output(self):
         # The status matters, not the output
         story = """
-bzr init
-cat >file
+$ bzr init
+$ cat >file
 <Hello
-bzr add file
-bzr commit -m 'adding file'
+$ bzr add file
+$ bzr commit -m 'adding file'
 """
         self.run_script(story)
 
     def test_ellipsis_output(self):
         story = """
-cat
+$ cat
 <first line
 <second line
 <last line
->first line
->...
->last line
+first line
+...
+last line
 """
         self.run_script(story)
         story = """
-bzr not-a-command
+$ bzr not-a-command
 2>..."not-a-command"
 """
         self.run_script(story)
 
         story = """
-bzr branch not-a-branch
+$ bzr branch not-a-branch
 2>bzr: ERROR: Not a branch...not-a-branch/".
 """
         self.run_script(story)
@@ -185,24 +186,24 @@
 
     def test_globing(self):
         self.run_script("""
-echo cat >cat
-echo dog >dog
-cat *
->cat
->dog
+$ echo cat >cat
+$ echo dog >dog
+$ cat *
+cat
+dog
 """)
 
     def test_quoted_globbing(self):
         self.run_script("""
-echo cat >cat
-cat '*'
+$ echo cat >cat
+$ cat '*'
 2>*: No such file or directory
 """)
 
     def test_quotes_removal(self):
         self.run_script("""
-echo 'cat' "dog" '"chicken"' "'dragon'"
->catdog"chicken"'dragon'
+$ echo 'cat' "dog" '"chicken"' "'dragon'"
+cat dog "chicken" 'dragon'
 """)
 
 
@@ -251,13 +252,13 @@
 
     def test_cat_bogus_input_file(self):
         self.run_script("""
-cat <file
+$ cat <file
 2>file: No such file or directory
 """)
 
     def test_cat_bogus_output_file(self):
         self.run_script("""
-cat >
+$ cat >
 2>: No such file or directory
 """)
 
@@ -265,7 +266,7 @@
         # We need a backing file sysytem for that test so it can't be in
         # TestEcho
         self.run_script("""
-echo <file
+$ echo <file
 2>file: No such file or directory
 """)
 
@@ -273,7 +274,7 @@
         # We need a backing file sysytem for that test so it can't be in
         # TestEcho
         self.run_script("""
-echo >
+$ echo >
 2>: No such file or directory
 """)
 
@@ -281,19 +282,19 @@
 class TestMkdir(script.TestCaseWithTransportAndScript):
 
     def test_mkdir_usage(self):
-        self.assertRaises(SyntaxError, self.run_script, 'mkdir')
-        self.assertRaises(SyntaxError, self.run_script, 'mkdir foo bar')
+        self.assertRaises(SyntaxError, self.run_script, '$ mkdir')
+        self.assertRaises(SyntaxError, self.run_script, '$ mkdir foo bar')
 
     def test_mkdir_jailed(self):
-        self.assertRaises(ValueError, self.run_script, 'mkdir /out-of-jail')
-        self.assertRaises(ValueError, self.run_script, 'mkdir ../out-of-jail')
+        self.assertRaises(ValueError, self.run_script, '$ mkdir /out-of-jail')
+        self.assertRaises(ValueError, self.run_script, '$ mkdir ../out-of-jail')
 
     def test_mkdir_in_jail(self):
         self.run_script("""
-mkdir dir
-cd dir
-mkdir ../dir2
-cd ..
+$ mkdir dir
+$ cd dir
+$ mkdir ../dir2
+$ cd ..
 """)
         self.failUnlessExists('dir')
         self.failUnlessExists('dir2')
@@ -302,29 +303,29 @@
 class TestCd(script.TestCaseWithTransportAndScript):
 
     def test_cd_usage(self):
-        self.assertRaises(SyntaxError, self.run_script, 'cd foo bar')
+        self.assertRaises(SyntaxError, self.run_script, '$ cd foo bar')
 
     def test_cd_out_of_jail(self):
-        self.assertRaises(ValueError, self.run_script, 'cd /out-of-jail')
-        self.assertRaises(ValueError, self.run_script, 'cd ..')
+        self.assertRaises(ValueError, self.run_script, '$ cd /out-of-jail')
+        self.assertRaises(ValueError, self.run_script, '$ cd ..')
 
     def test_cd_dir_and_back_home(self):
         self.assertEquals(self.test_dir, osutils.getcwd())
         self.run_script("""
-mkdir dir
-cd dir
+$ mkdir dir
+$ cd dir
 """)
         self.assertEquals(osutils.pathjoin(self.test_dir, 'dir'),
                           osutils.getcwd())
 
-        self.run_script('cd')
+        self.run_script('$ cd')
         self.assertEquals(self.test_dir, osutils.getcwd())
 
 
 class TestBzr(script.TestCaseWithTransportAndScript):
 
     def test_bzr_smoke(self):
-        self.run_script('bzr init branch')
+        self.run_script('$ bzr init branch')
         self.failUnlessExists('branch')
 
 
@@ -332,7 +333,7 @@
 
     def test_echo_usage(self):
         story = """
-echo foo
+$ echo foo
 <bar
 """
         self.assertRaises(SyntaxError, self.run_script, story)
@@ -351,8 +352,8 @@
     def test_echo_more_output(self):
         retcode, out, err = self.run_command(
             ['echo', 'hello', 'happy', 'world'],
-            None, 'hellohappyworld\n', None)
-        self.assertEquals('hellohappyworld\n', out)
+            None, 'hello happy world\n', None)
+        self.assertEquals('hello happy world\n', out)
         self.assertEquals(None, err)
 
     def test_echo_appended(self):
@@ -371,41 +372,41 @@
 class TestRm(script.TestCaseWithTransportAndScript):
 
     def test_rm_usage(self):
-        self.assertRaises(SyntaxError, self.run_script, 'rm')
-        self.assertRaises(SyntaxError, self.run_script, 'rm -ff foo')
+        self.assertRaises(SyntaxError, self.run_script, '$ rm')
+        self.assertRaises(SyntaxError, self.run_script, '$ rm -ff foo')
 
     def test_rm_file(self):
-        self.run_script('echo content >file')
+        self.run_script('$ echo content >file')
         self.failUnlessExists('file')
-        self.run_script('rm file')
+        self.run_script('$ rm file')
         self.failIfExists('file')
 
     def test_rm_file_force(self):
         self.failIfExists('file')
-        self.run_script('rm -f file')
+        self.run_script('$ rm -f file')
         self.failIfExists('file')
 
     def test_rm_files(self):
         self.run_script("""
-echo content >file
-echo content >file2
+$ echo content >file
+$ echo content >file2
 """)
         self.failUnlessExists('file2')
-        self.run_script('rm file file2')
+        self.run_script('$ rm file file2')
         self.failIfExists('file2')
 
     def test_rm_dir(self):
-        self.run_script('mkdir dir')
+        self.run_script('$ mkdir dir')
         self.failUnlessExists('dir')
         self.run_script("""
-rm dir
+$ rm dir
 2>rm: cannot remove 'dir': Is a directory
 """)
         self.failUnlessExists('dir')
 
     def test_rm_dir_recursive(self):
         self.run_script("""
-mkdir dir
-rm -r dir
+$ mkdir dir
+$ rm -r dir
 """)
         self.failIfExists('dir')

=== modified file 'doc/developers/testing.txt'
--- a/doc/developers/testing.txt	2009-09-02 23:45:04 +0000
+++ b/doc/developers/testing.txt	2009-09-17 14:15:15 +0000
@@ -201,6 +201,98 @@
   __ http://docs.python.org/lib/module-doctest.html
 
 
+Shell-like tests
+~~~~~~~~~~~~~~~~
+
+``bzrlib/tests/script.py`` allows users to write tests in a syntax very close to a shell session,
+using a restricted and limited set of commands that should be enough to mimic
+most of the behaviours.
+
+A script is a set of commands, each command is composed of:
+
+ * one mandatory command line,
+ * one optional set of input lines to feed the command,
+ * one optional set of output expected lines,
+ * one optional set of error expected lines.
+
+Input, output and error lines can be specified in any order.
+
+Except for the expected output, all lines start with a special
+string (based on their origin when used under a Unix shell):
+
+ * '$ ' for the command,
+ * '<' for input,
+ * nothing for output,
+ * '2>' for errors,
+
+Comments can be added anywhere, they start with '#' and end with
+the line.
+
+The execution stops as soon as an expected output or an expected error is not
+matched. 
+
+When no output is specified, any ouput from the command is accepted
+and execution continue. 
+
+If an error occurs and no expected error is specified, the execution stops.
+
+An error is defined by a returned status different from zero, not by the
+presence of text on the error stream.
+
+The matching is done on a full string comparison basis unless '...' is used, in
+which case expected output/errors can be less precise.
+
+Examples:
+
+The following will succeeds only if 'bzr add' outputs 'adding file'::
+
+  $ bzr add file
+  >adding file
+
+If you want the command to succeed for any output, just use::
+
+  $ bzr add file
+
+The following will stop with an error::
+
+  $ bzr not-a-command
+
+If you want it to succeed, use::
+
+  $ bzr not-a-command
+  2> bzr: ERROR: unknown command "not-a-command"
+
+You can use ellipsis (...) to replace any piece of text you don't want to be
+matched exactly::
+
+  $ bzr branch not-a-branch
+  2>bzr: ERROR: Not a branch...not-a-branch/".
+
+This can be used to ignore entire lines too::
+
+  $ cat
+  <first line
+  <second line
+  <third line
+  # And here we explain that surprising fourth line
+  <fourth line
+  <last line
+  >first line
+  >...
+  >last line
+
+You can check the content of a file with cat::
+
+  $ cat <file
+  >expected content
+
+You can also check the existence of a file with cat, the following will fail if
+the file doesn't exist::
+
+  $ cat file
+
+
+
 .. Effort tests
 .. ~~~~~~~~~~~~
 



More information about the bazaar-commits mailing list