What Could Testing Look Like For Web? #3440
Replies: 2 comments 5 replies
-
Thanks for kicking off this discussion. There's clearly some technical issues to resolve here.
One detail that is worth being explicit about here (for the benefit of anyone else reading): when you say "another program/process", we're referring to the Pytest suite. We're essentially looking at a situation where the pytest suite runs outside the context of the "app". In every other platform to date (macOS, Android etc), the test suite is a second thread inside the testbed app.
Pyodide APIs will definitely be available in this way - but then, so should any Javascript API, including PyScript APIs. If Pyodide is the easiest/best way to perform a given action, that's fine - but it's also worth keeping in mind that both higher and lower level APIs may also be an option.
The rendered DOM widget should be accessible through the Playwright API - I'm not sure I see why there would be a benefit (or need) to use "Playwright running pyodide running Python" to obtain DOM state. Am I missing something about what you're describing here?
That looks like a good summary of the types of operations that need to be performed. To put this another way:
The latter will be the harder of the two - essentially, you need to be able to get a handle to a proxy for the object inside the browser. When you invoke
True - but that should be something Playwright is able to manage - or if it isn't, we can put a "ready" marker into the startup sequence of the testbed app itself.
This is a non-starter. We can't make widget objects global. However, a Toga app has an API for doing a DOM-like "lookup by ID".
I'm not sure you've explained why this is the case. At a high level, the current testbed test suite is expressed in terms of high level functional behaviors that a widget should have, with the probe being used as a mechanism for evaluating if those functional behaviors have actually occurred (e.g., you can set the text color of a label - and sure, toga's API will return the new style, but does the actual underlying widget toolkit agree that the color has changed?) There's definitely a new way to start the testbed test suite, and there definitely needs to be a web probe backend; but why does the entire testbed directory need to be rebuilt? |
Beta Was this translation helpful? Give feedback.
-
I'm going to have a go at explaining things better, including a new plan. Note that these are only ideas currently. I will be using the Button widget and it's test file As mentioned, the main problem is that for web, the testbed app and the test suite can't run multi-threaded in the same process and must run separately. In the test suite, any toga element created is in the same memory space as the testbed app, and so can be easily referenced, modified and added to Currently, in Pytest fixtures such as @fixture
async def widget():
return toga.Button("Hello") in @pytest.fixture
async def widget():
return toga.Box(style=Pack(width=100, height=200, background_color=RED)) in The Button and Box widgets are created in the same memory space as the testbed app. So they can be easily modified and added to the widget.text = text child = toga.Box(style=Pack(width=75, height=100, background_color=GREEN))
grandchild = toga.Button("Hello")
child.add(grandchild)
widget.add(child) old_content = main_window.content
box = toga.Box(children=[widget])
main_window.content = box
main_window.content = old_content The only idea that I have is to do some aliasing, aliasing these toga classes with proxy/remote classes behind the scene. These alias proxy classes will act like a wrapper that will 'forward' any commands or changes to the real ones in the testbed app, so that they can be executed there, as if they are in the same process as the test suite expects. To get this set up, we can run the following, which will only be executed if the test suite is testing the web platform. Something like: @pytest.fixture(autouse=True, scope="session")
def patch_toga_classes_for_web():
if toga.platform.current_platform == "web":
toga.Button = RemoteButton
toga.Box = RemoteBox # or RemoteBoxProxy or BoxProxy These will act like aliases (but only for web testing) so that when In the After this, methods can be created in For example, when the test suite runs toga.App.widget["button-id"].text = "new text" I believe this is would effectively solve the problem that you explained earlier:
Where Obviously, the probes will be using Playwright to interrogate the DOM state and the rendered widgets in the DOM. The above proxy stuff just ensures that the test suite can get/set attributes and invoke methods as if it is running in the same process as the testbed app, with the proxies just forwarding commands to be executed in the testbed app context. Some other areas that need looking at in more detail (other than command string building) is to do with Briefcase would also need to know how to run the testbed app and the test suite as separate processes when a web app is run with the test flag. I'm not sure how this could be done however, as I'm not familiar with Briefcase. Also, at some level, either in Once some things have been figured out, some proof-of-concepts or prototypes could be developed. I have thought a lot about this and this plan should be feasible, the proxies/communication bridge between the test suite and testbed app that forwards commands/data is the stuff that needs to be figured out fully. There's also the other things discussed above (proxies, probes, command string building, etc). The proxy class/alias stuff should definitely work though (I hope) and basic tests (i.e. testing text changes) should be able to be added relatively easily once the architecture is figured out and is actually implemented. If this ends up not being feasible, I'm not really sure how it can be done at the moment (maybe somehow with web sockets or an API, but the RCE should be adequate, or modifying the test suite differently). |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
This discussion was created by myself and @vt37
I'm aware that multithreading can't be used due to WebAssembly, so perhaps the web app to be tested can be run on an HTTP server (as it already is), with another program/process running the tests. This testing process could run tests similar to those in the
toga/testbed/tests
directory, and the (to-be-implemented) probes in thetests_backend
of the web directory could use Playwright to "look at" and interact with the DOM of the web app.Communication Between Web App and Test Process
As for a communication channel between the web app and testing program, we could use Pyodide to run Python code remotely. Once a Playwright
Page
object navigates to the URL (e.g.,page.goto("http://localhost:8000")
), it could then execute:This method could also be used to return data from the widget objects directly, in addition to inspecting the rendered DOM widget.
Example Use Case
Testing a button’s text currently requires:
widget.text = text
could be run via Pyodide.widget
fixture/object could retrieve the text using a similar Pyodide call.probe
fixture/object would use Playwright to get the DOM representation of the button’s text.Potential Considerations
testbed
directory or creating a new one entirely, where the Pytest fixtures may not even be needed.What do you think about this idea? Is it feasible? I'm aware it's fairly high-level, so I’m sure there are aspects I haven’t considered yet. Any thoughts or feedback are much appreciated!
Beta Was this translation helpful? Give feedback.
All reactions