Tutorial - Invores Quality Assurance Tester for VoiceXML
Introduction
IQAT can be run either from the command line or from the IqatPlan
graphical interface. The files in all the following examples are
distributed in the installation directory \Program
Files\Invores\Iqat\examples. If you do not have a web
server installed on your system, you can run the examples by using the file: URL scheme instead of http:.
For
example,
the
URL
of
the
example
menu.v1.vxml
in the default distribution directory would be file://c:/Program
Files/Invores/Iqat/examples/menu.v1.vxml .
Manifest - /Program
Files/Invores/Iqat/examples/
- fastfood.app.vxml - Fastfood application root document
- fastfood.vxml - Fastfood application
- intro.vxml - stub file for the Menu application
- lookup.vxml - stub file for the Menu application
- menu.v1.vxml - Menu application, version 1
- menu.v2.vxml - Menu application, version 2
- msgs.vxml - stub file for the Menu application
- multiple.app.vxml - Multiple results application root document
- multiple.vxml - Multiple results application
- news.vxml - stub file for the Menu application
- next.vxml - stub file for the Object application
- obj1.vxml - Object application
- rec1.app.vxml - Record application root document
- rec1.vxml - Record application
- start.vxml - stub file for several applications
- xfr1.vxml - Transfer application
- fastfood.plan.txt - Fastfood test plan
- menu.v1.txt - Menu test plan, version 1
- menu.v2.txt - Menu test plan, version 2
- menu1.txt - Menu test plan, single call
- multiple.plan.txt - Multiple results test plan
- multiple.plan1.txt - Multiple results test plan
- multiple.plan2.txt - Multiple results test plan
- obj1.txt - Object text plan
- rec1.txt - Record test plan
- xfr1.txt - Transfer test plan
For this tutorial, the examples were copied from the
distribution to a
directory configured in the web server as /docs/iqtest. Thus, the
base URL used in most instances is http://localhost:8010/docs/iqtest
.
A Simple Test Plan
Primary Testing
Consider the following VoiceXML application taken from http://www.w3c.org/Voice/Guide/.
<?xml version="1.0"?>
<vxml version="2.0">
<!-- version 1 -->
<menu id="choose">
<prompt>
Say one of: <enumerate/>
</prompt>
<choice next="start.vxml">
Sports
</choice>
<choice next="intro.vxml">
Weather
</choice>
<choice next="news.vxml">
News
</choice>
<noinput>Please say one of <enumerate/></noinput>
</menu>
</vxml>
This is a simple top-level menu selection which invokes the next
phase of the application through one of three URL's. Two things
are important for the creation of a test plan:
- <menu> is a dialog-scope element;
- each <choice> element is implemented as a separate grammar.
There are three choices and thus three dialog-scope grammars.
A test plan Voice
statement provides the expected response. It specifies the
utterance returned from the recognizer and the
corresponding grammar which recognized the utterance. This plan
is menu1.txt.
menu1.txt
call:{}
// this statement triggers the second dialog scope grammar
voice:{utterance:"weather",grammar:"dialog-2"}
The above Voice statement provides the utterance "weather", and
triggers
the
second dialog scope grammar.
When executed, an extract of the log output looks like:
dlog03:menu
('choose')
prmp02:queueing TTS (Say one of:
Sports
<break size="small"/>
Weather
<break size="small"/>
News
<break size="small"/>)
gram01:enable dialog grammar
gram01:enable dialog grammar
gram01:enable dialog grammar
voic01:timeout=7000ms completetimeout=-1ms incompletetimeout=-1ms
maxspeechtimeout=-1ms nbest=1 confidencelevel=0.500 sensitivity=0.500
speedvsaccuracy=0.500
vxml09:choice next intro.vxml
vxml03:goto intro.vxml
docu02:fetch URI http://localhost:8010/docs/iqtest/intro.vxml
The test plan selected the second menu choice, and control was
transferred to the document intro.vxml file.
Since we are just interested in
testing the logic of the VoiceXML application, the document intro.vxml
is a stub, a VoiceXML document that does nothing. With the three
stub files for the three choices, we can extend the test plan to test
all
the choices and the <noinput> element. Since
<noinput> just causes the menu to be reiterated, there is no need
to test it
more than once, so we provide valid input for the second attempt.
The test plan follows.
menu1.v1.txt
// version 1
call:{}
voice:{grammar:"dialog-1",utterance:"sports"}
call:{}
voice:{grammar:"dialog-2",utterance:"weather"}
call:{}
voice:{grammar:"dialog-3",utterance:"news"}
call:{}
voice:{throw:"noinput"}
voice:{grammar:"dialog-3",utterance:"news"}
The empty Call statements mark the boundaries of a new call.
In addition, a Call statement can provide properties for the session
object. However, in this case, the Call statements are empty
because the application is not sensitive to information on the
session object.
If the application used properties from the session object, they would
be set in the Call statement. When this test plan is executed,
the execution log for the final call, which includes the noinput event, looks like this:
dlog03:menu ('choose')
prmp02:queueing TTS (Say one of:
Sports
<break size="small"/>
Weather
<break size="small"/>
News
<break size="small"/>)
gram01:enable dialog grammar
gram01:enable dialog grammar
gram01:enable dialog grammar
voic01:timeout=7000ms completetimeout=-1ms incompletetimeout=-1ms
maxspeechtimeout=-1ms nbest=1 confidencelevel=0.500 sensitivity=0.500
speedvsaccuracy=0.500
vxml07:event: noinput
vxml03:prompt element
prmp02:queueing TTS
vxml03:prompt element
prmp02:queueing TTS
dlog03:menu ('choose')
gram01:enable dialog grammar
gram01:enable dialog grammar
gram01:enable dialog grammar
voic01:timeout=7000ms completetimeout=-1ms incompletetimeout=-1ms
maxspeechtimeout=-1ms nbest=1 confidencelevel=0.500 sensitivity=0.500
speedvsaccuracy=0.500
vxml09:choice next news.vxml
vxml03:goto news.vxml
docu02:fetch URI http://localhost:8010/docs/iqtest/news.vxml
dlog01:form $_internalName_31446 initialization
vxml02:block ($_internalName_31447)
call02:call returned no result
ivrt04:IVRT test plan completed
The stub file news.vxml
is fetched, it executes an empty <block>,
and
the
call
ends.
This
test
plan
is
version
1
(menu.v1.txt),
and
when
it
is
run,
for the purposes of the tutorial, the output should be
saved in
a (version 1) log file, in this case menu.v1.log.
This
log
will
be
used
when
the
application
is
modified
and
we
need
to
do
regression
testing.
Regression Testing
Now the application is modified to add a fourth choice, and to avoid
a noinput loop. The modified (version 2) application looks like
this.
<?xml version="1.0"?>
<vxml version="2.0">
<!-- version 2 -->
<menu id="choose">
<prompt>
Say one of: <enumerate/>
</prompt>
<choice next="start.vxml">
Sports
</choice>
<choice next="intro.vxml">
Weather
</choice>
<choice next="news.vxml">
News
</choice>
<choice next="msgs.vxml">
Messages
</choice>
<noinput>Please say one of
<enumerate/></noinput>
<noinput count="2">Please call back
later<exit/></noinput>
</menu>
</vxml>
For regression testing, we want to verify that version 2 of the
application did not break version 1 behavior. We run the version
1 test plan against the
version 2 application and compare the resulting log with the log for
the same test plan against the version 1 application. We keep
track of the various log files in a matrix that matches the test plans
against the versions of the application and lists the resulting log
file.
\ Test Plan
Application \
|
menu.v1.txt |
menu.v2.txt |
menu.v3.txt
|
| menu.v1.vxml |
menu.v1.log |
|
|
| menu.v2.vxml |
menu.v2R.log |
menu.v2.log |
|
menu.v3.vxml
|
|
menu.v3R.log
|
menu.v3.log
|
The regression comparison of the logs menu.v1.log
and menu.v2R.log
produces the following output.
16,17d
> Messages
> <break size="small"/>)
21d
> gram01:enable dialog grammar
40,41d
> Messages
> <break size="small"/>)
45d
> gram01:enable dialog grammar
64,65d
> Messages
> <break size="small"/>)
69d
> gram01:enable dialog grammar
88,89d
> Messages
> <break size="small"/>)
93d
> gram01:enable dialog grammar
105,106d
> Messages
> <break size="small"/>)
111d
> gram01:enable dialog grammar
The differences are expected. There is one additional choice
in version 2 of the application, so the prompt has an added option, and
the new choice generates an additional enable for the new choice
grammar. These differences are repeated for each call in the test
plan. Note that the messages docu01 and docu02 have been selected
for short compares. These messages name the files being executed
and thus will be different from one version of the log to the
next. A short compare compares only the presence of the message
and not its contents. This eliminates irrelevant comparison
differences and makes the regression log simpler to read. Note
also that the comparison skips the time stamp. The
regression test shows that the changes for version 2 of
the application did not break the application's version 1
behavior. Now the application can be tested with a version 2 test
plan to exercise the new features of version 2 and to establish a base
for version 3 regression, assuming that the application will continue
to be modified.
The new test plan for version 2 adds calls to test the new choice
and the additional noinput path.
// version 2
call:{}
voice:{grammar:"dialog-1", utterance:"sports"}
call:{}
voice:{grammar:"dialog-2", utterance:"weather"}
call:{}
voice:{grammar:"dialog-3",utterance:"news"}
call:{}
voice:{grammar:"dialog-4", utterance:"messages"}
call:{}
voice:{throw:"noinput"}
voice:{grammar:"dialog-3",utterance:"news"}
call:{}
voice:{throw:"noinput"}
voice:{throw:"noinput"}
When version 2 of the application is executed with version 2 of the
test plan, the execution log shows that the new choice was selected
appropriately and that two successive noinput events terminates a
call. Version 2 of the application has now been regression tested
and tested with an updated test plan which targets the new version 2
features.
A Test Plan With
Grammar Objects
The following VoiceXML document, fastfood.vxml, is a simple
non-directed dialog in
which the caller may provide several pieces of information in a single
response. The response is returned as an ECMAScript object from
the recognizer. Although the grammar is important to the
application, it is not relevant to the test plan. The plan simply
specifies the object that should result from the recognition, which is
what drives the logic of the application. The ECMAScript function
confirmPrompt(), is defined in the
application's root document, which is omitted for simplicity. It
is included in the IQAT distribution examples directory.
At the <initial> element, named
food, the dialog attempts to fill the slots entree,
side, and drink.
Each of these slots refers to a field with the
corresponding name. If the slot is filled, the field is
bypassed. Any slots that are not filled by the initial response
are then individually prompted and filled. The application calls an
ECMAScript function, confirmPrompt(), to
build a confirmation prompt
for the order, then calls a subdialog, place_order.cgi,
to
place
the
order,
and
get
back
an
order
number
and
the
time
to
fulfillment.
The
call
then
ends.
fastfood.vxml Page 2
<block name="cfmprmpt">
<var name="thisPrompt"
expr="confirmPrompt(entree, side, drink)"/>
<if cond="thisPrompt.length >
0">
<prompt><value
expr="thisPrompt"/> Is this correct?</prompt>
<else/>
<assign name="confirm"
expr="true"/>
<assign name="order"
expr="true"/>
</if>
</block>
<field name="confirm" type="boolean">
<help>Please answer yes or
no.</help>
<filled>
<if cond="confirm ==
'false'">
<clear/>
</if>
</filled>
</field>
<subdialog src="place_order.cgi" name="order">
<param name="entree"
expr="entree"/>
<param name="side" expr="side"/>
<param name="drink" expr="drink"/>
<filled>
<prompt>
Your order
number is <value expr="order.ordnum"/>.
It will be ready
in <value expr="order.ordtim"/> minutes.
</prompt>
</filled>
</subdialog>
<block name="finish">
<prompt>
Thank you. Good bye.
</prompt>
<disconnect/>
</block>
<catch event="nomatch">
<prompt>
I did not understand you. Try
again or say help.
</prompt>
<reprompt/>
</catch>
<catch event="nomatch" count="3">
<prompt>
I can not understand you. Try
again later.
</prompt>
<disconnect/>
</catch>
<catch event="noinput">
<throw event="help"/>
</catch>
<catch event="noinput" count="2">
<prompt>
I did not hear any response. Try
again later. Good bye.
</prompt>
<disconnect/>
</catch>
<catch event="error subdialog">
<if cond="reenter">
<exit/>
</if>
<assign name="reenter" expr="true"/>
<prompt>
Sorry, your order cannot be filled.
Code <value expr="_event"/>.
</prompt>
<exit/>
</catch>
</form>
<catch event="connection.disconnect">
<exit/>
</catch>
</vxml>
fastfood.vxml Page 1
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" application="fastfood.app.vxml">
<var name="reenter" expr="false"/>
<form id="root">
<property name="confidencelevel" value=".8"/>
<property name="inputmodes" value="voice"/>
<var name="sctr" expr="0"/>
<var name="ectr" expr="0"/>
<var name="dctr" expr="0"/>
<block name="welcome">Welcome to Burger
Hut.</block>
<grammar type="application/srgs+xml"
src="FF2.grxml" version="1.0"/>
<initial name="food">
<prompt>What would you like to
order?</prompt>
<help>
Menu choices are hamburgers,
cheeseburgers, pizzas, drinks,
fries and onion rings.
<reprompt/>
</help>
</initial>
<field name="entree">
<grammar type="application/srgs+xml"
src="FFe.grxml"/>
<prompt>Would you like an
entree?</prompt>
<filled>
<if cond="entree == 'yes'
&& ectr < 3">
<assign
name="ectr" expr="ectr + 1"/>
<assign
name="entree" expr="undefined"/>
<prompt>
Entrees are hamburgers, cheeseburgers, and pizzas.
What
would you like?
</prompt>
<elseif cond="entree ==
'no'"/>
<assign
name="entree" expr="''"/>
</if>
</filled>
<help>
Entrees are hamburgers,
cheeseburgers, and pizzas.
<reprompt/>
</help>
</field>
<field name="side" cond="entree == 'hamburger' ||
entree == 'cheeseburger'">
<grammar type="application/srgs+xml"
src="FFs.grxml"/>
<prompt>Would you like a side
order?</prompt>
<help>
Side orders are french fries
or onion rings.
<reprompt/>
</help>
<filled>
<if cond="side == 'yes'
&& sctr < 3">
<assign
name="sctr" expr="sctr + 1"/>
<assign
name="side" expr="undefined"/>
<prompt>
Side
orders are french fries or onion rings.
</prompt>
<elseif cond="side ==
'no'"/>
<assign
name="side" expr="''"/>
</if>
</filled>
</field>
<field name="drink">
<grammar type="application/srgs+xml"
src="FFd.grxml"/>
<prompt>Would you like a
drink?</prompt>
<help>
Drinks are coke, seven up,
sprite, coffee, tea, or iced tea.
<reprompt/>
</help>
<filled>
<if cond="drink == 'yes'
&& dctr < 3">
<assign
name="dctr" expr="dctr + 1"/>
<assign
name="drink" expr="undefined"/>
<prompt>
Drinks are coke, seven up, sprite, coffee, tea, or iced tea.
</prompt>
<elseif cond="drink ==
'no'"/>
<assign
name="drink" expr="''"/>
</if>
</filled>
</field>
When the dialog attempts to fill the slots entree,
side, and drink, the
recognizer
can return
an
object
which
may
have
any
of
these properties set. The test plan begins by returning the
slots
entree and drink,
which we assume the grammar extracted from the
specified utterance. The slots are top level properties in the interpretation property of the first Voice
statement in the plan.
This is what the recognizer is expected to respond when it hears the
corresponding utterance. In IQAT, the interpretation property of
a Voice statement is displayed with a background green tint. This
is a reminder that the content of the field is JavaScript object
literal notation, and as such must be syntactically correct.
call:{}
// fastfood.vxml IQAT test plan
// prompt what would you like to order?
voice:{utterance:"I'd like a hamburger and a coke", confidence:0.80,
grammar:"dialog-1", interpretation:{drink:"coke", entree:"hamburger"}}
// the side slot is missing, so we should prompt for that slot
// prompt would you like a side order?
voice:{utterance:"no", confidence:0.90}
// prompt you ordered ... is this correct?
voice:{utterance:"yes", confidence:0.90}
//prompt your order number is ... it will be ready in ... minutes.
The response satisfies the <initial>
element and fills the fields with the corresponding slot names.
The form interpretation algorithm will then select the field side as the next field to be filled. The
prompt expected is indicated in the plan comment, and the plan response
is another voice statement with the utterance "no". This fills
the field side and selects in order the
<block>
cfmprmpt, the <field> confirm, the
<subdialog>
order, and the <block> finish. When this plan is run using
the
IqatPlan Verify Tab, the following log is produced. Some detail
has been suppressed in the interest of space. The output has been
annotated in the right-hand column to explain the log output.
Execution Notes
the name of the input test plan
the URL of the VoiceXML document being tested
load the VoiceXML document
load the root document
the root document's ECMAScript definitions
fastfood.vxml document scope variables
initialze form ID root
dialog scope variables
welcome block
initial element
default properties for the initial voice request
filled element for the filled field entree
filled element for the filled field drink
field side was not filled, so it is now selected by the FIA
filled element for field side
block cfmprmpt calls an ECMAScript function to get a confirm
prompt
the confirm prompt
field confirm solicits a response to the confirm prompt
filled element for field confiorm
subdialog order places the order with host logic
the document response to the subdialog request
the dialog scope variables
an unnamed block
the subdialog document returns
the filled element for subdialog order
execute the block finish
the goodbye prompt from block finish
the block executes a disconnect
the disconnect event is thrown
the catch element handling the disconnect event is executed
the application ends
the test plan is complete
fastfood.vxml Execution Log with fastfood.plan1.txt
iqat00:Invores Quality Assurance Tester for VoiceXML (copyright (c)
2009 Invores Systems)
iqat01:IQAT (1.0) executing test plan
C:\invores\docs\iqtest\fastfood.plan1.txt
docu02:initial VoiceXML document
'http://localhost:8010/docs/iqtest/fastfood.vxml'
...
docu02:fetch URI http://localhost:8010/docs/iqtest/fastfood.vxml
docu02:fetch URI http://localhost:8010/docs/iqtest/fastfood.app.vxml
vxml03:script inline
vxml01:var (reenter=false)
...
dlog01:form root initialization
vxml01:var (sctr=0)
vxml01:var (ectr=0)
vxml01:var (dctr=0)
vxml02:block (welcome)
vxml03:prompt element
prmp02:queueing TTS (Welcome to Burger Hut.)
vxml02:initial (food)
prmp02:queueing TTS (What would you like to order?)
gram01:enable dialog grammar
voic01:timeout=7000ms completetimeout=-1ms incompletetimeout=-1ms
maxspeechtimeout=-1ms nbest=1 confidencelevel=0.800 sensitivity=0.500
speedvsaccuracy=0.500
vxml03:if (entree == 'yes' && ectr < 3)
vxml03:elseif (entree == 'no')
vxml03:if (drink == 'yes' && dctr < 3)
vxml03:elseif (drink == 'no')
vxml02:field (side)
prmp02:queueing TTS (Would you like a side order?)
...
vxml03:if (side == 'yes' && sctr < 3)
vxml03:elseif (side == 'no')
vxml03:assign (side = '')
vxml02:block (cfmprmpt)
vxml01:var (thisPrompt=confirmPrompt(entree, side, drink))
vxml03:if (thisPrompt.length > 0)
vxml03:prompt element
prmp02:queueing TTS (You ordered a hamburger and coke. Is
this correct?)
vxml02:field (confirm)
...
vxml03:if (confirm == 'false')
vxml02:subdialog (order)
docu02:fetch URI http://localhost:8010/docs/iqtest/place_order.cgi
dlog01:form order_time initialization
vxml01:var (entree)
vxml01:var (side)
vxml01:var (drink)
vxml02:block ($_internalName_31423)
vxml01:var (ordnum=17)
vxml01:var (ordtim=10)
vxml03:return element
vxml03:prompt element
prmp02:queueing TTS (Your order number is 17 .
It will be ready
in 10 minutes.)
vxml02:block (finish)
vxml03:prompt element
prmp02:queueing TTS (Thank you. Good bye.)
vxml03:disconnect element
vxml07:event: connection.disconnect.hangup
vxml03:exit element
call02:call returned no result
iqat04:IQAT test plan completed
With any combination of three slots returned, it will take eight calls
to test the go-right logic for the application.The help elements should
be added to the test plan, which will increase number of calls A
full test plan for the application is included in the IQAT distribution.
Multiple Results
The following application uses multiple results from the recognizer
to increase the possibility of getting a correct recognition on the
first try. Of course, with multiple results, some additional
information must be taken into account in order for the application to
try to correctly
select among the recognizer's responses. In this application, the
request is for an account number, and the number has a check
digit. The first result which matches the check digit is
selected. A recognizer always presents multiple results ordered
from highest to lowest confidence, and so the test plan is designed to
return them in
the same way. The application's VoiceXML follows, along with
annotations in the right-hand column. The check digit
verification is in the application's root document.
Application notes
set the maxnbest property greater than 1
the grammar specifies numeric recognition with multiple results
try voice recognition first
the selectResult() function is defined in the root document; it
loops through the passed lastresult$ array looking for a result that
passes the check digit test
a good result was found, so set the next field to be bypassed
first time no match
second time nomatch
fill this form item variable to trigger the next field
execute only if acctv was set to 0
DTMF input
verify that the check digit is correct
DTMF first time nomatch
DTMF second time nomatch
disconnect after two no-matches
block executed if a correct account number has been entered
the next VoiceXML document in the application
dialog scope first time noinput
dialog scope second time noinput
error handler
avoid recursion
disconnect handler
multiple.vxml
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.0" application="multiple.app.vxml">
<var name="reenter" expr="false"/>
<form id="root">
<property name="maxnbest" value="5"/>
<property name="confidencelevel" value=".5"/>
<var name="account" expr="null"/>
<grammar type="application/srgs+xml"
src="mr1.grxml" version="1.0"/>
<field name="acctv">
<property name="inputmodes"
value="voice"/>
<prompt>Please say your account
number.</prompt>
<filled>
<assign name="account"
expr="selectResult(application.lastresult$)"/>
<if
cond="!account.found">
<assign
name="acctv" expr="undefined"/>
<throw
event="nomatch"/>
</if>
<assign name="acctd"
expr="0"/>
</filled>
<nomatch>
I did not understand what
you said.
Please say your account
number once more.
</nomatch>
<nomatch count="2">
Let's try your phone's
keypad.
<assign name="acctv"
expr="0"/>
</nomatch>
</field>
<field name="acctd" type="digits?length=5"
cond="acctv == 0">
<property name="inputmodes"
value="dtmf"/>
<prompt>Please enter your account
number.</prompt>
<filled>
<if
cond="!verifyCheck(acctd)">
<throw
event="nomatch"/>
</if>
</filled>
<nomatch>
I did not understand what
you said.
Please enter your account
number once more.
</nomatch>
<nomatch count="2">
I am unable to get your
account number. PLease call back later.
<disconnect/>
</nomatch>
</field>
<block name="finish">
<assign name="customer.account"
expr="(acctv != 0) ? acctv : acctd"/>
<goto next="lookup.vxml"/>
</block>
<catch event="noinput">
<prompt>I did not hear any
response.</prompt>
<reprompt/>
</catch>
<catch event="noinput" count="2">
<prompt>
I did not hear any response. Try
again later. Good bye.
</prompt>
<disconnect/>
</catch>
<catch event="error">
<if cond="reenter">
<exit/>
</if>
<assign name="reenter" expr="true"/>
<prompt>
Sorry, error <value
expr="_event"/> has occurred. Good bye.
</prompt>
<exit/>
</catch>
</form>
<catch event="connection.disconnect">
<exit/>
</catch>
</vxml>
The first call in the following test plan returns two results for
the first attempt,
both of
which will fail the check digit test. On the second attempt at
voice input, the plan returns three results, and the third result will
pass the check digit test, which is a simple mod 10 test. The
second call fails both attempts, and the application falls back on DTMF
entry. The plan then provides a DTMF sequence which has a correct
check digit.
Test Plan notes
first input response
result1 sets application.lastresult$[0].interpretation to '21349'
note that the results should be ordered by confidence
result2 sets application.lastresult$[1].interpretation to '21345'
second attempt at input provides three results
this result satisfies the check digit test
the second test call
both results fail the check digit test
a second attempt at voice input also fails the check digit test
the application requests DTMF input; the plan provide correct input
// multiple.plan.txt
call:{}
voice:{
result1{confidence:0.85,inputmode:'voice',interpretation:'21349',
utterance:'two one three four nine'},
result2:{confidence:0.80,inputmode:'voice',interpretation:'21345',
utterance:'two one three four five'}}
voice:{
result1:{confidence:0.85,inputmode:'voice',interpretation:'21349',
utterance:'two one three four nine'},
result2:{confidence:0.80,inputmode:'voice',interpretation:'21345',
utterance:'two one three four five'},
result3:{confidence:0.70,inputmode:'voice',interpretation:'26345',
utterance:'two six three four five'}}
call:{}
voice:{
result1:{confidence:0.85,inputmode:'voice',interpretation:'21349',
utterance:'two zero three four nine'},
result2:{confidence:0.80,inputmode:'voice',interpretation:'21345',
utterance:'two zero three four five'}}
voice:{
result1:{confidence:0.85,inputmode:'voice',interpretation:'21349',
utterance:'two zero three four nine'},
result2:{confidence:0.80,inputmode:'voice',interpretation:'21345',
utterance:'two zero three four five'}}
dtmf:{utterance:"26345"}
Recording
When an application needs to make a recording, the test plan
provides several different options. If the content of the recording is
irrelevant, a specification of the recording duration is all that is
needed in the Record test plan statement. IQAT will generate
sound for the requested length, at 8000 samples per second, and return
it as the value of the recording. If the type attribute is audio/x-wav,
a .wav header will be added to the generated sound. Any other
type will be treated as audio/basic for the purposes of the test.
If the content of the recording is important, IQAT can read a
previously recorded file and return its content to the <record>
element. This is specified with the file
property of the Record
test plan statement.
Test Plan
//record test - make a recording, then confirm with a 1
call:{}
// a minmal Record test plan statement specifies the generation
// of 10 seconds of sound to provide input for the <record>
element
record:{duration:10}
// a DTMF test plan statement provides the 1 which the application
// requests for confirmation after playing the recording
dtmf:{utterance:"1"}
rec1.vxml
<?xml version="1.0"?>
<vxml application="rec1_app.vxml" version="2.0">
<form id="frmRecord">
<var name="reenter" expr="false"/>
<var name="errmsg" expr="''"/>
<var name="atts" expr="0"/>
<var name="sessid" expr="callid"/>
<var name="logpfx" expr="appname + '.' + appid +
'.frmRecord'"/>
<record name="recording" type="audio/x-wav"
finalsilence="3s" maxtime="100s"
dtmfterm="true" beep="true">
<prompt count="1">
<audio
expr="'recPrompt1.wav'">
Please record
your message after the tone,
</audio>
</prompt>
<prompt count="2">
<audio
expr="'recPrompt2.wav'">
Please record
your message after the tone,
</audio>
</prompt>
<filled>
<assign name="lastrec"
expr="recording"/>
<if cond="confirm ==
false">
<goto
expr="recordNextSucceed"/>
</if>
</filled>
<catch event="nomatch noinput"
count="2">
<assign name="errmsg"
expr="'noinput/nomatch limit'"/>
<throw
event="apperr.record.fail"/>
</catch>
</record>
<field name="conf" cond="confirm">
<dtmf>1 | 2</dtmf>
<prompt>
<audio
expr="'IHeard.wav'">
I heard
</audio>
<value
expr="recording"/>
<audio
expr="'IfCorrect.wav'">
If this is
correct, press 1. To try again, press 2.
</audio>
</prompt>
<filled>
<if cond="conf != '1'">
<assign
name="atts" expr="atts + 1"/>
<if
cond="atts >= maxatts">
<assign name="errmsg" expr="'noinput/nomatch limit'"/>
<throw event="apperr.record.fail"/>
<else/>
<clear namelist="recording conf"/>
<reprompt/>
</if>
<else/>
<goto
next="start.vxml"/>
</if>
</filled>
<catch event="error">
<assign name="errmsg"
expr="'confirm'"/>
<throw
event="apperr.record.fail"/>
</catch>
</field>
<catch event="apperr.record">
<var name="msg" expr="''"/>
<if cond="typeof _message !=
'undefined'">
<assign name="msg"
expr="' message:' + _message"/>
</if>
<log><value expr="logpfx"/>
call:<value expr="sessid"/> <value expr="errmsg"/>
event:<value expr="_event"/><value expr="msg"/></log>
<exit/>
</catch>
<catch event="error">
<if cond="reenter">
<log>error recursion
<value expr="_event"/></log><exit/>
</if>
<assign name="reenter"
expr="true"/>
<assign name="errmsg"
expr="'unexpected'"/>
<throw event="apperr.record.fail"/>
</catch>
</form>
</vxml>
Transfer
The Transfer test plan statement provides response for a
<transfer> element. The example document xfr1.vxml
shows a simple blind transfer. Note that although the VoiceXML
specification says that a blind transfer always throws a connection.disconnect.transfer event, the Transfer
statement does not make that assumption. The example xfr1.txt test plan shows the transfer statement
with the explicit disconnect outcome. This is done because
<transfer> is often extended by a VoiceXML platform, and IQAT
tries to support as many platform variations as possible.
Object
Since the <object> element is by definition, platform
dependent, IQAT performs only minimal processing with it. In
order to verify the object when it is selected by the Form
Interpretation Algorithm, the Object test plan statement has a required
property, classid. This should match
the value of the classid attribute of the <object> element.
The other property of the Object statement is result. This is an
ECMAScript object with an arbitrary set of properties. This
becomes the value of the <object> element's form item
variable. The following test plan is used to test the document obj1.vxml.
obj1.txt
// test plan for the document obj1.vxml
call:{}
// object element example
// verify the object's classid, return an object with a status property
object:{classid:"com.invores.vxml.outdial",result:{status:'busy'}}
// this iteration return a connect status
object:{classid:"com.invores.vxml.outdial",result:{status:'connect'}}
Comments
A test plan can be annotated with comments using Javascript // or /*
...
*/ comment conventions. IQATPlan is line-oriented and restricts
comments to their own lines. Single line comments are preceded by
// and multi-line comments are bounded by /* ... */ . A checkbox
in the Comment tab determines the type of the comment. A test
plan created outside of IQATPlan, for example with a text editor, can
have comments on the same line as plan statements. However, if
such a plan is loaded into IQATPlan, the same-line comments will be
omitted, and will not be saved if the plan is updated within IQATPlan.