appium+python开发09--框架封装,作用yaml作数据驱动

雪球APP:

实现股票查询:(Search)

appium+python开发09--框架封装,作用yaml作数据驱动_第1张图片appium+python开发09--框架封装,作用yaml作数据驱动_第2张图片

股票选择:(Selected)

appium+python开发09--框架封装,作用yaml作数据驱动_第3张图片

登陆操作的封装:

appium+python开发09--框架封装,作用yaml作数据驱动_第4张图片

 Profilepage页面

 appium+python开发09--框架封装,作用yaml作数据驱动_第5张图片

 

appium+python开发09--框架封装,作用yaml作数据驱动_第6张图片

 登陆页面

 appium+python开发09--框架封装,作用yaml作数据驱动_第7张图片

目录结构:

appium+python开发09--框架封装,作用yaml作数据驱动_第8张图片appium+python开发09--框架封装,作用yaml作数据驱动_第9张图片 

AndroidClient.py主要实现app的安装的启动功能:
from appium import webdriver
from appium.webdriver.webdriver import WebDriver

class AndroidClient(object):

    driver:WebDriver
    @classmethod
    def installApp(cls)->WebDriver:
        caps = {}
        # caps['app']='app存放的位置'    #安装app
        caps["platformName"] = "android"
        caps["deviceName"] = "hogwarts"
        caps["appPackage"] = "com.xueqiu.android"
        caps["appActivity"] = ".view.WelcomeActivityAlias"
        caps["autoGrantPermissions"] = "true"  # 自动授权
        # caps["noReset"] = True

        cls.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
        cls.driver.implicitly_wait(20)  # 隐式等待
        return cls.driver

    @classmethod
    def restartApp(cls)->WebDriver:
        caps = {}
        caps["platformName"] = "android"
        caps["deviceName"] = "hogwarts"
        caps["appPackage"] = "com.xueqiu.android"
        caps["appActivity"] = ".view.WelcomeActivityAlias"
        # caps["autoGrantPermissions"] = "true"  # 启动的时候将,noReset设置成True就不需要这一句代码自动授权
        caps["noReset"] = True
        caps["unicodeKeyboard"]=True
        caps["resetKeyboard"]=True

        cls.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
        cls.driver.implicitly_wait(20)  # 隐式等待
        return cls.driver

 app.py

from page_object.page.BasePage import BasePage
from page_object.page.MainPage import MainPage


class App(BasePage):

    @classmethod
    def main(cls):
        cls.getClient().restartApp()
        return MainPage()

BasePage.py,所有page页都继承这个页面

from page_object.driver.AndroidClient import AndroidClient
from appium.webdriver.webelement import WebElement
from selenium.webdriver.common.by import By


class BasePage(object):

    def __init__(self):
        self.driver=self.getDriver()

    @classmethod
    def getDriver(cls):
        cls.driver=AndroidClient.driver
        return cls.driver  #没想通

    @classmethod
    def getClient(cls):
        return AndroidClient  # 没想通

    def find(self,kv)->WebElement:
        #todo:处理弹框
        return self.driver.find_element(*kv)

    def findByText(self,text)->WebElement:
        return self.find((By.XPATH,"//*[@text='%s']" %text))

  

LoginPage.py

from selenium.webdriver.common.by import By
from page_object.page.BasePage import BasePage




class LoginPage(BasePage):
    _back_locator=(By.ID,"iv_action_back")
    _phone_login=(By.ID,"iv_login_phone")
    _wx_login=(By.ID,"iv_login_wx")
    _weibo_login=(By.ID,"iv_login_weibo")
    _qq_login=(By.ID,"iv_login_qq")
    _other_login=(By.ID,"login_more")
    _register_phone_number=(By.ID,"register_phone_number")
    _register_code=(By.ID,"register_code")
    _button_next=(By.ID,"button_next")
    _tv_login_with_account=(By.ID,"tv_login_with_account")
    _login_account=(By.ID,"login_account")
    _login_password=(By.ID,"login_password")
    _error_msg=(By.ID,"md_content")
    #_error_sue=()

    def loginByWX(self):
        return self

    def loginByMSG(self,phone,code):
        return self

    def loginByPassword(self, account, password):

        self.find(self._tv_login_with_account).click()
        self.find(self._login_account).send_keys(account)
        self.find(self._login_password).send_keys(password)
        self.find(self._button_next).click()



    def loginSuccessByPassword(self,account,password):
        from page_object.page.MainPage import MainPage  #为什么会这样?
        return MainPage()

    def back(self):
        self.find(self._back_locator).click()
        from page_object.page.ProfilePage import ProfilePage  #为什么会这样?
        return ProfilePage()

    def getErrorMsg(self):
        msg= self.find(self._error_msg).text
        self.findByText("确定").click()

        return msg

MainPage.py

from selenium.webdriver.common.by import By
from page_object.page.BasePage import BasePage
from page_object.page.ProfilePage import ProfilePage
from page_object.page.SelectedPage import SelectedPage
from page_object.page.SearchPage import SearchPage


