Tutorial for test usage
Canonical implementation
This is the simplest implementation to warm up the framework. It uses the OpenApp and CloseApp transactions to open the web page of Google, to assert the title of the page is Google and to close the web application. More details about each component of the framework are explained in further sessions. First install Selenium with pip install selenium
# test_guara.py
from guara import it
from guara.transaction import Application, AbstractTransaction
from selenium import webdriver
class OpenApp(AbstractTransaction):
def do(
self, url: str,
) -> str:
self._driver.get(url)
return self._driver.title
class CloseApp(AbstractTransaction):
def do(self) -> None:
self._driver.quit()
def test_canonical():
google = Application(webdriver.Chrome())
google.when(OpenApp, url="http://www.google.com",).asserts(it.IsEqualTo,"Google")
google.execute(CloseApp)
Basic practical example
This is a basic search of the term “guara” on Google. To follow the steps create the files home.py and test_tutorial.py at the same folder.
# home.py
from guara.transaction import AbstractTransaction
from selenium.webdriver.common.by import By
class Search(AbstractTransaction):
def __init__(self, driver):
super().__init__(driver)
def do(self, text):
# Sends the received text to the textbox in the UI
self._driver.find_element(By.NAME, "q").send_keys(text)
# Click the button to search
self._driver.find_element(By.NAME, "btnK").click()
# Waits the next page appears and returns the label of the first tab "All".
# It will be used by assertions in the next sessions.
return self._driver.find_element(
By.CSS_SELECTOR, ".Ap1Qsc > a:nth-child(1) > div:nth-child(1)"
).text
class Search: is a concrete transaction. Notice that the name of the class is an action and not a noun as usually saw in OOP. It is intentional to make the statement in the test more natural.def __init__: is the same for all transactions. It passes thedriverto theAbstractTransaction.def do: is the ugly implementation of the method. It uses the private attributeself._driverinherited fromAbstractTransactionto callfind_element,send_keys,clickandtextfrom Selenium Webdriver. Notice the parametertext. It is received from the automation viakwargs. More details in further sessions.
# test_tutorial.py
import pytest
# Imports the module with the transactions of the Home page
import home
from selenium import webdriver
# Imports the Application to build and run the automation
from guara.application import Application
# Imports the module with the strategies to asset the result
from guara import it
@pytest.fixture
def google():
# Instantiates the Application to run the automation
google = Application(webdriver.Chrome())
# Some interesting things happen here.
# The framework is used to setup the web application.
# The method `at` from `app` is the key point here as it
# receives a transaction (AbstractTransaction) and its `kwargs`.
# Internally `at` executes the `do` method of the transaction and
# holds the result in the property `result` which is going to be
# presented soon.
# `OpenApp` is a concrete transaction.
# The `url` is passed to the `at` method by `kwargs`.
# The result returned by `at` is asserted by `asserts`
# using the strategy `it.IsEqualTo`.
google.given(
OpenApp,
url="http://www.google.com",
).then(it.IsEqualTo, "Google")
yield google
# Uses the concrete transaction `CloseApp` to close the web application
google.execute(CloseApp)
def test_google_search(google: Application):
# With the `app` received from the fixture the similar things
# explained previously in the fixture happens.
# The transaction `home.Search` with the parameter `text`
# is passed to `at` and the result is asserted by `asserts` with
# the strategy `it.IsEqualTo`
google.at(home.Search, text="guara").asserts(it.IsEqualTo, "All")
class Application: is the runner of the automation. It receives thedriverand passes it hand by hand to transactions.def at: receives the transaction created onhome.pyand its parameters. Notice the usage of the module namehometo make the readability of the statement as plain English. The parameters are passed explicitly for the same purpose. So thegoogle.at(home.Search, text="guara")is readGoogle at home [page] search [for] text "guara". The termspageandforcould be added to the implementation to make it more explicit, likegoogle.at(homePage.Search, for_text="guara"). This is a decision the tester may make while developing the transactions.def asserts: receives a strategy to compare the result against an expected value. Again, the focus on readability is kept. So,asserts(it.IsEqualTo, "All")can be readasserts it is equal to 'All'it.IsEqualTo: is one of the strategies to compare the actual and the expected result. Other example is theit.Containswhich checks if the value is present in the page. Notice that the assertion is very simple: it validates just one value. The intention here is keep the framework simple, but robust. The tester is able to extend the strategies inheriting fromIAssertion.