J'essaie d'automatiser les tests de régression pour les sites Web html de base en utilisant selenium-webdriver en python. J'ai écrit une fonction qui prendra l'entrée d'un excel pour déterminer le type de localisateur d'un élément sur la page Web qui va comme ceci:

            if locator_type == "ID":
                web_element = self.__driver.find_element_by_id(element)
            elif locator_type == "NAME":
                web_element = self.__driver.find_element_by_name(element)
            elif locator_type == "XPATH":
                web_element = self.__driver.find_element_by_xpath(element)
            elif locator_type == "TAG_NAME":
                web_element = self.__driver.find_element_by_tag_name(element)
            elif locator_type == "LINK_TEXT":
                web_element = self.__driver.find_element_by_link_text(element)
            elif locator_type == "CLASS_NAME":
                web_element = self.__driver.find_element_by_class_name(element)
            elif locator_type == "PARTIAL_LINK_TEXT":
                web_element = self.__driver.find_element_by_partial_link_text(element)

C'est pour que nous puissions spécifier le type de localisateur et donner le localisateur réel («élément») afin que le sélénium puisse essayer de trouver l'élément Web sur la page Web. Existe-t-il un moyen de réduire les déclarations elif ou toute autre meilleure façon d'écrire cette partie?

Trop d'instructions if

J'ai essayé la méthode dans le lien ci-dessus mais cela ne m'a pas aidé. Veuillez m'aider à résoudre ce problème.

MODIFIER J'ai essayé de créer un dicton comme celui-ci

locator_dict = {
'ID' : driver.find_element_by_id(element),
'NAME' : driver.find_element_by_name(element)}

Alors j'ai reçu une erreur disant que l'élément n'est pas défini

4
dguy73 18 mars 2019 à 22:28

2 réponses

Meilleure réponse

Vous pouvez construire le nom de la fonction à appeler à partir de locator_type, puis l'appeler:

locator_type_lower = locator_type.lower()

find_function_name = 'find_element_by_{}'.format(locator_type_lower)

driver_function_to_call = getattr(self.__driver, find_function_name)

web_element = driver_function_to_call(element)

Vous devriez probablement envelopper cela dans une vérification d'erreur - vérifiez si la fonction existe, vérifiez si elle est appelable, etc.

Ce que cela fait: convertit le locator_type en minuscules, puis construit ce qui est, espérons-le, le nom d'une fonction existante dans le pilote self .__, puis l'appelle avec votre élément.

Cette méthode a l'avantage que vous n'avez pas à mapper des chaînes à des fonctions - si self.__driver a une fonction appelée find_element_by_foo_bar_length, alors vous pouvez simplement ajouter FOO_BAR_LENGTH dans votre feuille de calcul Excel, et elle sera appelé, pas besoin de mettre à jour votre dict de mappage.

Modifier: mis à jour pour les commentaires

Pour traduire la chaîne locator_type en un attribut de la classe By:

locator_type = 'ID'
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((getattr(By, locator_type), element)))
4
Danielle M. 21 mars 2019 à 19:46

La seule différence entre les corps des différentes clauses est la méthode que vous appelez réellement. Vous pouvez factoriser cela dans un dict.

d = {
    "ID": self.__driver.find_element_by_id,
    "NAME": self.__driver.find_element_by_name,
    # etc
}

if locator_type in d:
    web_element = d[locator_type](element)
else:
    # do something if you haven't defined a method for locator_type

Vous pouvez également utiliser methodcaller, bien que cette première tentative fasse dépendre d de element:

from operator import methodcaller

methods = [
    ("ID", "find_element_by_id"),
    ("NAME", "find_element_by_name"),
    # etc
]
d = { tag: methodcaller(method, element) for tag, method in methods } 

if locator_type in d:
    web_element = d[locator_type](self.__driver)

Pour être complètement indépendant du pilote ou de l'élément, utilisez

d = dict(methods)
if locator_type in d:
    web_element = methodcaller(d[locator_type], element)(self.__driver)
11
chepner 18 mars 2019 à 20:04