Getting Started with Germanium II
The 2nd part of our 3 part series in which we’ll explore how to get started in using germanium. We’ll assume the only thing you have is python and a browser, and we’ll go from writing the first test, to integrating the test suite in a CI/CD system, in our case Jenkins.
This series is broken down into:
Test structure with behave
Now that we got the first test running, we will need to create quite a few of them. As the system would grow, the test complexities might follow if you’re not paying attention.
Separate selectors in their own
This is why the recommendation is to break down the UI components into their
own file. We’ll call that file
selectors.py. In this file we will define the
UI components with which the test is interacting. For this we will create
functions that will return the selectors defining a vocabulary for our
In it we would have things such as
etc. depending on what components are in the application.
Let’s go forward with the google sample. We would create a selector for the input:
from germanium.static import * def GoogleInput(): return InputText("q")
This decoupling allows us to be resilient to changes in the future. If the upstream developers decide to change the input selector, we still can use the awesome positional finding capabilities:
def GoogleInput(): return Element("input").below(Text("Search for:"))
All the description of the
GoogleInput, and how we find it are nicely packaged
This also means we can relate various UI components together, including in finding. For example we could have a component such as:
def DialogCloseButton(): return Button().inside(ModalDialogHeader)
Button comes from Germanium,
ModalDialogHeader is just another
function that will return a new selector.
Use the Germanium interaction APIs
Now we can interact with it, leveraging the Germanium’s input API, using its component’s custom name:
In the ever changing APIs from Selenium, Germanium is built with backwards
compatibility in mind. You can
type_keys including using keyboard shortcuts,
in a simple, sane API.
The format is also made so you can just stream your keys from your behave test directly into the API, without having action builders and other nonsense:
Scenario: Test cleaning the input works correctly. Given I have a value in the custom input spinner that is not '11' When I type in the custom input spinner '<ctrl-a><del>11<enter>' Then the value in the custom input spinner is '11'
The step implementation can then be just:
def type_in_custom_spinner(context, keys): type_keys(CustomSpinner, keys)
In this article we learned that we should:
Have all the UI components selectors into a single file, using functions to fetch them.
Use the Germanium interaction APIs in the step implementations.
Article Photo taken from Pexels: https://www.pexels.com/photo/assorted-color-great-board-decor-lot-1539581/