從yaml文件讀取內容使其轉換爲可識別的WebElement類型的值,進行操作

# FindBy.py文件  作用是將yaml格式中的Type的值轉換爲可被By對象可識別的元組,被FindWebElement調用
# -*- coding:utf-8 -*-
# explain :元素定位方式說明,用於返回By類型
import sys
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from com.chanpin.initialize.Start import Primary


class FindBy:
    def __init__(self, Type):
        """
        用於返回loaction元組的by類型
        :param Type: yaml文件的Type值
        """
        self.__Type = Type
    # 定義查找元素

    def find_by(self) -> By:
        """
        通過'id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath'查找相應的locationby
        :rtype locationby : selenium.webdriver.common.by.By
        :return locationby 對應的location元組的By的值
        """
        """定位元素"""
        by = self.__Type
        locationby = None
        if by in ['id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath']:

            try:
                if by == 'id':
                    locationby = By.ID
                elif by == 'name':
                    locationby = By.NAME
                elif by == 'class':
                    locationby = By.CLASS_NAME
                elif by == 'tag':
                    locationby = By.TAG_NAME
                elif by == 'link':
                    locationby = By.LINK_TEXT
                elif by == 'plink':
                    locationby = By.PARTIAL_LINK_TEXT
                elif by == 'css':
                    locationby = By.CSS_SELECTOR
                elif by == 'xpath':
                    locationby = By.XPATH
                else:
                    Primary.Log.error("沒有找到對應元素Type類型,請使用'id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath'")
                # Log.info('元素定位成功。定位方式:%s,使用的值%s:' % (by, value))
                return locationby
            except NoSuchElementException as e:
                # print("no suceelement")
                method = sys._getframe(1).f_code.co_name  # 調用該函數的函數名字,如果沒有被調用,則返回<module>
                path = sys._getframe(1).f_code.co_filename  # 調用該函數的文件名字,如果沒有被調用,則返回<module>
                Primary.Log.error("在執行【" + path + "】文件中的【" + method + "】方法時出現錯誤" + "沒有找到對應的元素" + e.__str__())

        else:
            # print("輸入的元素定位方式錯誤")
            Primary.Log.error("輸入的元素定位方式錯誤,請使用'id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath'")
            
            
            

                        
# --FindWebElemnet.py文件,該文件的作用是將yaml文件中Type值作爲元素定位的方式值,Value作爲元素內容值,兩個方法分別返回WebElement對象和由WebElement對象組成的list列表,被ReadyamlToElement類調用
# -*- coding:utf-8 -*-
# explain : WebElement元素定位,給GetelementFromYaml使用

from com.chanpin.initialize.Start import Primary
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.remote import webelement


