Missing perform for selenium ActionChains
Asked Answered
A

1

3

It is a very common and, sometimes, difficult to spot problem when "action chains" are defined but not being actually applied. Example:

# incorrect
ActionChains(driver).move_to_element(some_element).click(some_element)

as opposed to:

# correct
ActionChains(driver).move_to_element(some_element).click(some_element).perform()
                                                                       ^^^^^^^^^

ActionChains would essentially do nothing and perform no action without perform().

Is there a way to catch this type of a problem early with static code analysis?


I've also looked if PyCharm would warn about this, but it reports no suspicious code found which is understandable as without the perform() call it is still a perfectly valid Python.

There is also this missing-perform ESLint rule.

Attending answered 14/12, 2018 at 14:53 Comment(4)
perform() is a "sign" that you need to perform a chain of actions in ActionChains, not a single actionTouber
@Touber thanks, I think I'm not saying that this is a single action :) Thanks.Attending
ActionChains will not perform a “chain” of events without perform(). This is not a problem, this is logic. It's like in SQL commit after executeTouber
I am not questioning that, of course. I am asking about ways to detect missing perform and catch early when a developer missed calling perform() on an action chain.Attending
V
2

perform()

perform() method performs all stored actions.

As per the implementation of ActionChains, perform() is just like another method from the ActionChains Class like move_to_element(), click() etc.

Now, ActionChains Class is used to automate low level interactions such as mouse movements, mouse button actions, key press, and context menu interactions which are useful for doing complex actions like hover over and drag and drop through method chaining.

The documentation clearly mentions, to generate user actions when you call methods for actions on the ActionChains object, the actions are stored in a queue in the ActionChains object. Finally, when you call perform(), the events are fired in the order they are queued up.

So going by this logic, you were pretty correct to point out ...ActionChains would essentially do nothing and perform no action without perform()... and there is no way to catch this type of a problem early with static code analysis.

Even the IDEs, for example Eclipse, PyCharm or even Sublime Text3 a proprietary cross-platform source code editor with a Python application programming interface (API) wouldn't warn about this.

As an example Eclipse wouldn't complain about the missing perfrom():

no_perform

But Eclipse would complain about Bad Indentation:

bad_indentation

These cases are similar to the classic case of the IDEs not complaining when expected_conditions which should be called with a tuple and it is not a function, but actually a class, whose initializer expects just 1 argument beyond the implicit self:

class element_to_be_clickable(object):
    # .....
    def __init__(self, locator):
        # .....

IDE Snapshot:

tuple

Vibratile answered 17/12, 2018 at 9:52 Comment(1)
Thanks for looking into that. Yeah, it's too specific of a thing for existing static code analysis tool, I was thinking of a custom flake8 or pylint rule - will look into it.Attending

© 2022 - 2024 — McMap. All rights reserved.