DEV Community

Cover image for Test Automation With Python
Loadero
Loadero

Posted on • Originally published at blog.loadero.com

Test Automation With Python

According to IEEE Spectrum Python is the top programming language of 2021, and since April Loadero supports Python as a test script language. Many engineers agree that test automation with Python is an excellent choice, and in this blog post, we’ll show the basics of it.

Python tests in Loadero use the Py-TestUI framework. Py-TestUI wraps and implements additional features for Selenium Python binding. This means that Loadero Python tests can utilize the full power of Selenium and other cool features provided by Py-TestUI.

Test Structure

Every Python test starts with

def test_on_loadero(driver: TestUIDriver) -> None:
Enter fullscreen mode Exit fullscreen mode

This function is like the main function in other programming languages. It will be called once the test execution is started. All of the test logic must originate from this function. This means that additional functions outside of the test_on_loadero function can be added, but they must be called from the test_on_loadero function to have any effect.

Driver

Loadero tests automate browser interactions as if they were done by a human to allow for repeated execution, parallel tests, and scale-up for load testing. Tests can do almost any action that a human can in a browser, for example:

  • Navigate to URL
  • Click on links and elements
  • Input text
  • Copy text

These actions are achieved in a test with the driver object. driver wraps the workhorse of the browser test – Selenium WebDriver and is of type TestUIDriver. TestUIDriver implements commonly used browser interactions to improve ease of use but at the same time allows to access the underlying Selenium WebDriver for more complex browser interactions.

driver object is initialized and configured at the start of every test and passed as an argument to the test_on_loadero function.

Let’s look at common browser interactions and how to implement them in a test script.

Navigation

To start interacting with a web page, it first has to be opened. To do that call the following method

TestUIDriver.navigate_to(url: str) -> None
Enter fullscreen mode Exit fullscreen mode

Argument url is the URL of a web page to open.
Here is a simple test that demonstrates the usage of navigate_to.

def test_on_loadero(driver: TestUIDriver) -> None:
    driver.navigate_to("https://duckduckgo.com/")
    driver.save_screenshot("duckduckgo.png")
Enter fullscreen mode Exit fullscreen mode

Additionally, the test calls

TestUIDriver.save_screenshot(image_name: str) -> str
Enter fullscreen mode Exit fullscreen mode

This method will, as the name implies, capture the state of the browser at the moment of the save_screenshot method call and save it with the name supplied by image_name argument. After the test finishes execution, all screenshots taken during the test will be available in the artifacts tab in the Loadero result page of a single test participant.

Tip: Taking screenshots during a test is a common practice that helps test debugging or manually reviewing what was on the test participant’s screen at the important stages of your test.

Clicks

A very fundamental browser interaction is the click. To interact with an element it first has to be located with the e method.

TestUIDriver.e(locator_type: str, locator: str) -> Elements:
Enter fullscreen mode Exit fullscreen mode

locator_type argument describes the location method of an element and can have values:

  • css – locate element by CSS selector
  • name – locate element by name
  • className – locate the element by its class name
  • xpath – locate element by XPath

locator – describes how to locate the element with the location method set by locator_type argument. To learn more about using CSS selectors and XPath locators in your Selenium test automation scripts make sure to read this blog post.

An attentive reader might have noticed that e method has return type Elements – plural, but I have been using elements in a singular form so far. This is because Elements object has more advanced features (for example – locating multiple elements at once, image matching) that this blog post does not cover. So in an attempt not to confuse the reader these topics will be skipped.

After locating the desired element it can be clicked on with the click method.

Elements.click() -> Elements:
Enter fullscreen mode Exit fullscreen mode

There is nothing in the way for calling click right after an element has been located, but a good practice is to check if the element is visible with a runtime assertion before clicking on it. If the element is visible then it has had enough time to load and can be interacted with. Doing this allows avoiding test failures caused by attempting to click on an element that has not loaded yet. We use a lot in tests we create for our customers and advise you to do the same.

wait_until_visible method does as the name suggests – waits for the element to load and become visible before attempting further interactions.

Elements.wait_until_visible(seconds=10.0, log=True) -> Elements:
Enter fullscreen mode Exit fullscreen mode

Argument seconds with a default value of 10.0 specifies the amount of time the test will wait until the element becomes visible. If the element is not visible after waiting the specified time an error will be raised and the test will fail.

Argument log with a default value True specifies whether to log the result of the wait_until_visible method call. This argument generally should not be changed and can be ignored. Many Elements methods have a log argument and it can be ignored in all of them.

