22
© ThoughtWorks, 2006 Functional Testing Swing Applications with Frankenstein Vivek Prahlad

Functional Testing Swing Applications with Frankenstein

Embed Size (px)

DESCRIPTION

Presentation on Functional Testing Swing Applications with Frankenstein, an Open Source testing tool

Citation preview

Page 1: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Functional Testing Swing Applications with Frankenstein

Vivek Prahlad

Page 2: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Agenda

• Introduction to Frankenstein:– What is it?– Origin– How does it work?– Features

• Demo

Page 3: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

What is Frankenstein

• Record and Play tool for testing Swing Applications• Support for testing Multithreaded Applications• Ruby driver• Easy extension

Page 4: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Origins

• Originated on a ThoughtWorks project with a Swing UI

– Multithreaded user interface

– Custom components (date pickers, etc.)

• Functional testing tools (commercial and open source) inadequate

– Slow, inadequate support for testing multithreaded apps

– Poor custom component support

– Build integration

– License cost for commercial tools

Page 5: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Features

• Record and play support

• Performance

• Ruby driver

• OGNL based assertions

• Multithreaded application support

• Easy extension / customization

• Straightforward integration

• HTML Reports

– Records screenshot on test step failure

– Reports can be customized

Page 6: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

How does it work?

• Recorders hook on to Swing Event Queue

• Attach component specific listeners

• Record Events when the user interacts with the UI

– Event coalescing attempts to minimize script size

• Events can replay themselves

Page 7: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Record and play support

• Recording for reproducing bugs

• Not advisable to record entire scenarios

– Scripts become unmaintainable, difficult to read

• A better way is to record snippets of a user's workflow

– Can extract functions, parameterize

• Later, library functions can be used to write tests from scratch

Page 8: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Ruby driver

• Helps make tests modular

– Extract common steps into functions

– Parameterize functions

• Build a vocabulary for your application

• Test Suite support

Page 9: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Why Ruby?

• Ruby is a full-featured object oriented language

• Focus on readability, ease of use

• Allows test scripts to be modularized

• Lots of flexibility:

– Connect to databases

– Externalize strings (for i18n testing)

– CSV support

Page 10: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Recording + Ruby

• In combination, it is possible to build a testing vocabulary very close to the domain.

• Example:

login username, password

check_balance_is 1100

transfer 100.to destination_account_number

check_balance_is 1000

Page 11: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Assertions

• Control-rightclick on text and labels records assertions

– Need to add additional assertions manually using the Ruby driver

• Assert arbitrary properties via OGNL:

– assert “table_name” , “tableModel.rowCount” , “1”

– Equivalent to:

– assertEquals (1 , table.getTableModel().getRowCount())

• Can even make method calls!

– assert “table_name” “getValueAt(0,0)” , “cell text at row 0, column 0”

• Check out Ruby driver for examples

• http://www.ognl.org for information about OGNL

Page 12: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Testing Multithreaded apps

Two basic approaches exist:

• Arbitrary waits

– Make a guess about when an action will complete

• Explicit synchronization

– Look for indirect indications that actions are complete

Page 13: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Abitrary waits

• Tests are either:

– Slow, if the delays are more than required

– Fragile, if the delays are less than required

• Example:

login username, password

wait(20)

navigate inbox

select all

delete

Page 14: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Explicit Synchronization

• Tests tend to be verbose

• Example:

login username, password

wait_for_label(username)

navigate inbox

select all

delete

• wait_for_label in turn uses a delay within a loop

Page 15: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

FrankensteinApproach

• Scripts do not need to worry about threading issues

• The framework does it for you

– Decide on a worker thread naming convention

– Frankenstein will monitor threads in the system after each test step

• Example

login username, password

navigate inbox

select all

delete

Page 16: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Integrating Frankenstein

• Logically name components ( using component.setName() )

– Naming strategy allows testing UIs where components aren't named

• Use PipingMain to get Frankenstein to launch your app

– Typical startup script: Java .. com.your.app.Main ..

– Change to:

– Java .. com.thoughtworks.frankenstein.application.PipingMain com.your.app.Main ..

• Use Ant's exec task to run Ruby test suite– Remember to launch app using PipingMain first!– May need delay before starting test run to account for app startup time <exec dir="${test.script.dir}" executable="ruby.exe"> <arg line="testsuite.rb"/> </exec>

Page 17: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Customizing Frankenstein

• Write a main class

/** * Launch the application under test via Frankenstein. */public class FrankensteinLauncher { public static void main(String[] args) { FrankensteinIntegration integration = new FrankensteinIntegration(YouMainClass.class); integration.registerEvent(YourCustomEvent.class); integration.registerRecorder(YourCustomRecorder.class); integration.start(args); }}

Page 18: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Customizing Frankenstein

• Register custom events, if any

– Most events can extend AbstractFrankensteinEvent

– Use AbstractEventTestCase

• Register custom recorders, if any

– Most recorders can extend from AbstractComponentRecorder

– Recorders created using IOC, so declare which of these you'll need in your recorder's constructor:

• NamingStrategy, Recorder, ComponentDecoder, ComponentVisibility

Page 19: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Customizing Frankenstein

Multithreading support:

• Decide on a worker thread naming convention, if required

– Use RegexWorkerThreadMonitor

– new FrankensteinIntegration(YourMain.class, new RegexWorkerThreadMonitor(“<thread name pattern>”);

• Or implement the WorkerThreadMonitor interface

Page 20: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Demo

Page 21: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Get it at

• https://svn.openqa.org/svn/frankenstein/trunk• Main site at http://www.openqa.org/frankenstein

Page 22: Functional Testing Swing Applications with Frankenstein

© ThoughtWorks, 2006

Coming Soon

• Drag and Drop support

• Tree editor support

• Smart renderer decoders

– Pluggable renderer decoding support

• More assertions