昨天在家安装好了环境,今天来星巴克发现使用cmd和git bash执行adb,报错:不是内部命令

解决:(1)、cmd使用管理员权限运行,可以执行adb命令了

(2)、将sdk所在的目录权限降级然后重启电脑,git bash 执行adb命令可以使用不再报错

1、app弹框处理

"autoGrantPermissions": "true"

2、appium隐式等待(无条件等待)

driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
driver.implicitly_wait(6)

截图方法(get_screenshot_as_file):

TestXueqiuAndroid.driver.get_screenshot_as_file(str(i)+'.png')

3、appiumdesktop=appium server+client,我们正真使用的是appium server(没有录制功能,安装起来后面使用appium server).官网的方法不太好装appium server

使用淘宝的cnpm安装appium是最稳定快速的方法

npm install -g cnpm --registry=https://registry.npm.taobao.org 
cnpm install -g appium 
cnpm install appium@11.1  #将老版本装在本地命令

#全局安装并执行
cnpm install -g appium
appium   #查看appium是否安装成功及安装的目录,也可以用些命令直接打开appium server

#只安装到当前目录并执行
cnpm install  appium@1.11
./node_modules/appium/build/lib/main.js   #安装的1.11版本的目录

4、 输入法拦截

unicodeKeyboard=true

5、测试用例结构(测试步骤三要素:定位、交互、断言,)

1)caps={

app apk地址

appPackage包名

appActivity Activity名字

automationName 默认使用uiautomator

noReset fullReset  是否清理之前的数据,true不清理,false清理

unicodeKeyBoard resetKeyBoard是否重新输入

}

2)appium server配置

driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)  #localhost可以使用其他Ip地址
driver.implicitly_wait(10)

3)定位方式(比较两个文件的命令:vimdiff /temp/1.txt /temp/2.txt)

(1)cont-desc ---》   find_element_by_accessibility_id()

(2)class name---》find_element_by_class_name()

(3)resource-id---》    find_element_by_id()

(4)xpath----》driver.find_element_by_xpath()

雪球首页-》基金

id:跟据id反定位界面元素

python弹窗怎么控制大小_ico

 

xpath:

/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.view.ViewGroup/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.RelativeLayout[4]/android.widget.TextView

//*[@text='基金' and @instance='4']  #改造后的xpath

//*[@resource-id='com.xueqiu.android:id/public_timeline_header_container']//*[@text='基金']   #借助父节点,/前面的内容可以省略掉

//*[contains(@resource-id,'buttons_container')]//*[@text='基金']  #借助父节点,使用contains

python弹窗怎么控制大小_ci_02

作业:

1)//*[@text='基金' and @instance='9']  #instance不太稳定,instance的值基本不会变

python弹窗怎么控制大小_ico_03

2)//*[@resource-id='com.xueqiu.android:id/indicator']//*[@text='基金'] 

3)//*[contains(@resource-id,'indicator')]//*[@text='基金']

需要先安装Pytest,

from appium import webdriver
from appium.webdriver.webdriver import WebDriver

class Testxueqiuan(object):

    driver=WebDriver  #不写这句,识别不出find方法,也可以写成driver:WebDriver
    #driver=String   #这个就变成String的方法

    @classmethod
    def setup_class(cls):   #整体初始化
        print('setup class')
        cls.driver=cls.initapp()
        

    def setup_method(self): #每一个方法
        print('setup method')
        Testxueqiuan.driver=self.restartapp()
        self.driver=Testxueqiuan.driver

    def test_login(self):

        el1 = Testxueqiuan.driver.find_element_by_id("com.xueqiu.android:id/user_profile_icon")
        el1.click()
        el2 = self.driver.find_element_by_id("com.xueqiu.android:id/tv_login")
        el2.click()
        el3 = Testxueqiuan.driver.find_element_by_id("com.xueqiu.android:id/tv_login_by_phone_or_others")
        el3.click()


    def test_基金(self):

        el1=Testxueqiuan.driver.find_element_by_xpath("//*[contains(@resource-id,'indicator')]//*[@text='基金']").click()

    @classmethod
    def initapp(cls)->WebDriver:
        caps = {}
        caps["platformName"] = "android"
        caps["deviceName"] = "demo"
        caps["app"] = "com.xueqiu.android"
        caps["appActivity"] = "view.WelcomeActivityAlias"
        caps["autoGrantPermissions"] = "true"

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

    @classmethod
    def restartapp(cls) -> WebDriver:
        caps = {}
        caps["platformName"] = "android"
        caps["deviceName"] = "demo"
        caps["app"] = "com.xueqiu.android"
        caps["appActivity"] = "view.WelcomeActivityAlias"
        caps["autoGrantPermissions"] = "true"
        caps['noreset'] = 'true'  # 这个选项默认为false

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


    def teardown_method(self):
        Testxueqiuan.driver.quit()