Here is a simple test script showcasing everything shown so far. You can put everything learned so far to test with Loadero’s free trial. You can also find the script example in Loadero’s Github repository.

def test_on_loadero(driver: TestUIDriver) -> None:
    # Opens the search engine DuckDuckGo with default search query of
    # google.com
    driver.navigate_to("https://duckduckgo.com/?q=google.com")
    # Locates an element with a CSS selector that is pointing to the first
    # search results title, waits for the element to become visible and clicks
    # on it.
    driver.e("css", "#r1-0 > div > h2").wait_until_visible().click()
    # Ensures that the web page has loaded before taking a screenshot.
    driver.e("css", "body > div:first-of-type").wait_until_visible()
    driver.save_screenshot("google.png")
Enter fullscreen mode Exit fullscreen mode

Input Text

The previous test script example was cheating a bit. Realistically a human user would insert the search query “google.com” themselves and wouldn’t be using a specially prepared URL. To simulate this behavior, tests can input text with the .send_keys method.

Elements.send_keys(value: str, log=True) -> Elements:
Enter fullscreen mode Exit fullscreen mode

value argument specifies the text that will be sent to an element.
To clear the input value that was set by send_keys or an element has by default use clear method.

Elements.clear() -> None:
Enter fullscreen mode Exit fullscreen mode

Retrieving Content of an element

Browser interactions can be generalized as a feedback loop where the next interaction is determined by the resulting content of a web page. Tests need a way to retrieve the content of a web page or more specifically the content of a single element to implement logic that decides what the next interaction should be. This section will cover the other half of the browser interaction feedback loop – content retrieval.

Most HTML elements have content, with few exceptions like <br> element, that is rendered to the web page and can be interacted with.

To retrieve the textual value of an element use

Elements.get_text() -> str:
Enter fullscreen mode Exit fullscreen mode

Putting Everything Learned To Use

It’s time to combine all the commands we have described in a single test automation script. This script example performs a search for a specific query on the DuckDuckGo search engine and prints out the top results.

def test_on_loadero(driver: TestUIDriver) -> None:
    # The main logic of the test is in top_search_results function
    print(top_search_results(driver, "loadero", 10))
# top_search_results returns the top n search results for search_query.
def top_search_results(driver: TestUIDriver, search_query: str, n: int) -> str:
    # Limits the search result count to 10, because a single search query in
    # DuckDuckGo search engine returns only 10 results.
    n = min(n, 10)
    # Selectors.
    home_page_search_bar = "#search_form_input_homepage"
    home_page_search_button = "#search_button_homepage"
    # Opens the search engine DuckDuckGo.
    driver.navigate_to("https://duckduckgo.com/")
    # Locates search bar, waits for the element to load and sends a search query
    # to it
    driver.e("css", home_page_search_bar).wait_until_visible().send_keys(
        search_query
    )
    # Locates search button, verifies that it is visible and clicks it.
    driver.e("css", home_page_search_button).wait_until_visible().click()
    result = f"Top {n} DuckDuckGo search results for {search_query} ->\n"
    # Iterates over top n search results
    for i in range(n):
        # Creates a CSS selector that indicates to the search result title.
        selector = f"#r1-{i} > div > h2 > a.result__a"
        # Locates the search element and verifies that it is visible.
        search_result_element = driver.e("css", selector).wait_until_visible()
        # Retrives the title of search result and adds it to result string.
        title = search_result_element.get_text()
        result += f"\t {title} \n"
    return result
Enter fullscreen mode Exit fullscreen mode

You can find the output of this test script in Loadero’s single participants result pages logs tab under Selenium log. The output would log something like this:

Top 10 DuckDuckGo search results for loadero ->
     Loadero - Performance and Load Testing Tool
     Loadero | LinkedIn
     Loadero Pricing, Alternatives & More 2022 - Capterra
     Loadero - Home | Facebook
     GitHub - loadero/examples: Test script examples that are ...
     Loadero - YouTube
     Loadero - your performance & load testing partner from the ...
     Application Load Testing Tools for API Endpoints with ...
     Tractors - Tractor Loader Backhoe - B26 | Kubota
     EZ Loader TMS | EZ Loader TMS
Enter fullscreen mode Exit fullscreen mode

We covered the basics of working on test automation with Python. You can create a test similar to what we described and run it multiple times free of charge with Loadero’s free trial. To continue learning to use Python for your tests in Loadero make sure to visit our Wiki, where you can find information about custom commands that extend the functionality WebDriver and PyTestUI, variables that hold the relevant information about the test participant, and more script examples of test automation with Python. We will be glad to see you back again.

Top comments (0)