MARTY KUBE BEAVER CREEK CONSULTING CORP NOVA TEST AUTOMATION INTEREST GROUP 2009-04-08 Scripting...
-
Upload
ann-rosa-hunter -
Category
Documents
-
view
213 -
download
0
Transcript of MARTY KUBE BEAVER CREEK CONSULTING CORP NOVA TEST AUTOMATION INTEREST GROUP 2009-04-08 Scripting...
MARTY KUBEBEAVER CREEK CONSULTING CORP
NOVA TEST AUTOMATION INTEREST GROUP2009-04-08
Scripting Approaches For Java Application Test
Automation
http://beavercreekconsulting.com/http://www.novataig.net/
Scripting and Test Automation
Scripting is the way to go for test automation “High Level” languages - More functionality with less
code
How scripting interacts with the application External interfaces
Win runner JMeter
Expose Internals JavaScript in the Browser SQL
Survey a Few DSL Approaches
Small example applicationUse scripting and Domain Specific Language
to drive application Groovy JavaScript JavaCC
Hands on with code examples
Contrasting the DSL approaches
Focus on Strategy – Using Java as an example – similar tactics should apply for other environments.
Three types of resources Expertise for set-up, Integration effort, Expertise for
test authoringTrade offs:
General Trade offs Less front end setup More complex test authoring
More front end setup Less complex test authoring
Scripting Languages
Type-less or easy to use type systemHigh Level – more productive and less
defectsInterpretedInteractive shell for rapid exploration or
development Text processing - AWK, SED General Purpose - Perl, Python, TCL, Emacs LISP
http://en.wikipedia.org/wiki/Scripting
Domain Specific Languages (DSL)
Smaller language dedicated to a particular situation SQL Second Life/MORPHS Spotted in the wild
Less generalLack low level functionalityMore expressive in the particular domain
Really blurry line between scripting language and DSL
http://en.wikipedia.org/wiki/Domain_specific_language
Example Application
class nov ataig
«enumeration»Account
CHECKING TRAVEL_AND_ENTERTAINMENT SLUSH_FUND
«enumeratio...Ind
DEBIT CREDIT
JournalEntry
~ account: Account {readOnly}~ amount: Double {readOnly}~ ind: Ind {readOnly}
+ JournalEntry(Account, Ind, Double)
Ledger
~ balances: Map<Account, Double> = new HashMap<Acc...
+ getBalance(Account) : Double+ post(JournalEntry) : void+ setBalance(Account, Double) : void
~ind ~account
The Java Code
package com.beavercreekconsulting.novataig;public class TestLedger {
public static void main(String[] args) {
Ledger subLedger = new Ledger();
// Open the periodsubLedger.setBalance(Account.CHECKING, 1000.00);subLedger.setBalance(Account.TRAVEL_AND_ENTERTAINMENT, 200.00);subLedger.setBalance(Account.SLUSH_FUND, -500.00);
// Post activityJournalEntry [] activity = {
new JournalEntry(Account.CHECKING, Ind.CREDIT, 100.00),new JournalEntry(Account.TRAVEL_AND_ENTERTAINMENT, Ind.DEBIT, 100.00),
new JournalEntry(Account.CHECKING, Ind.CREDIT, 2000.00),new JournalEntry(Account.SLUSH_FUND, Ind.DEBIT, 2000.00)};
for(int i = 0; i < activity.length; i++) subLedger.post(activity[i]);
// Check ending balancesif (subLedger.getBalance(Account.CHECKING) != -1100.00) throw new TestFailure();if (subLedger.getBalance(Account.TRAVEL_AND_ENTERTAINMENT) != 300.00) throw new TestFailure();if (subLedger.getBalance(Account.SLUSH_FUND) != 1500.00) throw new TestFailure();
System.out.println("Happy Day!");}
}
The Groovy Code
package com.beavercreekconsulting.novataig;public class TestLedger {
public static void main(String[] args) {
Ledger subLedger = new Ledger();
// Open the periodsubLedger.setBalance(Account.CHECKING, 1000.00);subLedger.setBalance(Account.TRAVEL_AND_ENTERTAINMENT, 200.00);subLedger.setBalance(Account.SLUSH_FUND, -500.00);
// Post activityJournalEntry [] activity = [
new JournalEntry(Account.CHECKING, Ind.CREDIT, 100.00),new JournalEntry(Account.TRAVEL_AND_ENTERTAINMENT, Ind.DEBIT, 100.00),
new JournalEntry(Account.CHECKING, Ind.CREDIT, 2000.00),new JournalEntry(Account.SLUSH_FUND, Ind.DEBIT, 2000.00)];
for(int i = 0; i < activity.length; i++) subLedger.post(activity[i]);
// Check ending balancesif (subLedger.getBalance(Account.CHECKING) != -1100.00) throw new TestFailure();if (subLedger.getBalance(Account.TRAVEL_AND_ENTERTAINMENT) != 300.00) throw new TestFailure();if (subLedger.getBalance(Account.SLUSH_FUND) != 1500.00) throw new TestFailure();
System.out.println("Happy Day!");}
}
Groovy Up Close
Super set of JavaPlus
Dynamic typing Enhanced API Java Classes String interpolation
def x = “Bob”; print “Hello ${x}”; Closures
square = {it * it} [1..9].collect(square);
XML builders and groovy SQL Script MS Office with COM Bridge (Scriptom)
http://groovy.codehaus.org/Tutorial+2+-+Code+as+data,+or+closures
Groovy Architecture – What’s in the JVM
>groovy.bat -classpath bin TestLedger.groovy
cmp Groov y
JVM
Ledger Byte Code
Interactive Shell
groovyc
Test Groovy
Files
Ledger Java
SourceJavac
Test Byte Code
«flow»
«flow»
«flow»
«flow»«flow»
«flow»
Really Groovy Code
import com.beavercreekconsulting.novataig.*;
def subLedger = new Ledger();
[ [Account.CHECKING, 1000.00], [Account.TRAVEL_AND_ENTERTAINMENT, 200.00], [Account.SLUSH_FUND, -500.00] ].each() {subLedger.setBalance(it[0], it[1]);}
[ new JournalEntry(Account.CHECKING, Ind.CREDIT, 100.00),new JournalEntry(Account.TRAVEL_AND_ENTERTAINMENT, Ind.DEBIT, 100.00),new JournalEntry(Account.CHECKING, Ind.CREDIT, 2000.00),new JournalEntry(Account.SLUSH_FUND, Ind.DEBIT, 2000.00)
].each() {je -> subLedger.post(je);}
[ [Account.CHECKING, -1100.00],[Account.TRAVEL_AND_ENTERTAINMENT, 300.00],[Account.SLUSH_FUND, 1500.00]
].each() { expected ->if(subLedger.getBalance(expected[0]) != expected[1]) throw new TestFailure();
}println "Happy Day!"
JavaScript
JavaScript is a small language – ECMA ScriptEasy to integrateEasy to find JavaScript Fan boysRhino is a JavaScript interpreter written in
JavaOther JavaScript Engines, Mozilla, V8
http://en.wikipedia.org/wiki/Javascripthttp://www.mozilla.org/rhino/
Rhino Architecture
>java -classpath lib\js.jar;bin org.mozilla.javascript.tools.shell.Main
-f TestLedger.js
cmp Rhino
JVM
Rhino
Ledger
Interactive Shell
Test - JavaScript
Files
Command Line
«LiveConnect»
«flow» «flow»
The JavaScript Code
importPackage(com.beavercreekconsulting.novataig)
function assertEquals(a, b) {if(a != b) throw new TestFailure()
}
var subLedger = new Ledger()
subLedger.setBalance(Account.CHECKING, 1000.00)subLedger.setBalance(Account.TRAVEL_AND_ENTERTAINMENT, 200.00)subLedger.setBalance(Account.SLUSH_FUND, -500.00)
activity = [new JournalEntry(Account.CHECKING, Ind.CREDIT, 100.00),new JournalEntry(Account.TRAVEL_AND_ENTERTAINMENT, Ind.DEBIT, 100.00),
new JournalEntry(Account.CHECKING, Ind.CREDIT, 2000.00),new JournalEntry(Account.SLUSH_FUND, Ind.DEBIT, 2000.00)]
for(i = 0; i < activity.length; i++) subLedger.post(activity[i])
assertEquals(subLedger.getBalance(Account.CHECKING), -1100.00)assertEquals(subLedger.getBalance(Account.TRAVEL_AND_ENTERTAINMENT), 300.00)assertEquals(subLedger.getBalance(Account.SLUSH_FUND), 1500.00)
print("Happy Day!")
JavaCC – Create a DSL
## Test case: #16,678# Author: Marty#
Checking set 1000.00;travel_and_entertainment set 200.00;slush_fund set -500.00; checking post credit 100.00;travel_and_entertainment post debit 100.00;checking post credit 2000.00;slush_fund post debit 2000.00;
Checking verify -1100.00;travel_and_entertainment verify 300.00;slush_fund verify 1500.00;
print happy day!;
https://javacc.dev.java.net/
JavaCC
cmp Jav aCC
JVM
Language Specification
JavaCC
U
DSL Java Source
JavaC
DSL Interpreter
Test Cases - DSL
Test Results
Ledger Java Source
Ledger
«flow»
«flow»
«flow»
«flow»
«flow»
«flow»
«flow»
«flow»
«flow»
«flow»
JavaCC Lexer
SKIP: {" "}
TOKEN: { < CHECKING: "checking" >}
TOKEN: { < OP_SET : "set" > }
TOKEN: { < NUMBER : (["0"-"9"])+ > }
TOKEN: { < EOL: ";" >}
<CHECKING> <OP_SET> <NUMBER> <EOL>
Checking set 1000.00;
JavaCC Parser
Accepts the token stream:
<CHECKING> <OP_SET> <NUMBER> <EOL>
<TRAVEL> <OP_POST> <NUMBER> <EOL>
<EOF>
And enforces order – the grammar:(<CHECKING> <OP_SET> <NUMBER> <EOL> )*
<EOF>
Recognize Statements – Invoke Application
{( <CHECKING><OP_SET>t=<NUMBER>{ amount = new Double(t.image); }<EOL> {System.out.println("Posting: " + amount); }{ledger.setBalance(Account.CHECKING, amount);
})*<EOF>{System.out.println("Happy Day");}
}
Running
>javacc TestLedger.jj >javac -d bin -cp "../bin" gen\*.java >java -classpath "bin;../bin" LedgerLanguage TestCase.txt
cmp Jav aCC
JVM
Language Specification
JavaCC
U
DSL Java Source
JavaC
DSL Interpreter
Test Cases - DSL
Test Results
Ledger Java Source
Ledger
«flow»
«flow»
«flow»
«flow»
«flow»
«flow»
«flow»
«flow»
«flow»
«flow»
Comparison - LOE
Test Harness Authoring
Integration Test Authoring
Groovy H L H
JavaScript L L M
JavaCC H H L
Honorable mentions
SWIGAntlrJavaScript – Mozilla – v8Most scripting languages cross language
interfaces, Perl, Python, etc.Bean ShellJython
Wrap up
JVM is a target for many scripting languagesUsing a JVM based language make
integration easyDSL can make it easy to author test casesSetup can be a hurdle