081107 Sammy Eclipse Summit2
-
Upload
mkempka -
Category
Technology
-
view
947 -
download
1
description
Transcript of 081107 Sammy Eclipse Summit2
Enabling Test-First Development for Eclipse UI
Matthias KempkaInnoopract Informationssysteme GmbH
OutlineOutline
Problem description Components for testing UI programmatically Test Case with JFace/Workbench Robot Sammy
Creating code test-drivenCreating code test-driven
Piece of Code
Unit Tests
TDD creates little pieces of code Readable Simple Flexible Regression tests already there Great, uh?
Where should I put it?Where should I put it?
Piece of Code
A framework has many hooks Did I hook up my PoC in the right spot? Did I hook it up at all?
Eclipse Framework
„„Testing“ by handTesting“ by hand
Developer
Easiest approach: Try it. Regression tests?
Piece of Code
Eclipse Framework
use
*click*
PDE TestsPDE Tests
PDE Unit Tests
Let's write regression tests PDE tests can start our test code with a workbench Some Eclipse functionality is hard to reach programmatically
Piece of Code
Eclipse Framework
Functional Tests with SWT RobotsFunctional Tests with SWT Robots
Piece of Code
Eclipse Framework
PDE Unit Tests SWT Robot
use
use
*click*
SWT Robots can simulate User interaction Is it easier to find a ViewAction button on the screen than in the Workbench
API?
Are SWT Robots the solution?Are SWT Robots the solution?
Can find SWT widgets in the widget hierarchy Provides convenience methods to use the widgets Can read feedback from the UI
Composite
Shell
Label Text
Display
What's not in the Widget Hierarchy?What's not in the Widget Hierarchy?
Basically all objects an Eclipse programmer touches are not in the widget hierarchy
Association with IDs from plugin.xml is lost
Composite
Shell
Label Text
Display IViewPart
IEditorPart
TableViewer
TreeViewer
IActionDelegate
IHandler
...
IMarker
Functional Tests with RobotsFunctional Tests with Robots
Piece of Code
Eclipse Framework
SWT Robot
JFace/WorkbenchRobot
A JFace/Workbench Robot eases access to the interesting parts of the UI. Provides access to JFace controllers
PDE Unit Tests
use
*click*
Make common things easy, make difficult things possible
I need to set up test data for the TableViewer behind this SWT Table on the screen? How can I reach it?
I'm writing a view. How can I test that all the listeners are attached correctly? I'm writing a contribution to a view (i.e. a ViewAction) – How can I test that
my entries in plugin.xml works? Does my LabelProvider return the right image?
Sammy: The MissionSammy: The Mission
Writing a test with JFace/Workbench Robot Writing a test with JFace/Workbench Robot SammySammy
Write a test case: Set up: Prepare a view for the actual test
– open the view Tear down:
– Clean up allocated resources: Close the view Actual test
– Find the TableViewer in that view and set a test-specific input– Check that a view action is not enabled– Select an item in the table– Check that the view action is enabled
Set up: Open a viewSet up: Open a view
Views could be opened using IWorkbenchPage.showView( id )– Too cumbersome for such a common use case – No immediate feedback on errors
Sammy.openView( id ) eases setting up test cases– easy accessible API– Show errors in red test case instead of UI– Remembers the view for cleaning up
public void setup() throws Exception { sammy = new Sammy(); sammy.openView( ViewUnderTest.ID );}
Tear downTear down
Instances of Sammy (and SammyIDE) remember the resources they allocated and can release (close or delete) them– IViewPart– IEditorPart– IResource
public void teardown() throws Exception { sammy.cleanup();}
Test: Finding the viewTest: Finding the view
Every supported JFace/Workbench Element has an Operator:– IViewPart – ViewOperator– IEditorPart – EditorOperator– TableViewer – TableViewerOperator– …
The Operator gives access to the described JFace/Workbench element– Convenience methods for common use cases
Operator constructor – takes parameters that describe the JFace/Workbench element– returns without Exception only if the described element was found– waits a time for the element to appear
public void testViewAction() throws Exception { ViewOperator vo = new ViewOperator( “View Title” );}
Test: Finding the TableViewerTest: Finding the TableViewer
Operators for workbench parts know their parent composite– Given in IWorkbenchPart.createPartControl( Composite )
Operators for JFace elements – take a parent of the SWT element or the SWT element itself– can associate the SWT element with the JFace abstraction
public void testViewAction() throws Exception { ViewOperator vo = new ViewOperator( “View Title” ); TableViewerOperator tvo = new TableViewerOperator( vo.getParentComposite() );}
Test: Setting the InputTest: Setting the Input
Setting up Test Data often includes setting a special input on a viewer Having the TableViewer already available eases this remarkably *Operator.getSource()returns the actual JFace/Workbench element
public void testViewAction() throws Exception { ViewOperator vo = new ViewOperator( “View Title” ); TableViewerOperator tvo = new TableViewerOperator( vo.getParentComposite() ); tvo.getSource().setInput( new String[] { “a” } );}
Test: Checking ViewerOperator enablementTest: Checking ViewerOperator enablement
A ViewActionDelegate only is instanciated once the user selects the ViewAction
The ViewActionOperator knows the Proxy by the workbench as well as the delegate
public void testViewAction() throws Exception { ViewOperator vo = new ViewOperator( “View Title” ); TableViewerOperator tvo = new TableViewerOperator( vo.getParentComposite() ); tvo.getSource().setInput( new String[] { “a” } ); ViewActionOperator vao = new ViewActionOperator( vo, MyViewAction.ID ); assertFalse( vao.isEnabled() );}
Test: Checking ViewerOperator enablementTest: Checking ViewerOperator enablement
Now all the elements are in place to make this test useful– The View shows up (layout is not tested)– XML Code in plugin.xml is tested– Makes sure that the TableViewer is a SelectionProvider
public void testViewAction() throws Exception { ViewOperator vo = new ViewOperator( “View Title” ); TableViewerOperator tvo = new TableViewerOperator( vo.getParentComposite() ); tvo.getSource().setInput( new String[] { “a” } ); ViewActionOperator vao = new ViewActionOperator( vo, MyViewAction.ID ); assertFalse( vao.isEnabled() ); tvo.getSource().setSelection( new StructuredSelection(“a”)); assertTrue( vao.isEnabled() );}
Sammy InternalsSammy Internals
Widget Viewer
For many things, Sammy relies on mapping from widgets to JFace/Workbench elements– And vice versa
Some widgets are nowhere accessible in the workbench– Where necessary aspects are used to trap widget instances
For some things, Sammy has to access internals– i.e. the View that shows an error holds it in a private field– This leads to compatibility layers, but at least it's in one place
Sammy FutureSammy Future
More than proof of concept, less than beta A good state to start collecting requirements http://www.innoopract.com/en/developers/mkempka/sammy
The End
http://www.innoopract.com/en/developers/mkempka/sammy