On The Road To Abstraction II
Continuing the previous article with concrete code examples of the ultimate automation achievable in the Germanium stack (Selenium, WebDriver, Germanium, Behave).
Let’s imagine the common automation scenario:
Load a web page into a web editor like CKEditor
Wait for the load to finish; now you can perform browser actions like:
Click a visual widget on the page
Wait for completion of an action (like a click)
Type text at the mouse pointer location
Move the mouse pointer
Left-click the mouse left button
Right-click the mouse right button
Scroll the mouse wheel up or down
Select a region with hold-down left mouse button, movement of the mouse, and release the hold-down
These are all very low-level actions needing a raise of consciousness via abstraction.
The ugly words “click”, “wait” and so on for the others don’t contain any intrinsic abstract value indicating the foggiest notion of what they do. So, we want to replace them meaningfully in a different language and keep their effect the same:
Click becomes “perform” or “do”.
Wait is ok as is. Leave it “wait”.
The other elementary mouse action verbs above can similarly be abstracted. We’ll focus on the first two: click, wait.
If the different language reads like English, with entire sentences which can have placeholders for string parameters, then a test becomes understandable, at least somewhat.
Structuring the Test Code
We need to structure our group of English sentences into an executable set of 1 or more scenarios. Every sentence is a step that we must implement in a Germanium supported language, like Python or Java.
Since each action that a sentence implies can vary quite a bit, we need to group our step implementations into logical units. Each unit will contain Python (let’s say) functions or classes of steps that are somewhat similar in character and function. There may be some variation in the steps within a logical unit, but they are grouped together because of related functionality.
Python has modules. So, we implement our logical units into modules containing related Python functions and classes.
It would be convenient to have a framework that glues all these things together, making them run smoothly, and if not, indication what went wrong during execution.
There is such a framework already, Behave, which is what was introduced very briefly in the last few bullet items.
So, in what follows, an example excerpt of an automated Germanium Behave test will be discussed.
This is what it looks like at top level:
Feature: NIP-1 regression test. This test checks that nested insertion points works. Scenario: Test inserting nested building blocks. Given in Composer I open template 'cp/nip2/nested-ip/n3.itx' with 'cp/nip2/nested-ip/x3.xml' xml data, and 'cp/nip2/nested-ip/n3.idx' target document And I wait for the editor to load And I click the insertion point handle "int_IP_1" And I wait for the navibar to open And I wait for the building block definitions to load
This is only an excerpt. It starts creating a document by inserting building blocks (paragraphs, for example) which are nested. Assertions could be made but here are left out. This is an excerpt of a behave feature file. In the next blog post, we’ll drill down to each Python step that is executed.
Article Photo taken from Pexels: https://www.pexels.com/photo/road-landscape-nature-forest-39811/