Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

[Updated] How do you test code that uses Term::UI?

by dly (Beadle)
on Sep 02, 2012 at 05:51 UTC ( #991229=perlquestion: print w/replies, xml ) Need Help??
dly has asked for the wisdom of the Perl Monks concerning the following question:

I have some code that uses Term::UI, and now that I've coded it I'm struggling to figure out how to test it.

I've googled and searching perlmonks and stackexchage, but found nothing.

My options seem to be:

  1. Do what Term::UI does in its tests, and just rely on Term::UI's default option with $Term::UI::AUTOREPLY = 1 set. Which is lame and hacky, but relatively easy to set up and test.
  2. Use Expect, Expect::Simple, or Test::Expect to test my use of Test::UI, but those don't work on Windows except under Cygwin. And the interface seems to want to call an external command instead of just execute the function that I'm currently testing.
  3. Could I simply do it manually? Call Term::UI's get_reply() that waits for a reply..., but I can't do that, because Term::UI waits for a reply meaning Perl can't do anything else while its waiting for a reply. Would a crazy fork followed by a sleep() call to wait for Term::UI to be blocking for output, and then print a reply to Term::UI in the forked child followed by whatever <Enter> does (Ctrl-M perhaps?)and then exit. And after the child prints the answer followed by <Enter> the parent blocks waiting to collect the childs process id. Would something completely crazy like that actually work well?

Approach 1 seems lame, and hacky. And it doesn't seem to actually test anything, because nothing is printed and enter is never pressed, which might be ok for Term::UI, because it sits on top of Term::Readline, which presumably tests printing output and reading it in.

Approach 2 is not flexible enough, because in my test suite I'm importing functions, and then running them to test them. I'm not creating an actual perl script or binary to test using Expect, which seems to want an actual program to execute, which I don't have.

Approach 3 is just insane, but it might actually be crazy enough to work better than 1 (not really testing anything) or 2 (different paradigm: program to run instead of function to call).

What do you think? 1 or 3? Or any other ideas!


I decided to actually implement number 3, but I can't get it to work. I can't figure out how to print an <Enter> key properly. I've tried both print and syswrite and different combinations of "\n", "\r", "\cJ", and "\cM", and none of them work at all. The code is below.

#!/usr/bin/perl use strict; use warnings; use Term::UI; use Term::ReadLine; my $term = Term::ReadLine->new('test'); #binmode STDOUT; my $pid = fork(); if (not defined $pid) { die "fork failed!"; } elsif ($pid == 0) { #child sleep 2; # print "ftp://who.cares/what/my/\cJ"; my $output = "ftp://who.cares/what/my/\cJ"; syswrite STDOUT, "ftp://who.cares/what/my/\n", length($outpu +t); exit(0); } else { #parent my $lookup_url = $term->get_reply( prompt => q{What is your application's url?}, allow => qr!(ftp|http)://!, ); waitpid($pid,0); }
Sorry for no code. I need help figuring out what approach I should take more than help with any code I've already written. And that last crazy idea I came up with while writing this question here on perlmonks, so I haven't had time to actually code anything.

Replies are listed 'Best First'.
Re: How do you test code that uses Term::UI?
by Athanasius (Chancellor) on Sep 02, 2012 at 08:18 UTC

      No, I didn't see that thread. It didn't occur to me to search for stuff regarding Expect.

      IO::React looks really cool. I glanced at the code, and it's only a few hundred lines long, which is crazy, because it's an Expect replacement, and it's tiny compared to it. The only potential problem of using it is that it hasn't been updated in 11 years! But its tests still pass, but then you look at its tests, and its just one file called basic.t that only has like 18 tests in it, and basic.t manually prints 1..18 and ok and not ok implementing its TAP all on its own! That might not have been that crazy back in 2001.

      Using TCL would be a really crazy dependency, but could work.

      I think I'm leaning towards IO::React or Mocking it using default values and AutoReply = 1 like Term::UI does.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://991229]
Approved by Athanasius
Front-paged by kcott
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2018-02-22 19:12 GMT
Find Nodes?
    Voting Booth?
    When it is dark outside I am happiest to see ...

    Results (298 votes). Check out past polls.