A framework for writing maintainable poetry with Selenium WebDriver. Also provides features like reports with screenshots.
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
doc/uml
src
.gitignore
.travis.yml
LICENSE
README.md
deploy.sh
pom.xml
selenium-tinafw.vpp

README.md

selenium-tinafw

A minimal and effective Selenium framework, not a wrapper.

The goal is two-fold:

  • helping manage the mess inherent in a large test suite, by providing a well-defined structure for test code (see WebTask)
  • helping bootstrap a test suite by providing some basic services such as:
    • a factory of WebDriver instances, representing either a local browser or one on a Grid, based on settings in a property file
    • an automatic mechanism to close browsers as soon as a test terminates
    • a mechanism to retry flaky tests
    • test reports with screenshots attached

In order to get an idea of how tests look like by using this framework, please see the sample provided. Start from SampleWebTest, down to the WebTasks (OnMyAboutMePage, Search, CanCompliment), down to page objects (SearchResultsPage, SearchResult, etc.)

Usage

Please see the Tutorial on the wiki.

Features

  • Wraps without wrapping. Selenium WebDriver's API is not hidden in any way. You could virtually access a WebDriver instance from a test class (although you are encouraged not to do so, unless you want to break cohesion). The idea is that Selenium WebDriver has such a beautiful API that it's a shame to hide it.

  • WebTask hierarchy, the orchestrators of page objects:

    • helps keeping your code organized: each concrete WebTask is supposed to be a Given/When/Then step)

    • and highly readable (fluent interface): see e.g. SampleWebTest

    • solves the following problem in an elegant way:

      Given two tasks that run sequentially, the first does something and ends at a certain page. How can the second task know which was the last page the first task was visiting?

      (a naive solution being "every task restarts navigating the SUT from the home page").

  • WebDriverFactory hierarchy: elegant solution solving the problem of creating instances of WebDriver, modeled using the decorator design pattern.

  • BDD-style tests are not only supported but also strongly encouraged. You can write BDD tests by wrapping your own WebTask's in a given when or then task (each of which is a CompositeWebTask). See also WebTasks.BDD Please see SampleWebTest for an example of usage. For an introduction to BDD, please see the article Introducing BDD, by Dan North.

  • HTML reports with embedded screenshots for each failing test, thanks to HtmlReporter

  • the ability to run each test on many different browsers (or just one) by simply setting a property in a file: tinafw.browsers = chrome, firefox

  • the ability to retry a failed test for a given number of times: see TestRetrier

  • an automatic mechanism for closing browsers as soon as a test finishes, as well as the option to disable such a mechanism by setting a property: see BrowserManager

  • a clean directory structure, aka multilayered architecture, with:

    • the tests layer, for keeping your test cases along with their data
    • the domain layer, containing concepts like User and Browser, and supposed to contain the concepts of your own domain as well, e.g. BlogPost, BlogComment
    • the tasks layer, containing the orchestrators of page objects
    • the ui layer, with page objects
  • meaningful logs, e.g.:

      INFO  CompositeWebTask - BEGIN subtask Given
      INFO  CompositeWebTask - BEGIN subtask OnMyAboutMePage
      DEBUG PageHelper$Navigation - Page at URL http://alb-i986.me/ loaded
      INFO  BasePage - Loading page MyAboutMePage
      DEBUG PageHelper - BEGIN Explicit wait (timeout=15s). Waiting until visibility of [[ChromeDriver: chrome on MAC (e8eac3735de18ef7920ce08755d3f6bf)] -> css selector: #profile_box h1.name]
      DEBUG PageHelper - END Explicit wait: visibility of [[ChromeDriver: chrome on MAC (e8eac3735de18ef7920ce08755d3f6bf)] -> css selector: #profile_box h1.name]
      INFO  CompositeWebTask - END subtask OnMyAboutMePage
      INFO  CompositeWebTask - END subtask Given
      INFO  CompositeWebTask - BEGIN subtask When
      INFO  CompositeWebTask - BEGIN subtask Search
      INFO  BasePage - Loading page SearchResultsPage
      DEBUG PageHelper - BEGIN Explicit wait (timeout=15s). Waiting until visibility of [[ChromeDriver: chrome on MAC (e8eac3735de18ef7920ce08755d3f6bf)] -> css selector: #search-results div]
      DEBUG PageHelper - END Explicit wait: visibility of [[ChromeDriver: chrome on MAC (e8eac3735de18ef7920ce08755d3f6bf)] -> css selector: #search-results div]
      INFO  CompositeWebTask - END subtask Search
      INFO  CompositeWebTask - END subtask When
      INFO  CompositeWebTask - BEGIN subtask Then
      INFO  CompositeWebTask - BEGIN subtask CanCompliment
      INFO  CompositeWebTask - END subtask CanCompliment
      INFO  CompositeWebTask - END subtask Then
    

A glimpse of the internals: UML Sequence Diagrams

Open browser SD

Login SD

Design goals

  • small, clean, Object-based API (here, quoting Simon Stewart)
  • not a wrapper
  • high cohesion.
  • flexibility
  • poetry (to be, as well as to allow for)

Requirements

Graphviz is actually optional: it is needed for generating javadocs with pretty cool UML class diagrams (thanks UMLGraph!). So you're not gonna need it unless you want to run mvn site or mvn javadoc:javadoc.

Dependencies

The main dependencies are:

  • selenium-java
  • junit
  • log4j

Please see the POM file for more details.

TODO

  • redesign Config
  • cleanup by leveraging Guice
  • add PageComponent hierarchy
  • make it a data-driven framework