6)滑动手机模拟器屏幕:(3种不一样的写法)

from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from appium.webdriver.webdriver import WebDriver
import time

class Testxueqiuan(object):

    driver:WebDriver  #说明driver的类型是WebDriver

    @classmethod
    def setup_class(cls):   #整体初始化
        print('setup class在当前class中只执行一次')
        cls.driver=cls.install_app()   #安装一个app

    def setup_method(self): #每一个方法
        print('setup method在每个方法执行前中执行一次')
        TestXueqiuAndroid.driver=self.restart_app()
        self.driver=TestXueqiuAndroid.driver  #后面的driver都来自这里
        

    #下面三个方法是上下滑动手机或模拟器屏幕的
    def test_swipe(self):
        TestXueqiuAndroid.driver.find_element_by_xpath("//*[contains(@resource-id,'indicator')]//*[@text='基金']")
        for i in range(5):
            TestXueqiuAndroid.driver.swipe(1000,1000,200,200) #如果屏幕没有1000那么大就有可能执行失败
            time.sleep(2)
   
    def test_action(self):
        TestXueqiuAndroid.driver.find_element_by_xpath("//*[contains(@resource-id,'indicator')]//*[@text='基金']") 
        action=TouchAction(TestXueqiuAndroid.driver) #如果屏幕没有1000那么大就有可能执行失败
        for i in range(5):
            action.press(x=1000,y=1000).move_to(x=200,y=200).release().perform()
            time.sleep(2)

    def test_action_p(self):  #按百分比来滑动
        resc=TestXueqiuAndroid.driver.get_window_rect() #获取手机屏幕的width和height
        TestXueqiuAndroid.driver.find_element_by_xpath("//*[contains(@resource-id,'indicator')]//*[@text='基金']")
        action=TouchAction(self.driver)
        for i in range(5):
            action.press(x=resc['width']*0.8,y=resc['height']*0.8).move_to(x=resc['width']*0.2,y=resc['height']*0.2).release().perform()
            time.sleep(5)
           TestXueqiuAndroid.driver.get_screenshot_as_file(str(i)+'.png')  #每滑动一次屏幕就截图一张


    def test_login(self):

        el1 = TestXueqiuAndroid.driver.find_element_by_id("com.xueqiu.android:id/user_profile_icon")
        el1.click()
        el2 = TestXueqiuAndroid.driver.find_element_by_id("com.xueqiu.android:id/tv_login")
        el2.click()
        el3 = TestXueqiuAndroid.driver.find_element_by_id("com.xueqiu.android:id/tv_login_by_phone_or_others")
        el3.click()


    def test_jijin(self):

        el1=TestXueqiuAndroid.driver.find_element_by_xpath("//*[contains(@resource-id,'indicator')]//*[@text='基金']").click()



    @classmethod   #初始化app与restartapp有不同
    def install_app(cls)->WebDriver:
        caps = {}
        #caps['app']=''    #如果有必要需要安装和权限
        caps["platformName"] = "android"
        caps["deviceName"] = "demo"
        caps["app"] = "com.xueqiu.android"
        caps["appActivity"] = "view.WelcomeActivityAlias"
        #解决第一次启动时赋值权限
        caps["autoGrantPermissions"] = "true"
        driver = webdriver.Remote("http://localhost:5723/wd/hub", caps)
        driver.implicitly_wait(10)  # 隐式等待
        return driver

    @classmethod  #为了更快的启动
    def restart_app(cls) -> WebDriver:
        caps = {}
        caps["platformName"] = "android"
        caps["deviceName"] = "demo"
        caps["app"] = "com.xueqiu.android"
        caps["appActivity"] = "view.WelcomeActivityAlias"
        caps["autoGrantPermissions"] = "true"
        caps['noreset'] = 'true'  # 这个选项为true,保留之前的操作数据

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


    def teardown_method(self):
        TestXueqiuAndroid.driver.quit()

appium的操作可以查看appium官网文档,像command:http://appium.io/docs/en/commands/element/actions/click/

python弹窗怎么控制大小_ci_04

简化以后的代码:

from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from appium.webdriver.webdriver import WebDriver
import time