class FindWebElement:
    def __init__(self, driver, Type, Value):
        """
        :type driver: selenium.webdriver.remote.webdriver.WebDriver
        實例化findWebElement
        :param driver:
        :param Type: yaml文件的Type值
        :param Value: yaml文件的value值
        """
        self.__driver = driver
        self.__Type = Type
        self.__Value = Value
    # 定義查找元素

    def find_element(self, yamlpath, key) -> webelement:
        """
        通過'id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath'查找相應的元素
        :return: WebElemt對應
        """
        """定位元素"""
        by = self.__Type
        value = self.__Value
        element = None
        if by in ['id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath']:
                # noinspection PyBroadException
            try:
                if by == 'id':
                    element = self.__driver.find_element_by_id(value)
                elif by == 'name':
                    element = self.__driver.find_element_by_name(value)
                elif by == 'class':
                    element = self.__driver.find_element_by_class_name(value)
                elif by == 'tag':
                    element = self.__driver.find_element_by_tag_name(value)
                elif by == 'link':
                    element = self.__driver.find_element_by_link_text(value)
                elif by == 'plink':
                    element = self.__driver.find_element_by_partial_link_text(value)
                elif by == 'css':
                    element = self.__driver.find_element_by_css_selector(value)
                elif by == 'xpath':
                    element = self.__driver.find_element_by_xpath(value)
                else:
                    Primary.Log.error("沒有找到對應元素Type類型,請使用'id', 'name', "
                                      "'class', 'tag', 'link', 'plink', 'css', 'xpath'")
                # Log.info('元素定位成功。定位方式:%s,使用的值%s:' % (by, value))
                return element
            except NoSuchElementException as e:
                # print("no suceelement")
                Primary.Log.error("yaml文件爲:" + yamlpath + ";頁面中沒有定位key值爲'" + key +
                                  "'對應的元素;" + e.__str__() + ";請確保定位準確。")
                # self.get_img()  # 調用截圖
        else:
            # print("輸入的元素定位方式錯誤")
            Primary.Log.error("輸入的元素定位方式錯誤,請使用'id', 'name', 'class', "
                              "'tag', 'link', 'plink', 'css', 'xpath'")

    def find_elements(self, yamlpath, key) -> list:
        """
        通過'id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath'查找相應的元素
        :return: 當list_elements只有1個時直接返回selenium.webdriver.remote.webelement類,否則返回list
        :rtype list_elements : list of WebElement
        """
        """定位元素"""
        by = self.__Type
        value = self.__Value
        list_elements = None
        if by in ['id', 'name', 'class', 'tag', 'link', 'plink', 'css', 'xpath']:
                # noinspection PyBroadException
            try:
                if by == 'id':
                    list_elements = self.__driver.find_elements_by_id(value)
                elif by == 'name':
                    list_elements = self.__driver.find_elements_by_name(value)
                elif by == 'class':
                    list_elements = self.__driver.find_elements_by_class_name(value)
                elif by == 'tag':
                    list_elements = self.__driver.find_elements_by_tag_name(value)
                elif by == 'link':
                    list_elements = self.__driver.find_elements_by_link_text(value)
                elif by == 'plink':
                    list_elements = self.__driver.find_elements_by_partial_link_text(value)
                elif by == 'css':
                    list_elements = self.__driver.find_elements_by_css_selector(value)
                elif by == 'xpath':
                    list_elements = self.__driver.find_elements_by_xpath(value)
                else:
                    Primary.Log.error("沒有找到對應元素Type類型,請使用'id', 'name', 'class', "
                                      "'tag', 'link', 'plink', 'css', 'xpath'")
                # Log.info('元素定位成功。定位方式:%s,使用的值%s:' % (by, value))
                return list_elements
            except NoSuchElementException as e:
                # print("no suceelement")
                Primary.Log.error("yaml文件爲:" + yamlpath + ";頁面中沒有定位key值爲'" + key +
                                  "'對應的元素;" + e.__str__() + ";請確保定位準確。")
                # self.get_img()  # 調用截圖
        else:
            # print("輸入的元素定位方式錯誤")
            Primary.Log.error("輸入的元素定位方式錯誤,請使用'id', 'name', 'class', "
                              "'tag', 'link', 'plink', 'css', 'xpath'")

                              
                              
                              
                              
                              
                              
                                                            
# GetelementFromYaml.py文件,真正被調用其他模塊的調用的類,通過傳入yaml文件中的key值根據情況獲得真正能使用的WebElement對象,進行元素點擊輸入等操作                     
# -*- coding:utf-8 -*-
# explain : 從yaml文件中讀取返回webelement

import yaml
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException

from com.chanpin.utils.FindWebElemet import FindWebElement
from com.chanpin.utils.FindBy import FindBy
from com.chanpin.initialize.Start import Primary

# yaml文件位置
'''
   初始化添加對應的yaml文件位置,然後調用getAllValue方法,調用 getelement方法獲取到對應的webelement
   改進方法:保證yaml的文件名和test_case的文件名或者類名一致
'''