class MainPage(BasePage):
    _profile_button=(By.ID,"user_profile_icon")
    _search_button=(By.ID,"tv_search")


    def gotoSelected(self):

        zixuan = (By.XPATH, "//*[@text='自选']")
        self.find(zixuan)  # self.driver.find_element(By.XPATH,"//*[@text='自选']")
        self.find(zixuan).click()
        return SelectedPage()

    def gotoSearch(self):

        self.find(self._search_button).click()
        return SearchPage()


    def gotoProfile(self):
        self.find(MainPage._profile_button).click()
        return ProfilePage()

ProfilePage.py

from selenium.webdriver.common.by import By
from page_object.page.BasePage import BasePage
from page_object.page.LoginPage import LoginPage


class ProfilePage(BasePage):


    _phone_login = (By.ID, "iv_login_phone")

    def gotoLogin(self):
        self.find(self._phone_login).click()
       
        return LoginPage()

SearchPage.py

from selenium.webdriver.common.by import By
from page_object.page.BasePage import BasePage
import time


class SearchPage(BasePage):

    _edit_locator=(By.CLASS_NAME,"android.widget.EditText")
    _searched_lab=(By.XPATH,"//*[contains(@resource-id,'name') and @text='招商银行']")

    def search(self, name):
        self.find(self._edit_locator).send_keys(name)
        self.find(self._searched_lab).click()
        time.sleep(2)
        return self  #为了进行链式调用,一直用.调用

    def addToSelected(self,text):
        follow_button = (By.XPATH, "//*[contains(@resource-id,'stockCode') and contains(@text,'%s')]"
                         % text + "/../../..//*[contains(@resource-id,'follow_btn')]")
        self.find(follow_button).click()
        return self

    def removeFromSelected(self,text):
        follow_button = (By.XPATH, "//*[contains(@resource-id,'stockCode') and contains(@text,'%s')]"
                         % text + "/../../..//*[contains(@resource-id,'followed_btn')]")
        self.find(follow_button).click()
        return self

    def isInSelected(self,text):
        folled_button=(By.XPATH,"//*[contains(@resource-id,'stockCode') and contains(@text,'%s')]"
                                 %text+"/../../..//*[contains(@resource-id,'follow')]")
        id=self.find(folled_button).get_attribute("resourceId")
        print(id)
        return "followed_btn" in id

    def cancel(self):
        self.findByText("取消").click()

    def searchByUser(self,key):
        pass

    def isFollowed(self):
        pass

SelectedPage.py

from selenium.webdriver.common.by import By
from appium.webdriver.common.mobileby import MobileBy  #是对By的补充,只能使用在app中
from page_object.page.BasePage import BasePage


class SelectedPage(BasePage):

    def addDefault(self):
        return self

    def gotoHS(self):
        self.findByText("沪深").click()
        return self

    def getPriceByName(self,name):
        priceLocator=(By.XPATH,"//*[contains(@resource-id,'portfolio_stockName') and @text='%s']" %name+
                               "/../../../..//*[contains(@resource-id,'item_layout')]")
        price=self.find(priceLocator).text
        return float(price)

test_login.py:

from selenium.webdriver.common.by import By
from appium.webdriver.common.mobileby import MobileBy  #是对By的补充,只能使用在app中
from page_object.page.BasePage import BasePage


class SelectedPage(BasePage):

    def addDefault(self):
        return self

    def gotoHS(self):
        self.findByText("沪深").click()
        return self

    def getPriceByName(self,name):
        priceLocator=(By.XPATH,"//*[contains(@resource-id,'portfolio_stockName') and @text='%s']" %name+
                               "/../../../..//*[contains(@resource-id,'item_layout')]")
        price=self.find(priceLocator).text
        return float(price)

test_search.py

from selenium.webdriver.common.by import By
from appium.webdriver.common.mobileby import MobileBy  #是对By的补充,只能使用在app中
from page_object.page.BasePage import BasePage


class SelectedPage(BasePage):

    def addDefault(self):
        return self

    def gotoHS(self):
        self.findByText("沪深").click()
        return self

    def getPriceByName(self,name):
        priceLocator=(By.XPATH,"//*[contains(@resource-id,'portfolio_stockName') and @text='%s']" %name+
                               "/../../../..//*[contains(@resource-id,'item_layout')]")
        price=self.find(priceLocator).text
        return float(price)

test_selected.py

from page_object.page.MainPage import MainPage
from page_object.page.app import App


class TestSelected(object):

    mainPage:MainPage
    @classmethod
    def setup_class(cls):
        cls.mainPage=App.main()   #进入首页


    def test_price(self):
        assert self.mainPage.gotoSelected().gotoHS().getPriceByName("恒瑞医药")==78.88

使用yaml再次进行框架封装:

appium+python开发09--框架封装,作用yaml作数据驱动_第10张图片

BasePage.py增加读取yaml的方法:loadStep