class TestXueqiuAndroid(object):


    @classmethod
    def setup_class(cls):
        print("class setup")


    def setup_method(self):
        print("method setup")
        self.driver=self.restart_app()  #下面的driver来自动这里



    def test_login(self):
        el1=self.driver.find_element_by_id("com.xueqiu.android:id/home_search")
        el1.click()

        el3=self.driver.find_element_by_id("com.xueqiu.android:id/search_input_text")
        el3.send_keys("alibaba")


    def test_jijin(self):

        el1=self.driver.find_element_by_xpath("//*[contains(@resource-id,'buttons_container')]//*[@text='基金']")
        el1.click()

    #三种滑动屏幕的方法

    def test_swipe(self):
        self.driver.find_element_by_xpath("//*[contains(@resource-id,'buttons_container')]//*[@text='基金']")
        for i in range(5):
            self.driver.swipe(800,800,200,200)
            time.sleep(2)

    def test_action(self):
        self.driver.find_element_by_xpath("//*[contains(@resource-id,'buttons_container')]//*[@text='基金']")
        action=TouchAction(self.driver)
        for i in range(5):
            action.press(x=800,y=800).move_to(x=200,y=200).release().perform()
            time.sleep(2)

    def test_action_p(self):
        rect=self.driver.get_window_rect()
        self.driver.find_element_by_xpath("//*[contains(@resource-id,'buttons_container')]//*[@text='基金']")
        action=TouchAction(self.driver)
        for i in range(5):
            action.press(x=rect['width']*0.8,y=rect['height']*0.8).move_to(x=rect['width']*0.2,y=rect['height']*0.2).release().perform()
            time.sleep(2)



    @classmethod
    def install_app(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

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

    @classmethod
    def restart_app(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

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

    #不加这段teardown的代码也没关系,如果不quit(),启动appium会自动quit之前的session
    """
    def teardown_method(self):
        self.driver.quit()
    """

整个代码的迭代思想:

(1)先用appium自带的inspector录制了一段代码

(2)pycharm上面新建一个test头或者结尾的py文件,加上一个Test开关的类,一个test开头或者结尾的方法,然后拷贝(1)中录制的代码到方法中去,此次形成了初步的代码

(3)优化代码:添加setup_class\setup_method\teardown_method这些方法,把重复公用的方法,如启动app定义成类方法封装到restart_app()方法中,然后在setup_method中调用

(4)添加三种滑动屏幕的方法

(5)只需要一次的操作封装到setup_class中,每个方法都需要操作的封装到setup_method

7)不用每次退出

思路:不停的分解,将相同的操作都写在setup_class或者setup_method中,不同的操作再定义到具体的方法中去

from appium import webdriver
from appium.webdriver.webdriver import WebDriver
import time


class Testxueqiuan(object):
    driver = WebDriver  # 不写这句,识别不出find方法
    @classmethod
    def setup_class(cls):  # 整体初始化
        print('setup class在当前class中只执行一次')
        cls.driver = cls.installap()  #加上cls变成类变量
        el1 = cls.driver.find_element_by_id("com.xueqiu.android:id/user_profile_icon")
        el1.click()   #到点击登陆的页面

    def setup_method(self):  # 每一个方法
        print('setup method在每个方法执行前中执行一次')
        self.driver=Testxueqiuan.driver  #局部变量
        el2 = self.driver.find_element_by_id("com.xueqiu.android:id/tv_login")
        el2.click()  #选择登陆的页面


    def test_login_phone(self):
        el3 = self.driver.find_element_by_id("com.xueqiu.android:id/tv_login_by_phone_or_others")
        el3.click() #手机登陆的页面

    def test_login_passwd(self):
        el3 = self.driver.find_element_by_id("com.xueqiu.android:id/tv_login_by_phone_or_others")
        el3.click()
        self.driver.find_element_by_xpath("//*[@text='邮箱手机号密码登陆']").click() #手机登陆页面的密码登陆

    def test_login_error_username(self):
        el4=self.driver.find_element_by_id()  #手机登陆页手机号错面误密码

    def test_login_eror_passwd(self):
        el4=self.driver.find_element_by_xpath()#手机登陆页面密码错误


    @classmethod
    def installap(cls) -> WebDriver:
        caps = {}
        # caps['app']=''    #安装apk
        caps["platformName"] = "android"
        caps["deviceName"] = "demo"
        caps["app"] = "com.xueqiu.android"
        caps["appActivity"] = "view.WelcomeActivityAlias"
        # 解决第一次启动时赋值权限
        caps["autoGrantPermissions"] = "true"

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

    @classmethod
    def restartapp(cls) -> WebDriver:
        caps = {}
        caps["platformName"] = "android"
        caps["deviceName"] = "demo"
        caps["app"] = "com.xueqiu.android"
        caps["appActivity"] = "view.WelcomeActivityAlias"
        caps["autoGrantPermissions"] = "true"
        caps['noreset'] = 'true'  # 这个选项为true,保留之前的操作数据

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

    def teardown_method(self):
        self.driver.back()

注:实际中的app都存在动态加载,需要使用显示等待作判断

8)截图:

self.driver.get_screenshot_as_file(str(i)+".png")