The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Lembas -- Testing framework for command line applications inspired by Cram

SYNOPSIS

  use Test::More;
  use Lembas;
  
  open my $specs, '<', 'hg-for-dummies.lembas'
      or BAILOUT("can't open Mercurial session test specs: $!");
  
  my $lembas = Lembas->new_from_test_spec(handle => $specs);
  plan tests => $lembas->plan_size;
  $lembas->run;

DESCRIPTION

WHAT IS LEMBAS

It's better than cram :)

In short, you write down shell sessions verbatim, allowing for variance such as "this part here should match this regex" or "then there's some output nobody really cares about" or even "this output should be printed within N seconds". The markup is really very simple so you can almost copy-paste real shell sessions and have it work.

Then Lembas will spawn a shell process of your choice and pass it the commands and test if the output matches what's expected, thereby turning your shell session into a test suite!

You can get the number of tests run for a suite through your Lembas object, so you can plan your tests as usual (or just let done_testing handle it). A design point is that the number of tests should be constant for a given script, no matter how many lines fail to match.

An automatic, free test tells you if you had any extra unmatched output after your last matched line for each command. This is not entirely reliable though and may produce false positives. Tuits and patches welcome.

I DON'T GET IT, GIVE ME A REAL USE-CASE

This is a simple script suitable to test the very first chapter of your Mercurial Course for Dummkopfs. Whitespace is important.

  #!/bin/bash
  
  # Do all the work in /tmp
      $ cd /tmp
      $ pwd
      /tmp
  
  # Testing presence of Mercurial
      $ hg --version
  re: Mercurial Distributed SCM \(version [\d.]+\)
      (see http://mercurial.selenic.com for more information)
      
  re: Copyright \(C\) [\d-]+ Matt Mackall and others
      This is free software; see the source for copying conditions. There is NO
      warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  
  # Creating a repository
      $ mkdir foo
      $ cd foo
      $ pwd
      /tmp/foo
      $ hg init
      $ echo "this is a file" > content
      $ cat content
      this is a file
      $ hg add content
      $ hg st
      A content
      $ hg commit -m "created repo and added a file"
  
  # Checking that everything looks good
      $ hg log
  re: changeset:   0:[a-f0-9]{12}
      tag:         tip
      user:        Fabrice Gabolde <fabrice.gabolde@gmail.com>
  re: date:        .*
      summary:     created repo and added a file
      
  
  # Cleanup
      $ rm -Rf /tmp/foo

Lines with content in the first four characters are assumed to be Lembas commands (or comments). The rest are shell commands (if they start with "$ ") or shell output (otherwise). The syntax for "this line of output should be matched as a regex" is problematic; Cram puts " re" at the end of a line but it seems ugly to me.

The shebang-looking line at the top is almost exactly that. It's a user-friendly way of specifying "run this command with these arguments".

You'll notice that this works with or without the color extension for Mercurial; Lembas removes ANSI terminal escape characters before matching output.

The manual describes the syntax and lists the available commands.

METHODS

new

  my $lembas = Lembas->new(shell => [ '/bin/bash' ],
                           commands => [ { shell => 'whoami',
                                           outputs => [ 'fgabolde' ] } ]);

Creates a new Lembas object with the corresponding settings and expected outputs.

new_from_test_spec

  my $lembas = Lembas->new_from_test_spec(shell => [ '/bin/bash' ],
                                          handle => $iohandle);

Same as new, but parses a spec file first and uses it to set the command/outputs list. The shell parameter is optional if you have a shebang in the spec file, but still useful in case you want to force a different program.

plan_size

  plan tests => $lembas->plan_size + $the_rest;

If you dislike done_testing, you can use this method to obtain the number of tests that will be run by this Lembas instance. CAVEAT: it will only return a meaningful value if the Lembas instance was created with new_from_test_spec.

run

  $lembas->run;

Uses Test::Builder to run all the tests specified, reporting success, failure and diagnostics in the usual manner.

SEE ALSO

Test::Builder

The original inspiration for Lembas: Cram

If you're looking for something more complex and low-level, you probably want Expect.pm instead.

AUTHOR

Fabrice Gabolde <fabrice.gabolde@gmail.com>

COPYRIGHT AND LICENSE

Copyright (C) 2013 Fabrice Gabolde

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available.