from page_object.driver.AndroidClient import AndroidClient
from appium.webdriver.webelement import WebElement
from selenium.webdriver.common.by import By
import yaml

class BasePage(object):

    def __init__(self):
        self.driver=self.getDriver()

    @classmethod
    def getDriver(cls):
        cls.driver=AndroidClient.driver
        return cls.driver  #没想通

    @classmethod
    def getClient(cls):
        return AndroidClient  # 没想通

    def find(self,kv)->WebElement:
        #todo:处理弹框
        return self.driver.find_element(*kv)

    def findByText(self,text)->WebElement:
        return self.find((By.XPATH,"//*[@text='%s']" %text))

    def loadStep(self,po_path,key,**kwargs):
        file=open(po_path,'r')
        po_data=yaml.load(file)
        po_method=po_data[key]
        for step in po_method:
            element=self.driver.find_element(by=step['by'],value=step['locator'])
            action=str(step['action']).lower()  #这里把action的值转化成了小写
            #todo:定位失败,多数是弹框,try catch后进入 一个弹框处理
            if action =="click":  #写上小写,yaml文件中也要写上小写
                element.click()
            elif action=="sendkeys":  #这里要写小写,ymal文件中也要写上小写
                text=str(step['text'])
                for k,v in kwargs.items():
                    text=text.replace("$%s" %k, v)
                    print("update text:%s "% (text))
                element.send_keys(text)
            else:
                print("UNKONW COMMAND %s" % step)

LoginPage.yaml

loginByPassword:
 - locator: tv_login_with_account
   by: id
   action: click
 - locator: login_account
   by: id
   action: sendkeys
   text: $var1
 - locator: login_password
   by: id
   action: sendkeys
   text: $var2
 - locator: button_next
   by: id
   action: click

LoginPage.py代码变化:

from selenium.webdriver.common.by import By
from page_object.page.BasePage import BasePage


class LoginPage(BasePage):
    _back_locator=(By.ID,"iv_action_back")
    _phone_login=(By.ID,"iv_login_phone")
    _wx_login=(By.ID,"iv_login_wx")
    _weibo_login=(By.ID,"iv_login_weibo")
    _qq_login=(By.ID,"iv_login_qq")
    _other_login=(By.ID,"login_more")
    _register_phone_number=(By.ID,"register_phone_number")
    _register_code=(By.ID,"register_code")
    _button_next=(By.ID,"button_next")
    _tv_login_with_account=(By.ID,"tv_login_with_account")
    _login_account=(By.ID,"login_account")
    _login_password=(By.ID,"login_password")
    _error_msg=(By.ID,"md_content")

    def loginByWX(self):
        return self

    def loginByMSG(self,phone,code):
        return self

    def loginByPassword(self, account, password):

        self.loadStep("../data/LoginPage.yaml","loginByPassword",var1=account,var2=password)
        return self


    def loginSuccessByPassword(self,account,password):
        from page_object.page.MainPage import MainPage  #为什么会这样?
        return MainPage()

    def back(self):
        self.find(self._back_locator).click()
        from page_object.page.ProfilePage import ProfilePage  #为什么会这样?
        return ProfilePage()

    def getErrorMsg(self):
        msg= self.find(self._error_msg).text
        self.findByText("确定").click()

        return msg

MainPage.yaml:

gotoProfile:
  - by: id
    locator: user_profile_icon
    action: click

MainPage.py:

from selenium.webdriver.common.by import By
from page_object.page.BasePage import BasePage
from page_object.page.ProfilePage import ProfilePage
from page_object.page.SelectedPage import SelectedPage
from page_object.page.SearchPage import SearchPage


class MainPage(BasePage):
    #_profile_button=(By.ID,"user_profile_icon")
    _search_button=(By.ID,"tv_search")


    def gotoSelected(self):

        zixuan = (By.XPATH, "//*[@text='自选']")
        self.find(zixuan)  # self.driver.find_element(By.XPATH,"//*[@text='自选']")
        self.find(zixuan).click()
        return SelectedPage()

    def gotoSearch(self):

        self.find(self._search_button).click()
        return SearchPage()


    def gotoProfile(self):
        #self.find(MainPage._profile_button).click()
        self.loadStep("../data/MainPage.yaml","gotoProfile")  #使用yaml进行改造
        return ProfilePage()

Profile.yaml

gotoLogin:
  - by: id
    locator: iv_login_phone
    action: click

Profile.py:

from selenium.webdriver.common.by import By
from page_object.page.BasePage import BasePage
from page_object.page.LoginPage import LoginPage


class ProfilePage(BasePage):


    #_phone_login = (By.ID, "iv_login_phone")

    def gotoLogin(self):
        #self.find(self._phone_login).click()
        self.loadStep("../data/ProfilePage.yaml","gotoLogin")
        return LoginPage()

使用yaml做一次分离后,测试用例没有任何变化只有page页面发生变化

你可能感兴趣的:(移动app自动化测试)