SlideShare una empresa de Scribd logo
1 de 61
Descargar para leer sin conexión
Beyond Page Objects
                                    Dante Briones
                                    SeleniumConf
                                     5 April 2011

                             http://electronicingenuity.com
                            dante@electronicingenuity.com
                                     @dantebriones

Wednesday, 06 April, 2011
Let’s Start With A Story




Wednesday, 06 April, 2011
A long time ago* in an investment bank
                                     far, far away...




                                       *(2005)

Wednesday, 06 April, 2011
Our Hero




Wednesday, 06 April, 2011
A Chance Encounter




Wednesday, 06 April, 2011
A New Weapon




Wednesday, 06 April, 2011
Engaging The Enemy




Wednesday, 06 April, 2011
Victory


                                  MUCH more readable!




Wednesday, 06 April, 2011
What’s The Moral?


                        (hint: it’s not about the developer, the
                        author, or the book)




Wednesday, 06 April, 2011
The Details




Wednesday, 06 April, 2011
Why Page Objects?




Wednesday, 06 April, 2011
Why Page Objects?




Wednesday, 06 April, 2011
Why Page Objects?




Wednesday, 06 April, 2011
Tests Are Code


                             They need TLC



Wednesday, 06 April, 2011
Readability


        selenium.click(“id=itemAction1138”);
        assertEquals(“1”, selenium.getText(“css=#cart .count”));

                                   vs.
        item.clickAddToCart();
        assertEquals(1, cart.getItemCount());




Wednesday, 06 April, 2011
Stay DRY
         Test class:
         selenium.click(“id=zoom_out_action”);
         selenium.click(“id=zoom_out_action”);

                                     vs.
         Test class:
         map.zoomOut();
         map.zoomOut();
         Map class:
         selenium.click(“id=zoom_out_action”);


Wednesday, 06 April, 2011
Robustitude


         Thread.sleep(250); //wait for button to appear
         selenium.click(“id=a_button”);
         Thread.sleep(500); //wait for results to show up
         assertEquals(selenium.getText(“id=results”),
             “False Negatives suck!”);




Wednesday, 06 April, 2011
Sensible Names

                    • catalogItem.addToCart()
                    • blogEntry.post()
                    • auction.bid(25.00)


Wednesday, 06 April, 2011
Small Classes




Wednesday, 06 April, 2011
How Do We Get
                               There?

                    • Refactoring
                    • Apply Design Patterns
                    • Continuous Improvement


Wednesday, 06 April, 2011
How Do We Get
                               There?




Wednesday, 06 April, 2011
Context

                    • Several consulting gigs over the past few
                            years
                    • Current client:
                     • consumer-facing RIA
                     • tests written with Selenium 1 API in Java

Wednesday, 06 April, 2011
PRO TIP


                            Use WebDriver


Wednesday, 06 April, 2011
Page Objects Recap

                    • Model the application’s UI
                    • Expose methods that reflect the things a
                            user can see and do on that page
                    • Hides the details of telling the browser
                            how to do those things



Wednesday, 06 April, 2011
Page Object Benefits

                    • Readable tests
                    • Reduced or eliminated duplication
                    • Self-verification
                    • Reusability

Wednesday, 06 April, 2011
So Why Go “Beyond”?


                            Web Apps Are Different Now




Wednesday, 06 April, 2011
Why Go “Beyond”?


                                   meh

                                  OMG SOOO MUCH BETTER




Wednesday, 06 April, 2011
Why Go “Beyond”?




Wednesday, 06 April, 2011
Why Go “Beyond”?


                             Because modern web apps are
                                 dynamic and rich




Wednesday, 06 April, 2011
Example: Pivotal Tracker




Wednesday, 06 April, 2011
Wednesday, 06 April, 2011
Modeling The UI
         public class IssueSummary {
                   public IssueDetail expand() {...}
         }


         public class IssueDetail {
                   public void save() {...}
                   public void cancel() {...}
                   public String getStoryId() {...}
         }




Wednesday, 06 April, 2011
What’s This, Then?


                 I call them “Page Components”



Wednesday, 06 April, 2011
Method Chaining: Focus
                      Stays Put
         public class IssueDetail {
                   public void save() {...}
                   public IssueDetail addComment(String comment) {
                      ...
                      return this;
                  }
         }


         issueDetail.addComment().save();




Wednesday, 06 April, 2011
Method Chaining: Focus
                  Moves Elsewhere
         public class IssueDetail {
                  public ConfirmationDialog delete() {
                      ...
                      return new ConfirmationDialog();
                  }
         }


         issueDetail.delete().confirm();
         or
         issueDetail.delete().cancel();



Wednesday, 06 April, 2011
Page Component
                                   Recap

                    • Just like Page Objects... but littler
                    • Use return types to model the user
                            experience




Wednesday, 06 April, 2011
ComponentFactory


                              Do you like to type? I don’t.




Wednesday, 06 April, 2011
ComponentFactory


                                              1/(keystrokes
                        Job Satisfaction =   required write
                                             useful code)




Wednesday, 06 April, 2011
ComponentFactory
         public class ComponentFactory {
               public IssueSummary issueSummary() {
                            return new IssueSummary(...);
               }
         }
         public abstract BaseTestCase {
               protected ComponentFactory withComponent() {
                            return new ComponentFactory();
               }
         }



Wednesday, 06 April, 2011
ComponentFactory

                               new IssueSummary(selenium).expand();



                                               vs.
                             withComponent().issueSummary().expand();




Wednesday, 06 April, 2011
ComponentFactory
                                Recap

                    • Interactive documentation
                    • Easier entry point into component creation
                    • Another way to use strong typing to make
                            the tests easier to write




Wednesday, 06 April, 2011
Indexed Components




Wednesday, 06 April, 2011
Indexed Components


         IssueSummary summary =
               withComponent().backlog().issueSummary(0);
         assertEquals(summary.getTitle(), “some title”);




Wednesday, 06 April, 2011
Indexed Components

         CSS locators:
         Backlog = #backlog
         First issue summary = #backlog .issue-summary:nth(0)
         “Expand” button = #backlog .issue-summary:nth(0) .expand
         Title = #backlog .issue-summary:nth(0) .title




Wednesday, 06 April, 2011
The Locator Class
         public class Locator {
             protected int index;

                   public Locator(String rootLocator, int index) {
                     this.rootLocator = rootLocator;
                     this.index = index;
               }

                   public String of(String containedElement) {
                       return String.format(rootLocator, index) +
                             " " + containedElement;
                   }
         }


Wednesday, 06 April, 2011
Using A Locator
         public IssueDetail expand() {
               selenium.click(“#backlog .issue-summary:nth(0) .expand”);
               ...
       }

                                         vs.

       public IssueDetail expand() {
               selenium.expand(locator.of(“.expand”));
               ...
       }

Wednesday, 06 April, 2011
Synchronization Issues

                       Two kinds:
                       1. Element not present yet
                       2. Element content not updated yet




Wednesday, 06 April, 2011
Thread.sleep()


                                        NO.*
                            STEP AWAY FROM THE KEYBOARD.




Wednesday, 06 April, 2011
Thread.sleep()


                                            NO.*
                            STEP AWAY FROM THE KEYBOARD.


                             (*unless you have no other choice)


Wednesday, 06 April, 2011
Thread.sleep()

       Just be sure to wrap it in an appropriately named method:




Wednesday, 06 April, 2011
Thread.sleep()

       Just be sure to wrap it in an appropriately named method:

 • sleepAsALastResortWhenNothingElseWorks()




Wednesday, 06 April, 2011
Thread.sleep()

       Just be sure to wrap it in an appropriately named method:

 • sleepAsALastResortWhenNothingElseWorks()
 • sleepToMakeThisTestMoreFlakyThusEnsuringMyJobSecurity()




Wednesday, 06 April, 2011
Thread.sleep()

       Just be sure to wrap it in an appropriately named method:

 • sleepAsALastResortWhenNothingElseWorks()
 • sleepToMakeThisTestMoreFlakyThusEnsuringMyJobSecurity()
 • sleepBecauseImTooLazyToSolveThisProperly()




Wednesday, 06 April, 2011
Use The Wait Class


                        ...to delay the test until the app exhibits
                        certain behavior rather than waiting for an
                        arbitrary amount of time.




Wednesday, 06 April, 2011
Two Options

                    1. Subclass DefaultSelenium and override the
                       click() method
                    2. Extract a BaseComponent class that
                       provides a click() method for use by all
                       subclasses




Wednesday, 06 April, 2011
Next Issue


                        The element is present in the DOM, but
                        doesn't contain the right data yet.




Wednesday, 06 April, 2011
Cleanest Solution


                             Build the app for testability




Wednesday, 06 April, 2011
Next Best Solution

         public IssueDetail addComment() {
               int initialCount = getCommentCount();
               selenium.type(locator.of(“.comment-entry”));
               selenium.click(locator.of(“.add-comment”));
               waitUntilCommentCountIs(initialCount + 1);
               return this;
       }




Wednesday, 06 April, 2011
Final Thoughts


                              Beyond “Beyond”?




Wednesday, 06 April, 2011
Thank You!


                             http://electronicingenuity.com
                            dante@electronicingenuity.com
                                     @dantebriones




Wednesday, 06 April, 2011
References

                    •       Dan North on Best Practices:

                            •   http://www.viddler.com/explore/kvarnhammar/videos/6/

                    •       Adam Goucher on built-in test synchronization:

                            •   http://saucelabs.com/blog/index.php/2011/02/advanced-selenium-
                                synchronization-with-latches/




Wednesday, 06 April, 2011

Más contenido relacionado

Destacado

Сергей Татаринцев — Тестирование CSS-регрессий с Gemini
Сергей Татаринцев — Тестирование CSS-регрессий с GeminiСергей Татаринцев — Тестирование CSS-регрессий с Gemini
Сергей Татаринцев — Тестирование CSS-регрессий с Gemini
Yandex
 
Hybrid framework for test automation
Hybrid framework for test automationHybrid framework for test automation
Hybrid framework for test automation
srivinayak
 

Destacado (20)

Better Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component PatternBetter Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component Pattern
 
Better Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component PatternBetter Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component Pattern
 
Automation Abstraction Layers: Page Objects and Beyond
Automation Abstraction Layers: Page Objects and BeyondAutomation Abstraction Layers: Page Objects and Beyond
Automation Abstraction Layers: Page Objects and Beyond
 
BDD Anti-patterns
BDD Anti-patternsBDD Anti-patterns
BDD Anti-patterns
 
Perils of Page-Object Pattern
Perils of Page-Object PatternPerils of Page-Object Pattern
Perils of Page-Object Pattern
 
Specifications For Enterprise Testing
Specifications For Enterprise TestingSpecifications For Enterprise Testing
Specifications For Enterprise Testing
 
Specification by Example
Specification by ExampleSpecification by Example
Specification by Example
 
Refactoring page objects The Screenplay Pattern
Refactoring page objects   The Screenplay Pattern Refactoring page objects   The Screenplay Pattern
Refactoring page objects The Screenplay Pattern
 
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...
 
Сергей Татаринцев — Тестирование CSS-регрессий с Gemini
Сергей Татаринцев — Тестирование CSS-регрессий с GeminiСергей Татаринцев — Тестирование CSS-регрессий с Gemini
Сергей Татаринцев — Тестирование CSS-регрессий с Gemini
 
Page object with selenide
Page object with selenidePage object with selenide
Page object with selenide
 
CukeUp 2016 Agile Product Planning Workshop
CukeUp 2016 Agile Product Planning WorkshopCukeUp 2016 Agile Product Planning Workshop
CukeUp 2016 Agile Product Planning Workshop
 
Hybrid automation framework
Hybrid automation frameworkHybrid automation framework
Hybrid automation framework
 
Serenity-BDD training
Serenity-BDD trainingSerenity-BDD training
Serenity-BDD training
 
Estimation techniques and software metrics
Estimation techniques and software metricsEstimation techniques and software metrics
Estimation techniques and software metrics
 
Out of box page object design pattern, java
Out of box page object design pattern, javaOut of box page object design pattern, java
Out of box page object design pattern, java
 
Design patterns in web testing automation with WebDriver
Design patterns in web testing automation with WebDriverDesign patterns in web testing automation with WebDriver
Design patterns in web testing automation with WebDriver
 
Hybrid framework for test automation
Hybrid framework for test automationHybrid framework for test automation
Hybrid framework for test automation
 
Moving Towards Zero Defects with Specification by Example
Moving Towards Zero Defects with Specification by ExampleMoving Towards Zero Defects with Specification by Example
Moving Towards Zero Defects with Specification by Example
 
Hybrid framework
Hybrid frameworkHybrid framework
Hybrid framework
 

Similar a Beyond Page Objects

Using+javascript+to+build+native+i os+applications
Using+javascript+to+build+native+i os+applicationsUsing+javascript+to+build+native+i os+applications
Using+javascript+to+build+native+i os+applications
Muhammad Ikram Ul Haq
 
Koss, How to make desktop caliber browser apps
Koss, How to make desktop caliber browser appsKoss, How to make desktop caliber browser apps
Koss, How to make desktop caliber browser apps
Evil Martians
 
Milkyway@home rcos presentation_4_8_2011
Milkyway@home rcos presentation_4_8_2011Milkyway@home rcos presentation_4_8_2011
Milkyway@home rcos presentation_4_8_2011
mskmoorthy
 

Similar a Beyond Page Objects (20)

Using+javascript+to+build+native+i os+applications
Using+javascript+to+build+native+i os+applicationsUsing+javascript+to+build+native+i os+applications
Using+javascript+to+build+native+i os+applications
 
What's Cooking in Xtext 2.0
What's Cooking in Xtext 2.0What's Cooking in Xtext 2.0
What's Cooking in Xtext 2.0
 
Node js techtalksto
Node js techtalkstoNode js techtalksto
Node js techtalksto
 
Namesmatter
NamesmatterNamesmatter
Namesmatter
 
HTML5 and jQuery for Flex Developers
HTML5 and jQuery for Flex DevelopersHTML5 and jQuery for Flex Developers
HTML5 and jQuery for Flex Developers
 
Javascript Unit Testting (PHPBenelux 2011-05-04)
Javascript Unit Testting (PHPBenelux 2011-05-04)Javascript Unit Testting (PHPBenelux 2011-05-04)
Javascript Unit Testting (PHPBenelux 2011-05-04)
 
Atlassian RoadTrip 2011 Slide Deck
Atlassian RoadTrip 2011 Slide DeckAtlassian RoadTrip 2011 Slide Deck
Atlassian RoadTrip 2011 Slide Deck
 
Koss, How to make desktop caliber browser apps
Koss, How to make desktop caliber browser appsKoss, How to make desktop caliber browser apps
Koss, How to make desktop caliber browser apps
 
Javascript Views, Client-side or Server-side with NodeJS
Javascript Views, Client-side or Server-side with NodeJSJavascript Views, Client-side or Server-side with NodeJS
Javascript Views, Client-side or Server-side with NodeJS
 
You're doing it wrong
You're doing it wrongYou're doing it wrong
You're doing it wrong
 
Milkyway@home rcos presentation_4_8_2011
Milkyway@home rcos presentation_4_8_2011Milkyway@home rcos presentation_4_8_2011
Milkyway@home rcos presentation_4_8_2011
 
Notebook
NotebookNotebook
Notebook
 
Future-proofing Your JavaScript Apps (Compact edition)
Future-proofing Your JavaScript Apps (Compact edition)Future-proofing Your JavaScript Apps (Compact edition)
Future-proofing Your JavaScript Apps (Compact edition)
 
High quality iOS development
High quality iOS developmentHigh quality iOS development
High quality iOS development
 
Discussing Java's Future
Discussing Java's FutureDiscussing Java's Future
Discussing Java's Future
 
Himanshu pbe
Himanshu pbeHimanshu pbe
Himanshu pbe
 
Accessibility Lightning Talk
Accessibility Lightning TalkAccessibility Lightning Talk
Accessibility Lightning Talk
 
Desacoplando aplicaciones
Desacoplando aplicacionesDesacoplando aplicaciones
Desacoplando aplicaciones
 
A new world with cdi en
A new world with cdi enA new world with cdi en
A new world with cdi en
 
YOU WILL REGRET THIS
YOU WILL REGRET THISYOU WILL REGRET THIS
YOU WILL REGRET THIS
 

Último

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Último (20)

MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 

Beyond Page Objects

  • 1. Beyond Page Objects Dante Briones SeleniumConf 5 April 2011 http://electronicingenuity.com dante@electronicingenuity.com @dantebriones Wednesday, 06 April, 2011
  • 2. Let’s Start With A Story Wednesday, 06 April, 2011
  • 3. A long time ago* in an investment bank far, far away... *(2005) Wednesday, 06 April, 2011
  • 6. A New Weapon Wednesday, 06 April, 2011
  • 8. Victory MUCH more readable! Wednesday, 06 April, 2011
  • 9. What’s The Moral? (hint: it’s not about the developer, the author, or the book) Wednesday, 06 April, 2011
  • 14. Tests Are Code They need TLC Wednesday, 06 April, 2011
  • 15. Readability selenium.click(“id=itemAction1138”); assertEquals(“1”, selenium.getText(“css=#cart .count”)); vs. item.clickAddToCart(); assertEquals(1, cart.getItemCount()); Wednesday, 06 April, 2011
  • 16. Stay DRY Test class: selenium.click(“id=zoom_out_action”); selenium.click(“id=zoom_out_action”); vs. Test class: map.zoomOut(); map.zoomOut(); Map class: selenium.click(“id=zoom_out_action”); Wednesday, 06 April, 2011
  • 17. Robustitude Thread.sleep(250); //wait for button to appear selenium.click(“id=a_button”); Thread.sleep(500); //wait for results to show up assertEquals(selenium.getText(“id=results”), “False Negatives suck!”); Wednesday, 06 April, 2011
  • 18. Sensible Names • catalogItem.addToCart() • blogEntry.post() • auction.bid(25.00) Wednesday, 06 April, 2011
  • 20. How Do We Get There? • Refactoring • Apply Design Patterns • Continuous Improvement Wednesday, 06 April, 2011
  • 21. How Do We Get There? Wednesday, 06 April, 2011
  • 22. Context • Several consulting gigs over the past few years • Current client: • consumer-facing RIA • tests written with Selenium 1 API in Java Wednesday, 06 April, 2011
  • 23. PRO TIP Use WebDriver Wednesday, 06 April, 2011
  • 24. Page Objects Recap • Model the application’s UI • Expose methods that reflect the things a user can see and do on that page • Hides the details of telling the browser how to do those things Wednesday, 06 April, 2011
  • 25. Page Object Benefits • Readable tests • Reduced or eliminated duplication • Self-verification • Reusability Wednesday, 06 April, 2011
  • 26. So Why Go “Beyond”? Web Apps Are Different Now Wednesday, 06 April, 2011
  • 27. Why Go “Beyond”? meh OMG SOOO MUCH BETTER Wednesday, 06 April, 2011
  • 29. Why Go “Beyond”? Because modern web apps are dynamic and rich Wednesday, 06 April, 2011
  • 32. Modeling The UI public class IssueSummary { public IssueDetail expand() {...} } public class IssueDetail { public void save() {...} public void cancel() {...} public String getStoryId() {...} } Wednesday, 06 April, 2011
  • 33. What’s This, Then? I call them “Page Components” Wednesday, 06 April, 2011
  • 34. Method Chaining: Focus Stays Put public class IssueDetail { public void save() {...} public IssueDetail addComment(String comment) { ... return this; } } issueDetail.addComment().save(); Wednesday, 06 April, 2011
  • 35. Method Chaining: Focus Moves Elsewhere public class IssueDetail { public ConfirmationDialog delete() { ... return new ConfirmationDialog(); } } issueDetail.delete().confirm(); or issueDetail.delete().cancel(); Wednesday, 06 April, 2011
  • 36. Page Component Recap • Just like Page Objects... but littler • Use return types to model the user experience Wednesday, 06 April, 2011
  • 37. ComponentFactory Do you like to type? I don’t. Wednesday, 06 April, 2011
  • 38. ComponentFactory 1/(keystrokes Job Satisfaction = required write useful code) Wednesday, 06 April, 2011
  • 39. ComponentFactory public class ComponentFactory { public IssueSummary issueSummary() { return new IssueSummary(...); } } public abstract BaseTestCase { protected ComponentFactory withComponent() { return new ComponentFactory(); } } Wednesday, 06 April, 2011
  • 40. ComponentFactory new IssueSummary(selenium).expand(); vs. withComponent().issueSummary().expand(); Wednesday, 06 April, 2011
  • 41. ComponentFactory Recap • Interactive documentation • Easier entry point into component creation • Another way to use strong typing to make the tests easier to write Wednesday, 06 April, 2011
  • 43. Indexed Components IssueSummary summary = withComponent().backlog().issueSummary(0); assertEquals(summary.getTitle(), “some title”); Wednesday, 06 April, 2011
  • 44. Indexed Components CSS locators: Backlog = #backlog First issue summary = #backlog .issue-summary:nth(0) “Expand” button = #backlog .issue-summary:nth(0) .expand Title = #backlog .issue-summary:nth(0) .title Wednesday, 06 April, 2011
  • 45. The Locator Class public class Locator { protected int index; public Locator(String rootLocator, int index) { this.rootLocator = rootLocator; this.index = index; } public String of(String containedElement) { return String.format(rootLocator, index) + " " + containedElement; } } Wednesday, 06 April, 2011
  • 46. Using A Locator public IssueDetail expand() { selenium.click(“#backlog .issue-summary:nth(0) .expand”); ... } vs. public IssueDetail expand() { selenium.expand(locator.of(“.expand”)); ... } Wednesday, 06 April, 2011
  • 47. Synchronization Issues Two kinds: 1. Element not present yet 2. Element content not updated yet Wednesday, 06 April, 2011
  • 48. Thread.sleep() NO.* STEP AWAY FROM THE KEYBOARD. Wednesday, 06 April, 2011
  • 49. Thread.sleep() NO.* STEP AWAY FROM THE KEYBOARD. (*unless you have no other choice) Wednesday, 06 April, 2011
  • 50. Thread.sleep() Just be sure to wrap it in an appropriately named method: Wednesday, 06 April, 2011
  • 51. Thread.sleep() Just be sure to wrap it in an appropriately named method: • sleepAsALastResortWhenNothingElseWorks() Wednesday, 06 April, 2011
  • 52. Thread.sleep() Just be sure to wrap it in an appropriately named method: • sleepAsALastResortWhenNothingElseWorks() • sleepToMakeThisTestMoreFlakyThusEnsuringMyJobSecurity() Wednesday, 06 April, 2011
  • 53. Thread.sleep() Just be sure to wrap it in an appropriately named method: • sleepAsALastResortWhenNothingElseWorks() • sleepToMakeThisTestMoreFlakyThusEnsuringMyJobSecurity() • sleepBecauseImTooLazyToSolveThisProperly() Wednesday, 06 April, 2011
  • 54. Use The Wait Class ...to delay the test until the app exhibits certain behavior rather than waiting for an arbitrary amount of time. Wednesday, 06 April, 2011
  • 55. Two Options 1. Subclass DefaultSelenium and override the click() method 2. Extract a BaseComponent class that provides a click() method for use by all subclasses Wednesday, 06 April, 2011
  • 56. Next Issue The element is present in the DOM, but doesn't contain the right data yet. Wednesday, 06 April, 2011
  • 57. Cleanest Solution Build the app for testability Wednesday, 06 April, 2011
  • 58. Next Best Solution public IssueDetail addComment() { int initialCount = getCommentCount(); selenium.type(locator.of(“.comment-entry”)); selenium.click(locator.of(“.add-comment”)); waitUntilCommentCountIs(initialCount + 1); return this; } Wednesday, 06 April, 2011
  • 59. Final Thoughts Beyond “Beyond”? Wednesday, 06 April, 2011
  • 60. Thank You! http://electronicingenuity.com dante@electronicingenuity.com @dantebriones Wednesday, 06 April, 2011
  • 61. References • Dan North on Best Practices: • http://www.viddler.com/explore/kvarnhammar/videos/6/ • Adam Goucher on built-in test synchronization: • http://saucelabs.com/blog/index.php/2011/02/advanced-selenium- synchronization-with-latches/ Wednesday, 06 April, 2011