11

Writing a Flutter Web application, I try to leverage a Web-UI-Testing framework based on Selenium. Sadly I fail to identify a HTML-Element representing a certain flutter widget by its id or name attribute. The widget key is not present in the HTML document.

I manage to use Text widget contents to find an widget's text portion and can find its parent element representing the widget containing the text but this fails for images, canvas etc.

Is there any mechanism I can use to add id/name (or any other means of identification) to the HTML tag soup?

Using JavaScript, is there a way to traverse the internal logical widget tree and from there conclude the representing HTML element (for example by its location and size)?

Martin Kersten
  • 5,127
  • 8
  • 46
  • 77
  • Hi @Martin, what exactly are you trying to achieve? Are you trying to use Selenium and cannot reference the item? Or are you modifying the DOM structure / HTML? Any chance you can share some example HTML of what is and what should be? Also, examples of what exactly you are hoping to do? Thank you. – Lefty G Balogh Feb 03 '20 at 13:37
  • 1
    I would like to identify individual HTML elements and the widgets they represent. I want to (easily) end to end test the HTML output of a Flutter Web app the way we are used to do. It is a large part of the requirement for us to switch to Flutter Web. – Martin Kersten Feb 03 '20 at 17:21
  • Maybe you should give a try with [Puppeteer](https://github.com/puppeteer/puppeteer) or [Cypress](https://www.cypress.io/). I've had some hard times using Selenium web driver in the past. – Christos Lytras Feb 03 '20 at 19:35
  • 1
    I checked out the way tests are written under both testing frameworks. Using those I would suffer the same problem. Flutter does not add anything to the HTML to make identifying certain Widgets reliablely possible. – Martin Kersten Feb 04 '20 at 08:57
  • I still find it hard to imagine this whole chaos without any source samples, but I looked into example flutter pages and they are definitely weird. Apologies if you have already looked into it: flutter seems to come with its own recipes for testing: https://flutter.dev/docs/cookbook/testing/widget/finders Does this make any sense to you in your context? – Lefty G Balogh Feb 04 '20 at 09:20
  • Selenium and co worked best with xpath for us. For example, go to https://flutter.github.io/samples/#/, in Categories, Materials, open the Pickers, Click show picker. Inspect the source for the OK button. Copy its full xpath - and feed this to Selenium: `/html/body/flt-glass-pane/flt-scene-host/flt-scene/flt-transform/flt-offset[2]/flt-offset/flt-clip/flt-clip-interior/flt-picture[6]/flt-dom-canvas/p` Can you try and see if this works? – Lefty G Balogh Feb 04 '20 at 09:33
  • 1
    @LeftyGBalogh You are not wrong. Xpath approach will work with selenium as well, but imagine flutter team introducing a new element in between and the whole test suite will require an update unless a wildcard logic is used within the xpath. – Abhilash Chandran Feb 04 '20 at 14:37
  • Sad but true. Though it is not flutter specific. If the document structure changes, it is always a headache. This is why usually you abstract away these into page objects so you only need to update it in one place, methinks. – Lefty G Balogh Feb 04 '20 at 15:34
  • The question is thou, why I can not use a (string) key value and it becomes the id property. Seems like this is a feature request right there. – Martin Kersten Feb 04 '20 at 19:06
  • I am using a different thing than xpath since maintaining a full xpath is cumbersome especially since the chrome inspector is of none help... . (Using Chrome DevTools) I can not even locate the HTML element by clicking at the element since every element in-between is a 0x0 sized element and the use of transforms is just too much for chrome I guess. (Anyone having a solution for that issue?) – Martin Kersten Feb 04 '20 at 19:09
  • May I suggest you join the [discord group](https://discordapp.com/invite/N7Yshp4) and pose this question there. At least you will get a direct response from the development team. – Abhilash Chandran Feb 05 '20 at 07:35
  • @AbhilashChandran I was thinking about filing a feature request as well. I will go over there and ask, thanks for the pointer. – Martin Kersten Feb 05 '20 at 20:13
  • @MartinKersten Can you provide us some hint about where you are exactly stuck? Any sample HTML and locators you have tried? Errors? – undetected Selenium Feb 06 '20 at 15:34
  • Have you managed to find a solution to place some identification data on the generated divs? I'm trying to setup Cypress. There's no way I start using another obnoxious "fancy" wrapper/driver for testing virtual DOM. Angular/React/Flutter, all of them are promising fast testing only to drag you in a pit of despair. I'm sick of things like "testbed", "robot", "settle", "tick" and so on. These kinds of test end up eating massive amounts of useful time. The only testing that I really enjoy is Cypress. And I will go to great lengths to do it this way. – Adrian Moisa Jan 28 '22 at 22:41

2 Answers2

6

I do not think it is right way to use any Selenium kind of testing framework for Flutter Web.

Reason for that is that you (as web developer) have no control on how generated DOM looks like. Which means you can not use XPath and other means to select elements.

I suppose the only way of testing Flutter apps (including Flutter Web) is using Flutter Driver: https://api.flutter.dev/flutter/flutter_driver/flutter_driver-library.html

Alex Radzishevsky
  • 3,416
  • 2
  • 14
  • 25
  • I would rather use image 'recognition' like I use for the mobile app testing. The tool stack we use to describe our web tests / E+E does not work well with flutter testing capabilities (or we still miss a point). – Martin Kersten Feb 05 '20 at 20:12
1

You currently can not consistently add identification information to Widgets rendering on different devices.

To achieve your goal however you can use Flutter Driver. The flutter_driver Dart package is specifically designed to enable UI testing of Flutter apps and provides an API to the apps on real devices, simulators or emulators. To get started with Flutter Driver testing you need to:

  • Get the flutter_driver package
  • Set up a test directory
  • Create an instrumented app for testing
  • Write UI tests using flutter_driver API
  • Execute the UI tests in the real device or simulator

To find a Flutter widget you can use SerializableFinder, e.g.:

test('verify the text on home screen', () async {
    SerializableFinder message = find.text("Widget Title");
    await driver.waitFor(message);
    expect(await driver.getText(message), "Widget Title");
});

For more information check out:

realAlexBarge
  • 1,808
  • 12
  • 19