Test::AskAnExpert - Automatically test things that require Human Intelligence (by asking someone).
use Test::AskAnExpert import => [qw(is_yes is_no ask answer)],tests => 7;
Start up the Human Interface:
Synchronously submit and wait for a yes or a no answer:
is_yes("Can you read this captcha?"); is_no("Is this a quality CPAN distribution?");
Same, but with timeouts: (In seconds)
is_yes("Can you read this captcha very fast?",10); is_no("Is the skew-t log-p diagram located at /images/charts/stlp.png correct for the 12Z GFS data?",10);
Submit an asynchronous question:
# Not a good example question because its not yes/no, but answering will take about 70000 years $question_object = ask("What is the meaning of life, the universe, and everything?");
Check the answer:
Checking the answer also accepts a timeout parameter:
Test::AskAnExpert aims to fill a hole in the current set of testing tools by integrating an automated method for asking testing questions that computers cannot easily answer like: "Is this meteorologically sound?" or "Does this output fit into category x?" or "Is this distrobution quality?" and still allow standard test tools to work properly in terms of generating reports, locking the doors if the tests aren't passing, etc. etc.
Test::AskAnExpert is built on Test::Builder and will play nice with Test::Simple, Test::More, and anything they play nice with. To provide correct answers to conceptual questions we cheat by asking people instead of actually solving a Very Hard Problem regarding machine intelligence. This requires a little more overhead as we need to set up a way to talk to people, and provide them some (but not too much) time to tender an answer.
The initialize function must be called before using any of Test::AskAnExpert's functions to load a Human Interface, otherwise the default (skip all tests) will load. To specify something other than the default pass a subclass of Test::AskAnExpert::Interface. @interface_params are any Interface specific parameters, consult the documentation of the Interface you're using for what (if anything) to pass here.
On error it returns false, allowing you to try to load multipule Interfaces in a short-circuit style before giving up:
Test::AskAnExpert->initialize("Test::AskAnExpert::Interface::Custom::InHouse::System") or Test::AskAnExpert->initialize("Test::AskAnExpert::CGI") or skip_all("No good interfaces available");
Note that skip_all isn't required, if no Interface is specified Test::AskAnExpert will use a default Interface that simply skips if its asked to test anything.
Test::AskAnExpert provides two methods for the programmers who don't want to muck with asynchronous interaction, is_yes and is_no. is_yes passes when the question asked is answered yes, is_no the opposite. They are slim wrappers arround ask and answer, taking a plain text question, test name, and optionally a timeout in the same way.
NOTE: This does not actually run any tests!
ask is a very self explanatory function: it sends a question to be answered by whatever is on the other side of the Interface (Test::AskAnExpert::Pass anyone?). It returns a Test::AskAnExpert::Question object which is later used for retrieving the answer. Since this is the factory for Test::AskAnExpert::Question objects it also optionally takes the test name the question is bound to, though this can be changed with the
name method. If there was an error in asking the question the object will have its skip parameters set so when
answer is called on it the test will be skipped. Read the Test::AskAnExpert::Question documentation if you'd like to query the object your self and do something other than skip the test (like re-initialize to a different Interface and ask again, or BAIL_OUT).
$QuestionText should be plaintext with no markup, the Interface is expected to format it nicely for the human on the other side (e.g. if its an HTML interface give them nice links) to make their life a little easier.
answer takes a previously asked question and waits until an answer is ready or optionally $Timeout seconds have passed and then executes typical test magic.
$QuestionObj should be a Test::AskAnExpert::Question object returned by ask or correctly constructed otherwise. $Expected can be any capitalization of yes or no and will be checked against the answer in the question for the test.
Nothing is exported by default, you must ask for whatever you want by passing import => [qw(functions you want)] as arguments to use like this
use Test::AskAnExpert import => [qw(is_yes)]; #we just deal with yes-men
This is very young code, it probably has some. Bug reports, failing tests, and patches are all welcome.
Test::AskAnExpert::Interface::CGI and Test::AskAnExpert::Interface::DBI. These would probably be more useful than the current File interface which exists more to prove it can be done than anything. Maybe also a Test::AskAnExpert::Interface::Terminal if the person running the tests is the expert.
Set up a way to make sure an expert is indeed being asked. This is a hard one since it would require the test-writer (who may also not be qualified) to write some sort of captcha. This might get on an indefinite hold, you have to start trusting people at some point (hey, they let us write software... ).
All bugs should be filed via the CPAN bug tracker at
For other issues, or commercial enhancement or support, contact the author.
Edgar A. Bering, <email@example.com>
Copyright (C) 2007 by Edgar A. Bering
This library is free software; you can redistribute it and/or modify it under the terms of the Artistic 2.0 liscence as provided in the LICENSE file of this distribution.