Framework to build UI test automation in Page Transactions pattern
Project description
Guará
Photo by Mateus Campos Felipe on Unsplash
The scarlet ibis, sometimes called red ibis (Eudocimus ruber), is a species of ibis in the bird family Threskiornithidae. It inhabits tropical South America and part of the Caribbean. In form, it resembles most of the other twenty-seven extant species of ibis, but its remarkably brilliant scarlet coloration makes it unmistakable. It is one of the two national birds of Trinidad and Tobago, and its Tupi–Guarani name, guará, is part of the name of several municipalities along the coast of Brazil.
Guará is an implementation of the Page Transactions pattern. The intent of this pattern is to simplify UI test automation. It was inspired by Page Objects, App Actions, and Screenplay. Page Transactions focus on the operations (transactions) a user can perform on a web page, such as Login, Logout, or Submit Forms. The idea is to group blocks of interactions into classes. These classes inherit from AbstractTransaction and override the do method.
Each transaction is passed to the Application instance, which provides the methods at and asserts. These are the only two methods necessary to orchestrate the automation. While it is primarily bound to Selenium WebDriver, experience shows that it can also be used to test REST APIs and unit tests, for example (check the tests folder).
Here is the base implementation of the framework:
from typing import Any, NoReturn
from selenium.webdriver.remote.webdriver import WebDriver
from guara.it import IAssertion
class AbstractTransaction:
def __init__(self, driver: WebDriver):
self._driver = driver
def do(self, **kwargs) -> Any | NoReturn:
raise NotImplementedError
class Application:
def __init__(self, driver):
self._driver = driver
@property
def result(self):
return self._result
def at(self, transaction: AbstractTransaction, **kwargs):
self._result = transaction(self._driver).do(**kwargs)
return self
def asserts(self, it: IAssertion, expected):
it().asserts(self._result, expected)
return self
-
AbstractTransaction: This is the class from which all transactions inherit. Thedomethod is implemented by each transaction. In this method, calls to WebDriver are placed. If the method returns something, like a string, the automation can use it for assertions. -
Application: This is the runner of the automation. It executes thedomethod of each transaction and validates the result using theassertsmethod.- The
assertsmethod receives a reference to anIAssertioninstance. It implements theStrategy Patternto allow its behavior to change at runtime. - Another important component of the
Applicationis theresultproperty. It holds the result of the transaction, which can be used byassertsor inspected by the test using the native built-inassertmethod.
- The
-
IAssertion: This is the interface implemented by all assertion classes.- The
assertsmethod of each subclass contains the logic to perform validations. For example, theIsEqualTosubclass compares theresultwith the expected value provided by the tester. - Testers can extend this interface to add new validations that the framework does not natively support.
- The
When the framework is in action, it follows a highly repetitive pattern. Notice the use of the at method to invoke transactions and the asserts method to apply assertion strategies. Also, the automation is describe in plain English improving the comprehention of the code.
def test_sample_web_page():
# Instantiates the Application with a driver
app = Application(webdriver.Chrome())
# At setup opens the web application
app.at(setup.OpenApp, url="https://anyhost.com/",)
# At Home page changes the language to Portuguese and asserts its content
app.at(home.ChangeToPortuguese).asserts(it.IsEqualTo, content_in_portuguese)
# Still at Home page changes the language
# to English and uses native assertion to validate the `result`
assert app.at(home.ChangeToEnglish).result == content_in_english
# At Info page asserts the text is present
app.at(info.Navgigate).asserts(
it.Contains, "This project was born"
)
# At setup closes the web application
app.at(setup.CloseApp)
setup.OpenAppandsetup.CloseAppare part of the framework and provide basic implementation to open and close the web application using Selenium Webdriver.
The ugly code which calls the webdriver is like this:
class ChangeToPortuguese(AbstractTransaction):
def __init__(self, driver):
super().__init__(driver)
# Implements the `do` method and returns the `result`
def do(self, **kwargs):
self._driver.find_element(
By.CSS_SELECTOR, ".btn:nth-child(3) > button:nth-child(1) > img"
).click()
self._driver.find_element(By.CSS_SELECTOR, ".col-md-10").click()
return self._driver.find_element(By.CSS_SELECTOR, "label:nth-child(1)").text
Again, it is a very repetivite activity:
- Create a class representing the transaction, in this case, the transaction changes the language to Portuguese
- Inherits from
AbstractTransaction - Implementes the
domethod- Optinonal: Returns the result of the transaction
Read more in Tutorial
Installation
This framework can be installed by
pip install guara
Tutorial
Read the step-by-step to build your first automation with this framework.
Contributing
Read the Code of Conduct before push new Merge Requests. Now, follow the steps in Contributing session.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file guara-0.0.1.tar.gz.
File metadata
- Download URL: guara-0.0.1.tar.gz
- Upload date:
- Size: 823.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
168817a317fc479b32783933c3d685061b7d0b06739ccbd623cf182295b166a2
|
|
| MD5 |
9cd1292f6204b64c2083ef49de5e8d65
|
|
| BLAKE2b-256 |
8f5ed82942ed1f2c38e5dc4a2dd3d7a785e7a08c06d480c85ad9840725d76219
|
File details
Details for the file guara-0.0.1-py3-none-any.whl.
File metadata
- Download URL: guara-0.0.1-py3-none-any.whl
- Upload date:
- Size: 5.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbfa012fec03b1a6408de4f0f394d57f49a2bdaabdacdf0f6d6d5709c3bd4b8e
|
|
| MD5 |
8e04d1ed5cbdc0b7788a5e4d70bbdce8
|
|
| BLAKE2b-256 |
fd61eb334b12fedd83bd2d16f0685bc36854c995da5792d003f3f509739319fd
|