The pattern
Guará is the Python implementation of the design pattern Page Transactions. It is more of a programming pattern than a tool. As a pattern, it can be bound to any driver other than Selenium including the ones used to Linux, Window and Mobile automation.

The intent of this pattern is to simplify test automation. It was inspired by Page Objects, App Actions, and Screenplay. Page Transactions focus on the operations (transactions) a user can perform on an application, such as Login, Logout, or Submit Forms.

This initiative was born to improve the readability, maintainability and flexibility of automation testing code without the need for new automation tools or the necessity of many abstractions to build human-readable statements. Another concern was to avoid binding the framework to specific automation tools, like Selenium, leaving the testers free to choose their preferred ones. No new plugin nor new knowledge is required to start using Guará with Helium, Dogtail, RPA Python, Playwright or whatever tool you like or need.

It is worth to say again:

Guará is the Python implementation of the design pattern Page Transactions. It is more of a programming pattern than a tool.

Guará leverages the Command Pattern (GoF) to group user interactions, like pressing buttons or filling texts, into transactions. Despite I’m calling it a framework, it is not a new tool.

Instead of focusing on UI elements like buttons, check boxes or text areas, it emphasizes the user journey. The complexity is abstracted into these transactions, making the test statements feels like plain English. Testers also have the flexibility to extend assertions to custom ones that are not provided by the framework.

The Framework in action
This simple implementation mimics the user switching languages in a Web Page:

from selenium import webdriver
from guara.transaction import Application
from guara import it, setup
import home

def test_language_switch():
app = Application(webdriver.Chrome())

# Open the application
app.at(setup.OpenApp, url="https://example.com/")

# Change language and assert
app.at(home.ChangeToPortuguese).asserts(it.IsEqualTo, "Conteúdo em Português")
app.at(home.ChangeToEnglish).asserts(it.IsEqualTo, "Content in English")

# Close the application
app.at(setup.CloseApp)

Each user transaction is grouped into its own class (e.g., ChangeToPortuguese) which inherits from AbstractTransaction. The tester just has to override the do method and the framework does the work.

from guara.transaction import AbstractTransaction

class ChangeToPortuguese(AbstractTransaction):
def do(self, *kwargs):
self._driver.find_element(By.CSS_SELECTOR, ".btn-pt").click()
return self._driver.find_element(By.CSS_SELECTOR, ".content").text
The tester can check the the transactions and assertions in the logs after run the tests:

test_demo.py::test_language_switch
2025-01-24 21:07:10 INFO Transaction: setup.OpenApp
2025-01-24 21:07:10 INFO url: https://example.com/
2025-01-24 21:07:14 INFO Transaction: home.ChangeToPortuguese
2025-01-24 21:07:14 INFO Assertion: IsEqualTo
2025-01-24 21:07:14 INFO Actual Data: Conteúdo em Português
2025-01-24 21:07:14 INFO Expected: Conteúdo em Português
2025-01-24 21:07:14 INFO Transaction: home.ChangeToEnglish
2025-01-24 21:07:14 INFO Assertion: IsEqualTo
2025-01-24 21:07:14 INFO Actual Data: Content in English
2025-01-24 21:07:14 INFO Expected: Content in English
2025-01-24 21:07:14 INFO Transaction: setup.CloseApp
The tester can also use fixtures like setup and tear down to initiate and finish the tests. Remember, it is not a new tool, so you can use pytest or unittesting features without any problem.