SWTBot Essentials
                    Chris Aniszczyk
                http://aniszczyk.org
             caniszczyk@gmail.c...
Agenda
introduction
exercises
  setting up the environment
  SWTBot API
how does it work?
conclusion and Q&A
UI Testing


 It’s not easy, natural brittleness...
 manual vs. automated testing
 deciding what to test
UI Testing Challenges
Challenges
Identifying Controls
Challenges
Similar looking controls
Similar looking controls
Moving controls
Challenges
Sending “events” to controls
Challenges
Manage SWT Threading
Challenges
Tests to be non-blocking
Challenges
Run in a separate thread
Still manage synchronization between threads
Challenges
Internationalization (i18n) and Localization (L10n)
Challenges
Readability
Hands on exercises!
Learn by doing.
All exercises focus around...
 creating a java project “MyFirstProject”
 create a java class
 type in a program that print...
Exercise 0: Setup
Test01.java
Objectives
Setup SWTBot
Run a test with the SWTBot launch configuration
Setting up the Environment
Use Eclipse 3.6
Install SWTBot via update site
  http://www.eclipse.org/swtbot/downloads.php
Create a plugin project
 “org.eclipse.swtbot.examples”
Setup Dependencies
org.eclipse.ui
org.eclipse.core.runtime
org.eclipse.swtbot.eclipse.finder
org.eclipse.swtbot.junit4_x
or...
Create a new plugin project
Create a simple Test
   @RunWith(SWTBotJunit4ClassRunner.class)
   public class Test01 {

   	   @Test
   	   public void ...
Run the first test
SWTBot API Introduction
Finding widgets
SWTWorkbenchBot bot = new SWTWorkbenchBot();

SWTBot[Widget] widget = bot.[widget][With][Matcher(s)]();

S...
Finding obscure widgets
  Use matchers and WidgetMatcherFactory!

withLabel("Username:")       Matcher pushButtonToProceed...
Performing actions
button.click() // click on a button

// chain methods to make them concise
bot.menu("File").menu("New")...
Exercise 1: Hello SWTBot
SWTBotTest01.java
Objectives
Get introduced to the SWTBot API
  SWTWorkbenchBot is your friend
Tasks
  beforeClass() - close the welcome vie...
beforeClass()


	   @BeforeClass
	   public static void beforeClass() throws Exception {
	   	 bot = new SWTWorkbenchBot()...
canCreateANewProject()

     @Test
 	   public void canCreateANewJavaProject() throws Exception {
 	   	    bot.menu("File...
Seeing log messages?
How does it work? Magic?
)"*#(+,,(
-"#$%&'(




 !"#$%&'(
Redundancy and Failure
Proofing
)"*#(+,,(
-"#$%&'(




 !"#$%&'(
Find all widgets

  Depth first traversal of UI elements


1.Find top level widgets
  1.Find children of each widget
2.For ...
Finding widgets

public SWTBotTree treeWithLabelInGroup(String l, String g, int i) {

       // create the matcher
       ...
Thread Safety


Tests should run in non-ui thread
query state of a widget
change state of a widget
Thread Safety (Query state)

    public class SWTBotCheckBox {
	   public boolean isChecked() {
	   	 // evaluate a result...
Thread Safety(change state)

public class SWTBotCheckBox {
	   public void select() {
	   	   asyncExec(new VoidResult() {...
Exercise 2: More SWTBot
SWTBotTest02.java
Objectives
Tasks
  canCreateANewJavaClass()
    create a new java class: HelloWorld
    Source folder: MyFirstProject/src
...
canCreateANewJavaClass()

	   @Test
	   public void canCreateANewJavaClass() throws Exception {
	   	   bot.toolbarDropDow...
Exercise 3: SWTBotEditor
SWTBotTest03.java
Objectives
Tasks
  canTypeInTextInAJavaClass()
    open a file: HelloWorld.java
    set some text in the Java file
  canExec...
canTypeInTextInAJavaClass()
     @Test
 	   public void canTypeInTextInAJavaClass() throws Exception {
 	   	    Bundle bu...
canExecuteJavaApplication()

    	   @Test
    	   public void canExecuteJavaApplication() throws Exception {
    	   	 bo...
SWTBotEditor
Exercise 4: Matchers
SWTBotTest04.java
Objectives
Learn about SWTBot and the Matcher API
Tasks
  canExecuteJavaApplication()
    Run the Java application
    Gra...
canExecuteJavaApplication()
	   @Test
	   public void canExecuteJavaApplication() throws Exception {
	   	 bot.menu("Run")...
Matchers
Under the covers, SWTBot uses Hamcrest
Hamcrest is a framework for writing ‘match’ rules
SWTBot is essentially al...
WidgetMatcherFactory
Creating matchers

WidgetMatcherFactory is your friend!
withText("Finish")
withLabel("Username:")
withRegex("Proceed to st...
Combining matchers

allOf(matchers...)
anyOf(matchers...)
not(matcher)
allOf(anyOf(matchers...), matchers...)
Exercise 5: Waiting
SWTBotTest05.java
Objectives
Learn about waiting and SWTBot Condition API
Tasks
  afterClass()
    Select the Package Explorer view
    Sele...
afterClass()
	   @AfterClass
	   public static void afterClass() throws Exception {
	   	    SWTBotView packageExplorerVie...
Handling long operations

describe a condition
poll for the condition at intervals
wait for it to evaluate to true or fals...
ICondition
Handling Waits

private void waitUntil(ICondition condition, long timeout, long interval) {

	   long limit = System.curre...
Conditions is your friend
Building Abstractions
Abstractions are good!
 They simplify writing tests for QA folks
 Build page objects for common “services”
   Project Expl...
Model Capabilities

 Create a project
 Delete a project
 Create a class
 Execute a class
 more...
Domain Objects
Domain Objects?



Represent the operations that can be performed on
concepts
Sample Domain Object

public class JavaProject {
	 public JavaProject create(String projectName){
	 	 // create a project ...
Page Objects
http://code.google.com/p/webdriver/wiki/PageObjects
Page Objects?
Represent the services offered by the page to the test
developer
Internally knows the details about how thes...
Page Objects... should not


 Expose details about user interface elements
 Make assertions about the state of the UI
A Sample Page Object

    public class LoginPage {

	   public HomePage loginAs(String user, String pass) {
	   	   // ......
Using Page Objects

// the bad test
public void testMessagesAreReadOrUnread() {
    Inbox inbox = new Inbox(driver);
    i...
LoginPage login = new LoginPage();
HomePage home = login.loginAs("username", "secret");
SearchPage search = home.searchFor...
Exercise 6: Abstractions
SWTBotTest06.java
Objectives
Learn about page and domain objects
Tasks
  Create a NewProjectBot
    Opens the new project wizard
    Allows ...
NewProjectBot
public class NewProjectBot {

    private static SWTWorkbenchBot      bot;

    public NewProjectBot() {
   ...
Modify Project Wizard Code
 @Test
 public void canCreateANewJavaProject() throws Exception {
    // use the NewProjectBot ...
Best Practices & Tips
Logging
Turn logging on always, it helps :)
http://wiki.eclipse.org/SWTBot/
FAQ#How_do_I_configure_log4j_to_turn_on
_loggi...
Slow down executions
  Useful for debugging at times...
  SWTBotPreferences.PLAYBACK_DELAY
  -Dorg.eclipse.swtbot.playback...
Changing Timeout
  SWTBotPreferences.TIMEOUT
  -Dorg.eclipse.swtbot.search.timeout=10000
  or via code...
long oldTimeout ...
Identifiers
 In our examples, we used labels as matchers mostly
 SWTBot allows you to use IDs as matchers
 IDs are less bri...
Page Objects
Use Page Objects to simplify writing tests
Allows more people than just normal devs to write tests
More SWTBot?


Eclipse Forms support in HEAD
GEF support is available for graphical editor testing
Questions ?
newsgroup: news://news.eclipse.org/eclipse.swtbot
web: eclipse.org/swtbot
SWTBot Tutorial
Upcoming SlideShare
Loading in...5
×

SWTBot Tutorial

20,497

Published on

A set of slides to teach people about SWTBot.

Published in: Technology, Education
1 Comment
12 Likes
Statistics
Notes
No Downloads
Views
Total Views
20,497
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
458
Comments
1
Likes
12
Embeds 0
No embeds

No notes for slide










































































  • Should:
    * Represent the services offered by the page to the test developer
    * Internally knows the details about how these services are offered and the details of UI elements that offer them
    * Return other page objects to model the user’s journey through the application
    * Different results of the same operation modeled differently
  • Should not:
    * Expose details about user interface elements
    * Make assertions about the state of the UI













  • Transcript of "SWTBot Tutorial"

    1. 1. SWTBot Essentials Chris Aniszczyk http://aniszczyk.org caniszczyk@gmail.com
    2. 2. Agenda introduction exercises setting up the environment SWTBot API how does it work? conclusion and Q&A
    3. 3. UI Testing It’s not easy, natural brittleness... manual vs. automated testing deciding what to test
    4. 4. UI Testing Challenges
    5. 5. Challenges Identifying Controls
    6. 6. Challenges Similar looking controls
    7. 7. Similar looking controls
    8. 8. Moving controls
    9. 9. Challenges Sending “events” to controls
    10. 10. Challenges Manage SWT Threading
    11. 11. Challenges Tests to be non-blocking
    12. 12. Challenges Run in a separate thread Still manage synchronization between threads
    13. 13. Challenges Internationalization (i18n) and Localization (L10n)
    14. 14. Challenges Readability
    15. 15. Hands on exercises! Learn by doing.
    16. 16. All exercises focus around... creating a java project “MyFirstProject” create a java class type in a program that prints “Hello, World” execute the program verify that the program printed “Hello, World”
    17. 17. Exercise 0: Setup Test01.java
    18. 18. Objectives Setup SWTBot Run a test with the SWTBot launch configuration
    19. 19. Setting up the Environment Use Eclipse 3.6 Install SWTBot via update site http://www.eclipse.org/swtbot/downloads.php
    20. 20. Create a plugin project “org.eclipse.swtbot.examples”
    21. 21. Setup Dependencies org.eclipse.ui org.eclipse.core.runtime org.eclipse.swtbot.eclipse.finder org.eclipse.swtbot.junit4_x org.eclipse.swtbot.swt.finder org.junit4
    22. 22. Create a new plugin project
    23. 23. Create a simple Test @RunWith(SWTBotJunit4ClassRunner.class) public class Test01 { @Test public void thisOneFails() throws Exception { fail("this test fails"); } @Test public void thisOnePasses() throws Exception { pass(); } }
    24. 24. Run the first test
    25. 25. SWTBot API Introduction
    26. 26. Finding widgets SWTWorkbenchBot bot = new SWTWorkbenchBot(); SWTBot[Widget] widget = bot.[widget][With][Matcher(s)](); SWTBotText text = bot.textWithLabel("Username:"); Think of the bot as something that can do tasks for you (e.g., find widgets, click on them, etc.)
    27. 27. Finding obscure widgets Use matchers and WidgetMatcherFactory! withLabel("Username:") Matcher pushButtonToProceedToNextStep = allOf( withMnemonic("Finish") widgetOfType(Button.class), withText("&Finish") withStyle(SWT.PUSH), inGroup("Billing Address") withRegex("Proceed to step (.*) >") widgetOfType(Button.class) ); withStyle(SWT.RADIO) withTooltip("Save All") SWTBotButton button = new SWTBotButton( withRegex("Welcome, (.*)") (Button) bot.widget(pushButtonToProceedToNextStep) );
    28. 28. Performing actions button.click() // click on a button // chain methods to make them concise bot.menu("File").menu("New").menu("Project...").click(); tree.expand("Project").expand("src").expand("Foo.java").contextMenu("Delete").clic k(); // delete Foo.java list.select("Orange", "Banana", "Mango"); // make a selection in a list list.select(2, 5, 6); // make a selection using indexes
    29. 29. Exercise 1: Hello SWTBot SWTBotTest01.java
    30. 30. Objectives Get introduced to the SWTBot API SWTWorkbenchBot is your friend Tasks beforeClass() - close the welcome view canCreateANewProject() - create a java project Run the test! Ensure SWTBot logging works
    31. 31. beforeClass() @BeforeClass public static void beforeClass() throws Exception { bot = new SWTWorkbenchBot(); bot.viewByTitle("Welcome").close(); }
    32. 32. canCreateANewProject() @Test public void canCreateANewJavaProject() throws Exception { bot.menu("File").menu("New").menu("Project...").click(); SWTBotShell shell = bot.shell("New Project"); shell.activate(); bot.tree().select("Java Project"); bot.button("Next >").click(); bot.textWithLabel("Project name:").setText("MyFirstProject"); bot.button("Finish").click(); }
    33. 33. Seeing log messages?
    34. 34. How does it work? Magic?
    35. 35. )"*#(+,,( -"#$%&'( !"#$%&'(
    36. 36. Redundancy and Failure Proofing
    37. 37. )"*#(+,,( -"#$%&'( !"#$%&'(
    38. 38. Find all widgets Depth first traversal of UI elements 1.Find top level widgets 1.Find children of each widget 2.For each child do (1) and (2)
    39. 39. Finding widgets public SWTBotTree treeWithLabelInGroup(String l, String g, int i) { // create the matcher Matcher matcher = allOf( widgetOfType(Tree.class), withLabel(l), inGroup(g) ); // find the widget, with redundancy built in Tree tree = (Tree) widget(matcher, index); // create a wrapper for thread safety // and convinience APIs return new SWTBotTree(tree, matcher); }
    40. 40. Thread Safety Tests should run in non-ui thread query state of a widget change state of a widget
    41. 41. Thread Safety (Query state) public class SWTBotCheckBox { public boolean isChecked() { // evaluate a result on the UI thread return syncExec(new BoolResult() { public Boolean run() { return widget.getSelection(); } }); } }
    42. 42. Thread Safety(change state) public class SWTBotCheckBox { public void select() { asyncExec(new VoidResult() { public void run() { widget.setSelection(true); } }); notifyListeners(); } protected void notifyListeners() { notify(SWT.MouseDown); notify(SWT.MouseUp); notify(SWT.Selection); } }
    43. 43. Exercise 2: More SWTBot SWTBotTest02.java
    44. 44. Objectives Tasks canCreateANewJavaClass() create a new java class: HelloWorld Source folder: MyFirstProject/src Package: org.eclipsecon.project Click Finish! Run the test!
    45. 45. canCreateANewJavaClass() @Test public void canCreateANewJavaClass() throws Exception { bot.toolbarDropDownButtonWithTooltip("New Java Class").menuItem("Class").click(); bot.shell("New Java Class").activate(); bot.textWithLabel("Source folder:").setText("MyFirstProject/src"); bot.textWithLabel("Package:").setText("org.eclipsecon.project"); bot.textWithLabel("Name:").setText("HelloWorld"); bot.button("Finish").click(); }
    46. 46. Exercise 3: SWTBotEditor SWTBotTest03.java
    47. 47. Objectives Tasks canTypeInTextInAJavaClass() open a file: HelloWorld.java set some text in the Java file canExecuteJavaApplication() Run the Java application Run the test!
    48. 48. canTypeInTextInAJavaClass() @Test public void canTypeInTextInAJavaClass() throws Exception { Bundle bundle = Activator.getContext().getBundle(); String contents = FileUtils.read(bundle.getEntry("test-files/HelloWorld.java")); SWTBotEditor editor = bot.editorByTitle("HelloWorld.java"); SWTBotEclipseEditor e = editor.toTextEditor(); e.setText(contents); editor.save(); }
    49. 49. canExecuteJavaApplication() @Test public void canExecuteJavaApplication() throws Exception { bot.menu("Run").menu("Run").click(); // FIXME: verify that the program printed 'Hello World' }
    50. 50. SWTBotEditor
    51. 51. Exercise 4: Matchers SWTBotTest04.java
    52. 52. Objectives Learn about SWTBot and the Matcher API Tasks canExecuteJavaApplication() Run the Java application Grab the Console view Verify that “Hello World” is printed Run the tests!
    53. 53. canExecuteJavaApplication() @Test public void canExecuteJavaApplication() throws Exception { bot.menu("Run").menu("Run").click(); SWTBotView view = bot.viewByTitle("Console"); Widget consoleViewComposite = view.getWidget(); StyledText console = bot.widget(WidgetMatcherFactory.widgetOfType(StyledText.class), consoleViewComposite); SWTBotStyledText styledText = new SWTBotStyledText(console); assertTextContains("Hello World", styledText); }
    54. 54. Matchers Under the covers, SWTBot uses Hamcrest Hamcrest is a framework for writing ‘match’ rules SWTBot is essentially all about match rules bot.widget(WidgetMatcherFactory.widgetO fType(StyledText.class), consoleViewComposite);
    55. 55. WidgetMatcherFactory
    56. 56. Creating matchers WidgetMatcherFactory is your friend! withText("Finish") withLabel("Username:") withRegex("Proceed to step (.*)") widgetOfType(Button.class) withStyle(SWT.ARROW, "SWT.ARROW")
    57. 57. Combining matchers allOf(matchers...) anyOf(matchers...) not(matcher) allOf(anyOf(matchers...), matchers...)
    58. 58. Exercise 5: Waiting SWTBotTest05.java
    59. 59. Objectives Learn about waiting and SWTBot Condition API Tasks afterClass() Select the Package Explorer view Select MyFirstProject Right click and delete the project Run the test!
    60. 60. afterClass() @AfterClass public static void afterClass() throws Exception { SWTBotView packageExplorerView = bot.viewByTitle("Package Explorer"); packageExplorerView.show(); Composite packageExplorerComposite = (Composite) packageExplorerView.getWidget(); Tree swtTree = (Tree) bot.widget(WidgetMatcherFactory.widgetOfType(Tree.class), packageExplorerComposite); SWTBotTree tree = new SWTBotTree(swtTree); tree.select("MyFirstProject"); bot.menu("Edit").menu("Delete").click(); // the project deletion confirmation dialog SWTBotShell shell = bot.shell("Delete Resources"); shell.activate(); bot.checkBox("Delete project contents on disk (cannot be undone)").select(); bot.button("OK").click(); bot.waitUntil(shellCloses(shell)); }
    61. 61. Handling long operations describe a condition poll for the condition at intervals wait for it to evaluate to true or false of course there’s a timeout SWTBot has an ICondition
    62. 62. ICondition
    63. 63. Handling Waits private void waitUntil(ICondition condition, long timeout, long interval) { long limit = System.currentTimeMillis() + timeout; condition.init((SWTBot) this); while (true) { try { if (condition.test()) return; } catch (Throwable e) { // do nothing } sleep(interval); if (System.currentTimeMillis() > limit) throw new TimeoutException("Timeout after: " + timeout); } }
    64. 64. Conditions is your friend
    65. 65. Building Abstractions
    66. 66. Abstractions are good! They simplify writing tests for QA folks Build page objects for common “services” Project Explorer The Editor The Console View The main menu bar, tool bar
    67. 67. Model Capabilities Create a project Delete a project Create a class Execute a class more...
    68. 68. Domain Objects
    69. 69. Domain Objects? Represent the operations that can be performed on concepts
    70. 70. Sample Domain Object public class JavaProject { public JavaProject create(String projectName){ // create a project and return it } public JavaProject delete(){ // delete the project and return it } public JavaClass createClass(String className){ // create a class and return it } }
    71. 71. Page Objects http://code.google.com/p/webdriver/wiki/PageObjects
    72. 72. Page Objects? Represent the services offered by the page to the test developer Internally knows the details about how these services are offered and the details of UI elements that offer them Return other page objects to model the user’s journey through the application Different results of the same operation modeled
    73. 73. Page Objects... should not Expose details about user interface elements Make assertions about the state of the UI
    74. 74. A Sample Page Object public class LoginPage { public HomePage loginAs(String user, String pass) { // ... clever magic happens here } public LoginPage loginAsExpectingError(String user, String pass) { // ... failed login here, maybe because one or both of // username and password are wrong } public String getErrorMessage() { // So we can verify that the correct error is shown } }
    75. 75. Using Page Objects // the bad test public void testMessagesAreReadOrUnread() { Inbox inbox = new Inbox(driver); inbox.assertMessageWithSubjectIsUnread("I like cheese"); inbox.assertMessageWithSubjectIsNotUndread("I'm not fond of tofu"); } // the good test public void testMessagesAreReadOrUnread() { Inbox inbox = new Inbox(driver); assertTrue(inbox.isMessageWithSubjectIsUnread("I like cheese")); assertFalse(inbox.isMessageWithSubjectIsUnread("I'm not fond of tofu")); }
    76. 76. LoginPage login = new LoginPage(); HomePage home = login.loginAs("username", "secret"); SearchPage search = home.searchFor("swtbot"); assertTrue(search.containsResult("http://eclipse.org/swtbot"));
    77. 77. Exercise 6: Abstractions SWTBotTest06.java
    78. 78. Objectives Learn about page and domain objects Tasks Create a NewProjectBot Opens the new project wizard Allows you to set the project name and click finish Modify canCreateANewJavaProject() Run the test!
    79. 79. NewProjectBot public class NewProjectBot { private static SWTWorkbenchBot bot; public NewProjectBot() { bot.menu("File").menu("New").menu("Project...").click(); bot.shell("New Project").activate(); bot.tree().select("Java Project"); bot.button("Next >").click(); } public void setProjectName(String projectName) { bot.textWithLabel("Project name:").setText(projectName); } public void finish() { bot.button("Finish").click(); } }
    80. 80. Modify Project Wizard Code @Test public void canCreateANewJavaProject() throws Exception { // use the NewProjectBot abstraction NewProjectBot newProjectBot = new NewProjectBot(); newProjectBot.setProjectName("MyFirstProject"); newProjectBot.finish(); assertProjectCreated(); }
    81. 81. Best Practices & Tips
    82. 82. Logging Turn logging on always, it helps :) http://wiki.eclipse.org/SWTBot/ FAQ#How_do_I_configure_log4j_to_turn_on _logging_for_SWTBot.3F
    83. 83. Slow down executions Useful for debugging at times... SWTBotPreferences.PLAYBACK_DELAY -Dorg.eclipse.swtbot.playback.delay=20 or via code... long oldDelay = SWTBotPreferences.PLAYBACK_DELAY; // increase the delay SWTBotPreferences.PLAYBACK_DELAY = 10; // do whatever // set to the original timeout of 5 seconds SWTBotPreferences.PLAYBACK_DELAY = oldDelay;
    84. 84. Changing Timeout SWTBotPreferences.TIMEOUT -Dorg.eclipse.swtbot.search.timeout=10000 or via code... long oldTimeout = SWTBotPreferences.TIMEOUT; // increase the timeout SWTBotPreferences.TIMEOUT = 10000; // do whatever // set to the original timeout of 5 seconds SWTBotPreferences.TIMEOUT = oldTimeout;
    85. 85. Identifiers In our examples, we used labels as matchers mostly SWTBot allows you to use IDs as matchers IDs are less brittle than labels! text.setData(SWTBotPreferences.DEFAULT_ KEY,”id”) bot.textWithId(“id”)
    86. 86. Page Objects Use Page Objects to simplify writing tests Allows more people than just normal devs to write tests
    87. 87. More SWTBot? Eclipse Forms support in HEAD GEF support is available for graphical editor testing
    88. 88. Questions ? newsgroup: news://news.eclipse.org/eclipse.swtbot web: eclipse.org/swtbot
    1. Gostou de algum slide específico?

      Recortar slides é uma maneira fácil de colecionar informações para acessar mais tarde.

    ×