class ReadyamlToElement:
    """
       通過yaml文件獲取相應的元素定位,方法如下:
       getelement(self, key) : 返回WebElement類元素
       getelements(self, key) : 返回list
       getelementsintnum(self, key, intnum=0) : 返回WebElement類元素
       getelementsstringtext(self, key, strtext: str, attributename=None) : 返回WebElement類元素
       waitgetelement(self, key) : 返回WebElement類元素
       waitgetelements(self, key) : 返回list
       waitgetelement_clickable(self, key) : 返回WebElement類元素
       getlocator(self, key) : 返回tuple
    """

    def __init__(self, driver: WebDriver, yamlpath):
        """
        實例化readyaml類
        :param driver:
        :param yamlpath: 對應的yaml文件名
        """
        self.__yamlPath = yamlpath
        self.__driver = driver

    def __getAllValue(self):
        """
           將指定yaml文件轉化爲dic字典,key爲
           :return  dic字典
         """
        '''
        curPath = os.path.dirname(os.path.realpath(__file__))
        # 獲取yaml文件路徑
        yamlPath = os.path.join(curPath, "cfgyaml.yaml")
        print(type(yamlPath))
        '''
        with open(self.__yamlPath, 'r', encoding='utf-8') as f:
            cfg = f.read()

        dic_yaml = yaml.load(cfg, Loader=yaml.FullLoader)  # 用load方法轉字典
        return dic_yaml

    '''
       通過key獲取到對應的webelement,改進方法,將其全部遍歷後,生成key:element的字典,從裏面取對應的數據
    '''

    def getelement(self, key) -> WebElement:
        """
        通過yaml文件的key獲取到對應的Webelement
        :param key: yaml文件的key
        :return: 對應的WebElement對象
        :rtype keyelement: selenium.webdriver.remote.webelement
        """
        dic = ReadyamlToElement(self.__driver, self.__yamlPath).__getAllValue()  # 接受readyaml().getAllValue()返回的dict
        if key in dic:
            list_value = dic.get(key)
            # list_Type_value = list_value[0].split(":")[1]    #獲取type的值
            # list_Value_value = list_value[1].split(":")[1]   #獲取value的值
            list_Type_value = list_value.get("Type")  # 獲取type的值
            list_Value_value = list_value.get("Value")  # 獲取value的值
            keyelement = FindWebElement(self.__driver, list_Type_value,
                                        list_Value_value).find_element(self.__yamlPath, key)  # 用於返回webelement對象
            Primary.Log.info(self.__yamlPath + "中獲取到該element,通過該key:" + key)
            return keyelement
        else:
            Primary.Log.error(self.__yamlPath + "中不存在該key:" + key + ":關閉程序")
            # self.__driver.quit()

    def getelements(self, key):
        """
        通過yaml文件的key獲取到對應的Webelement
        :param key: yaml文件的key
        :return: 對應的WebElement對象 類型爲WebElement
        :rtype keyelements: list
        """
        dic = ReadyamlToElement(self.__driver, self.__yamlPath).__getAllValue()  # 接受readyaml().getAllValue()返回的dict
        # print(dic)
        if key in dic:
            list_value = dic.get(key)
            list_Type_value = list_value.get("Type")  # 獲取type的值
            list_Value_value = list_value.get("Value")  # 獲取value的值
            keyelementlist = FindWebElement(self.__driver, list_Type_value,
                                            list_Value_value).find_elements(self.__yamlPath, key)  # 用於返回webelement對象
            Primary.Log.info(self.__yamlPath + "中獲取到該element,通過該key:" + key)
            return keyelementlist
        else:
            Primary.Log.error(self.__yamlPath + "中不存在該key:" + key + ":關閉程序")
            # self.__driver.quit()

    def getelementsintnum(self, key, intnum=0) -> WebElement:
        """
        通過yaml文件的key獲取一組WebElemnts,通過數組下標獲取對應的WebElemnt
        :param key: yaml文件的key
        :param intnum 數組下標
        :type key : String
        :type intnum : int
        :return: 對應的WebElement對象
        :rtype keyelements[intnum]: selenium.webdriver.remote.webelement
        """
        dic = ReadyamlToElement(self.__driver, self.__yamlPath).__getAllValue()  # 接受readyaml().getAllValue()返回的dict
        # print(dic)
        list_keyelements = []
        if key in dic:
            list_value = dic.get(key)
            # list_Type_value = list_value[0].split(":")[1]    #獲取type的值
            # list_Value_value = list_value[1].split(":")[1]   #獲取value的值
            list_Type_value = list_value.get("Type")  # 獲取type的值
            list_Value_value = list_value.get("Value")  # 獲取value的值
            list_keyelements = FindWebElement(self.__driver, list_Type_value,
                                              list_Value_value).find_elements(self.__yamlPath, key)  # 用於返回webelement對象
            Primary.Log.info(self.__yamlPath + "中獲取到該element,通過該key:" + key)
        else:
            Primary.Log.error(self.__yamlPath + "中不存在該key:" + key + ":關閉程序")
            # self.__driver.quit()
            # 判斷輸入的值是否正確,正確則正確找到,否則就報空
        if -len(list_keyelements) <= intnum < len(list_keyelements):
            return list_keyelements[intnum]
        else:
            Primary.Log.error("當前輸入的intnum大於" + str(len(list_keyelements)) + "有問題")
            return None

    def getelementsstringtext(self, key, strtext: str, attributename=None) -> WebElement:
        """
        通過yaml文件的key獲取一組WebElemnts,通過指定元素的值獲取到對應的WebElemnt
        :param key: yaml文件的key
        :param strtext 對應元素的值
        :type key : str
        :type strtext : str
        :param attributename 元素的屬性值,Name of the attribute/property to retrieve
        :type attributename : str
        :return: 對應的WebElement對象
        :rtype element: selenium.webdriver.remote.webelement
        """
        dic = ReadyamlToElement(self.__driver, self.__yamlPath).__getAllValue()  # 接受readyaml().getAllValue()返回的dict
        # print(dic)
        list_keyelements = []
        if key in dic:
            list_value = dic.get(key)
            # list_Type_value = list_value[0].split(":")[1]    #獲取type的值
            # list_Value_value = list_value[1].split(":")[1]   #獲取value的值
            list_Type_value = list_value.get("Type")  # 獲取type的值
            list_Value_value = list_value.get("Value")  # 獲取value的值
            list_keyelements = FindWebElement(self.__driver, list_Type_value,
                                              list_Value_value).find_elements(self.__yamlPath, key)  # 用於返回webelement對象
            Primary.Log.info(self.__yamlPath + "中獲取到該element,通過該key:" + key)
        else:
            Primary.Log.error(self.__yamlPath + "中不存在該key:" + key + ":關閉程序")
            # self.__driver.quit()
            # 判斷輸入的值是否正確,正確則正確找到,否則就報空
        booleanfind = False
        element = None
        # 當沒有設備屬性值時用元素的text值
        if attributename is None:
            for webelement in list_keyelements:
                if webelement.text == strtext:
                    element = webelement
                    booleanfind = True
                    break
        # 當設備屬性值時用元素的指定的屬性值的內容
        else:
            for webelement in list_keyelements:
                if webelement.get_attribute(attributename) == strtext:
                    element = webelement
                    booleanfind = True
                    break

        if booleanfind:
            return element
        else:
            Primary.Log.error(self.__yamlPath + "中未找到對應的元素值,請確認" + strtext + "的正確")
            return element

    def waitgetelement(self, key) -> WebElement:
        """
        通過yaml文件的key獲取到對應的Webelement,加入了顯示等待,WeblEment.is_displayed()爲真時返回該該webElement
        :param key:  yaml文件的key
        :return: 對應的WebElement對象
        """
        try:
            inttime = Primary.readini.getvalue("webdriver", "implicit_waitTime")
            WebDriverWait(self, int(inttime)).until(lambda x: x.getelement(key).is_displayed())
            return self.getelement(key)
        except Exception as e:
            Primary.Log.error(self.__yamlPath + "中該元素不存在:" + key + "導致錯誤:" + e.__str__())
            return None
            # self.__driver.quit()

    def waitgetelements(self, key) -> list:
        """
        通過yaml文件的key獲取到對應的Webelement,加入了顯示等待,WeblEment.is_displayed()爲真時返回該該webElement
        :param key:  yaml文件的key
        :return: 對應的WebElement對象
        """
        try:
            inttime = Primary.readini.getvalue("webdriver", "implicit_waitTime")
            WebDriverWait(self, int(inttime)).until(lambda x: x.getelement(key).is_displayed())
            return self.getelements(key)
        except Exception as e:
            Primary.Log.error(self.__yamlPath + "中該元素不存在:" + key + "導致錯誤:" + e.__str__())
            return None
            # self.__driver.quit()

    def waitgetelement_clickable(self, key) -> WebElement:
        """
        通過yaml文件的key獲取到對應的Webelement,當元素可以點擊時返回webelement
        :param key: yaml文件的key
        :return: 對應的WebElement對象
        :rtype keyelement: selenium.webdriver.remote.webelement
        """
        dic = ReadyamlToElement(self.__driver, self.__yamlPath).__getAllValue()  # 接受readyaml().getAllValue()返回的dict
        if key in dic:
            list_value = dic.get(key)
            list_Type_value = list_value.get("Type")  # 獲取type的值
            list_Value_value = list_value.get("Value")  # 獲取value的值
            try:
                # 顯式等待時間
                inttime = Primary.readini.getvalue("webdriver", "implicit_waitTime")
                # 配合expected_conditions當元素可以點擊時返回element
                elemnet = WebDriverWait(self.__driver, int(inttime)).until(EC.element_to_be_clickable((
                    FindBy(list_Type_value).find_by(), list_Value_value)), (self.__yamlPath +
                                                                            "中No such element : 請檢查該‘" + key +
                                                                            "’對應下的Value值是否能在頁面上定位成功"))
                return elemnet
            except TimeoutException as e:
                Primary.Log.error(e.__str__())
                return None

    def getlocator(self, key) -> tuple:
        """
        返回location 元組類型的值,主要給EC模塊入參使用
        :param key : yaml文件的key
        :return: tup_locator 元組類型的值如(By.Id,"value")
        :rtype tup_locator : tuple
        """
        dic = ReadyamlToElement(self.__driver, self.__yamlPath).__getAllValue()  # 接受readyaml().getAllValue()返回的dict
        if key in dic:
            list_value = dic.get(key)
            # list_Type_value = list_value[0].split(":")[1]    #獲取type的值
            # list_Value_value = list_value[1].split(":")[1]   #獲取value的值
            list_Type_value = list_value.get("Type")  # 獲取type的值
            list_Value_value = list_value.get("Value")  # 獲取value的值
            tup_locator = (FindBy(list_Type_value).find_by(), list_Value_value)
            if len(tup_locator) is None:
                Primary.Log.error(self.__yamlPath + "中請檢查該‘" + key + "’的值是否正確")
                return None
            else:
                return tup_locator
                
                
yaml文件格式樣例

# -*- coding:utf-8 -*-
# explain : 登錄頁面的元素定位
#Type : id, name, class, tag, link, plink, css, xpath

#登錄用戶名輸入框
login_username :   # ReadyamlToElement類對象方法的實參
  Type : css      # 八大定位方式
  Value : i.iconfont.icon-login+span+label>input  # 定位值

說明:需要三個主要方法來實現WebElement對象的值 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章