How test the Web UI for Anvil Apps

We’re using Anvil to create simple web apps to control devices using API’'s.

We use CI/CD pipelines to build and test our work and deploy to docker containers

We need to test the UI’s and how they interact with the server back and device, we would normally use Selenium to do this.

Is anyone else doing something similar and what tools are you using? Anvil people, I assume you do this internally as part of your CI/CD process, can you share anything?

I use pytest/selenium to set up a test infrastructure for my UI.

It was built off of this example:

Although , it doesn’t work out of the box, you’ll have to do some tweaking. But it was a great start and saved me loads of time.

2 Likes

thanks, pointed the team at it, they were having issues getting unique id’s or xpaths to elements in pages with multiple instances of controls.

You may want to also take a look at Playwright: https://playwright.dev/

It seems to me to be a step forward from Selenium.

In Best Practices | Playwright they propose to use user-facing attributes like text on a button over ids and xpath.

2 Likes

Love newer better tools… Thanks for the rec!

Popping in to give double thanks to @stein.

Started using playwright and it is so smooth and easy. Great tool.

1 Like

Popping back in to answer this question, which got kinda lost in the follow-up:

This can be solved straightforwardly, by using anvil.js to put identifying IDs or classes onto particular components in your __init__ method. (This is the approach I mentioned here, which got refined into a scary but effective monkey-patch for every instance of the Component class here)

Here’s how it works:

anvil.js.get_dom_node(target_component).classList.add("some-class")

or

anvil.js.get_dom_node(target_component).id = "something-meaningful"

Or you can even find and target elements within components. For example, to target the <button> element inside a Button component:

from anvil.js import get_dom_node, window

# Find the component:
node = window.jQuery(get_dom_node(self.button_1))
# Tag the actual <button> element that component:
node.find("button").attr("id", "something-meaningful")
1 Like