Appium iOS 测试脚本开发实战

最近老板家心情好,不停的给UI加了好多的任务,iOS开发部门的小哥哥见到UI妹妹的眼神由爱转嫌弃,饱含深深地怨气,每个周都会发布一个迭代;回归测试就是一个繁琐又不能忽略的事,没办法就是懒,不想继续点点点,干脆写个弱弱的iOS测试脚本,满足下自己懒得欲望,一番调研,选择了Appium作为iOS的测试框架,当然我没找到更合适的框架了;一周小成,分享出来,开心开心,大佬屠刀轻点,同为菜鸟慢慢吐槽😂

首先,开发iOS测试脚本的最重要前提是你的有一台macOS系统的设备

安装jdk,弱弱的问一句,哪位和开发沾点边的电脑没有jdk;Java -version检查下吧

接下来就是安装node.js,有好多写的很好的博文,不懂的可以移步了解下,检查下您家电脑的node是否安装成功吧

附带的,检查下您家电脑的npm是否可以正常使用吧

安装完成了以上的几个小东西,接下来就是安装我们尊贵的Appium了,Appium有两种,一种是桌面版,一种是命令行模式,这里建议安装桌面版的Appium-desktop,附上下载链接,下载后装即可;

https://github.com/appium/appium-desktop/releases

安装完成即可启动

仅仅是安装完成Appium-desktop可不代表可以您能开始的秀上您的优雅代码,我这这个坑硬是填了整整一天,Appium-desktop始终无法和客户端进行通讯,一直发生各种各样的报错,抑郁症狂犯;

到这里,先需要检查下Appium是否安装了它所需要的类库,最好的方式就是使用其自带的appium-doctor检查下。

在命令行客户端中输入appium-doctor,appium-doctor就会自动检查类库的安装是否完整,当没安装完整是就会在图中的红框部分显示出来,这时你需要根据提示将缺失的类库一一安装,直到不再爆红(以上爆红为安卓测试需要用到的adb和sdk,这里测试iOS,不进行处理)

到这里,Appium-desktop的安装完成,看看他的盛世美颜吧

要想和手机进行通讯,最重要的一环是安装WebDeiverAgent,安装WebDeiverAgent可能需要iOS开发同事的帮忙,但是你如果很了解xcode的使用情况下,可以自行下载,并完成编译,这部分的安装我暂且不做介绍,因为我之前也是根据大神的教程来完成安装的,需要的可以参考大神们的作品;编译完成后模拟器上会WebDriverAgent的图标,点击图标会启动然后结束,很像闪退的效果

 

之前推荐大家安装desktop版本的原因就是desktop版本可以截取到App UI的结构,配置好即可启动,并读取App的UI结构,点击红框部分进入到UI框架读取界面

 

配置好需要的desired capabilities,点击启动即可,其中每一项的内容分析会在下一部分一一解析

{

"bundleId": "com.latsen.Pawfit",

"deviceName": "Simulator",

"platformVersion": "14.2",

"platformName": "iOS",

"automationName": "Appium",

"noReset": true,

"udid": "F1B7F19F-C517-4587-8DE5-8EE73B8BBFDF"

}

启动看看结果吧

好的,第一个阶段算是完成了,环境搭建是我觉得这一个开发iOS测试脚本的最难部分,安装期间会遇到各种各样的问题,可以百度仰慕下大神的作品及其解决方案,祝您顺利

这个准备也是需要费点时间的工作,我这里三言两语就说完,但不代表这个步骤很简单,出现的意外可能就会让您前面的努力白费;

准备好您的模拟器或者手机,这里建议使用模拟器测试,手机会因为SDK的问题导致无法连接到手机,启动模拟器;

接下来就是准备好需要测试的APP文件,这个地方需要注意下,如果该APP文件不适配您的电脑,

启动APP请求网络是时APP会闪退,从而无法进行开发,我自然就遇到过,奇怪的就是网上为何都没出现过呢???为此,我花了三瓶可乐来招待开发小哥哥😅;检查下APP是否可以正常在中运行

文档准备,官方的稳定简直就是烂透了,这里建议使用看云的文档,可能需要登录

https://www.kancloud.cn/testerhome/appium_docs_cn/2001597

Appium配置文档

https://appium.io/docs/cn/writing-running-appium/caps/

完成了以上的折磨后,现在可以开启美丽的开发过程了,启动你的编译器吧

pip安装appium的python客户端代码

pip install Appium-Python-Client

from appium import webdriver
my_ios_driver=None
import json
class my_driver(object):
    session=None
    def __init__(self):
        self.session=self.get_my_driver(self.get_deried_cap())
    def get_deried_cap(self):
        caps = {}
        #APP文件在电脑中的位置,当模拟器中安装后,可以去掉该配置
        # caps["app"] = "/Users/kefeng/Desktop/Pawfit1230_1.zip"
        #将测试APP的包名
        caps["bundleId"] = "com.latsen.Pawfit"
        #模拟器名称
        caps["deviceName"] = "Simulator"
        #模拟器系统版本
        caps["platformVersion"] = "14.2"
        #测试的平台
        caps["platformName"] = "iOS"
        #测试期间使用的驱动
        caps["automationName"] = "XCUITest"
        #是否需要重置APP,不需要写False
        caps["noReset"] = True
        #命令执行的超时时间,这个很重要
        caps["newCommandTimeout"]=600
        #是否中断回话,并重启app
        caps['autoLaunch']=False
        #设备的UDID
        caps["udid"] = "F1B7F19F-C517-4587-8DE5-8EE73B8BBFDF"
        return caps
    def get_my_driver(self,caps):
        driver=webdriver.Remote("http://localhost:4723/wd/hub", caps)
        driver.set_page_load_timeout(50000)
        driver.set_script_timeout(50000)
        driver.implicitly_wait(10)
        # 设置权限,可根据xcrun simctl privacy命令查看
        return driver
    def disconnect(self):
        my_ios_driver.quit()
my_ios_driver=my_driver().session
if __name__ == '__main__':
    my_ios_driver.execute_script('mobile: setPermission','io.appium.example',{ 'location-always': 'yes'})

以上注释中提到的几个配置项都非常非常重要,如果配置错误,将无法启动;

#是否中断回话,并重启app caps["newCommandTimeout"]=600 #是否中断回话,并重启app caps['autoLaunch']=False

这两项在测试和开发中相当重要,尤其是caps['autoLaunch']=False,他可以帮助你不用每次重启APP即可进行测试,这在开发中极其的方便,我们并不是每次都想重启APP来进行测试,尤其是后期再testsuit套件测试时;

开发过程中,经常会出现的错误就是元素查找异常,Appium提供了多样的元素获取方式,如下:

根据类名:

#根据类名:
pet_breed=my_ios_driver.find_element_by_class_name('XCUIElementTypeTextField')[
pet_breed=my_ios_driver.find_elements_by_class_name('XCUIElementTypeTextField')[2]

#根据xpath
my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Dog"]').click()
my_ios_driver.find_elements_by_xpath('//XCUIElementTypeButton[@name="Dog"]')[0].click()

#根据predicate
my_ios_driver.find_element_by_ios_predicate('label == "Female"').click()

 

当然还会有其他的,可以根据您的需求来选择,例如我常用的代码截选

当然还会有其他的,可以根据您的需求来选择,例如我常用的代码截选
if type == "SUBSCRIBABLE" and status == "INACTIVE":
    # paypal方式使用手动测试
    pay_method = "1"

    if str(pay_method) == '1':
        device_id.clear()
        device_id.send_keys(barcode)
        self.hide_key_board()
        bind_buttom.click()
        sleep(5)
        # 启动支付流程
        # 检查优惠码有效性
        code=my_ios_driver.find_element_by_class_name('XCUIElementTypeTextField')
        # 检查无效
        code.clear()
        code.send_keys("@@@@@@@")
        self.hide_key_board()
        my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Buy now"]').click()
        sleep(5)
        # 检查过期优惠码
        code.clear()
        code.send_keys("asdfgv")
        self.hide_key_board()
        my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Buy now"]').click()
        sleep(5)
        # 已经被使用
        code.clear()
        code.send_keys("qawsde")
        self.hide_key_board()
        my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Buy now"]').click()
        # TODO 优惠码支付,请完善
        my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="OK"]').click()
        #返回绑定界面,等待绑定完成
        sleep(10)
        my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="OK"]').click()
    else:
        #TODO 由于paypal的原因,支付完成后可能会出现pending状态而无法继续接着其他步骤,可能需要单独处理
        device_id.clear()
        device_id.send_keys(barcode)
        self.hide_key_board()
        bind_buttom.click()
        sleep(5)
        buy_now=my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Buy now"]')
        buy_now.click()
        sleep(5)
        my_ios_driver.find_elements_by_class_name('XCUIElementTypeButton')[2].click()
        sleep(5)
        if self.utis.exists('xpath','//XCUIElementTypeButton[@name="Next"]',30):
            my_ios_driver.find_element_by_class_name('XCUIElementTypeTextField').send_keys("accounting-buyer@latsen.com")
            my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Next"]').click()
            sleep(10)
            my_ios_driver.find_element_by_class_name('XCUIElementTypeSecureTextField').send_keys("paypalDev123")
            my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Log in"]').click()
        else:
            my_ios_driver.find_element_by_class_name('XCUIElementTypeTextField').send_keys("accounting-buyer@latsen.com")
            my_ios_driver.find_element_by_class_name('XCUIElementTypeSecureTextField').send_keys("paypalDev123")
            self.hide_key_board()
            my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Log in"]').click()
        sleep(15)
        my_ios_driver.execute_script("mobile:swipe", {"direction": "up", 'element': my_ios_driver.find_element_by_xpath('  //XCUIElementTypeStaticText[@name="Pay with"]'), "duration": 1})
        my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Agree and Subscribe"]').click()

else:
    device_id.clear()
    device_id.send_keys(barcode)
    self.hide_key_board()
    bind_buttom.click()
    # 优惠码购买完成,但服务器设备状态未进行更改
    #处理不同型号机器弹框不同问题
    # sleep(10)
    # my_ios_driver.set_page_load_timeout(10000)
    sleep(15)
    if type=="SUBSCRIBABLE":
        my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="OK"]').click()
    #P
    else:
        my_ios_driver.find_element_by_xpath('//XCUIElementTypeButton[@name="Yes"]').click()

用到sleep简直就是噩梦,但不得不用,官方的等待方式经常会导致元素查找异常,哪怕我已经做了异常处理,场景多变,况且我还是菜;

# TODO 修改代码,返回一个元组,里面里面存放元素是否存在和控件对象

# TODO 修改代码,返回一个元组,里面里面存放元素是否存在和控件对象
def exists(self, what_method, resource_text, timeout=1):
    i = 0
    flag = False
    driver = my_ios_driver
    while timeout > i:
        try:
            if what_method == "accid":
                driver.find_element_by_accessibility_id(resource_text)
            elif what_method == "class":
                driver.find_element_by_class_name(resource_text)
            elif what_method == "css":
                driver.find_element_by_class_name(resource_text)
            elif what_method == "xpath":
                driver.find_element_by_xpath(resource_text)
            elif what_method == "pred":
                driver.find_element_by_ios_predicate(resource_text)
            elif what_method == "tag":
                driver.find_element_by_tag_name(resource_text)
            elif what_method == "name":
                driver.find_element_by_name(resource_text)
            elif what_method == "id":
                driver.find_element_by_id(resource_text)
            flag = True
            return flag
        except Exception as e:
            print(e)
            i += 1
            continue
    return flag

更多的代码细节不能太多暴露,请原谅

配合unittest使用,设计合理的测试流程,即可完成整个APP的全部用例的测试;

from ios.ios_app_edit_user_info_testcase import test_edit_user_profile
from ios.ios_app_register_testcase import Register_TestCase
from ios.ios_app_edit_pet_info_testcase import Edit_Pet_Info

if __name__ == '__main__':
    testcase = unittest.TestLoader().loadTestsFromTestCase(Login_Test)
    test_edit_user_profile = unittest.TestLoader().loadTestsFromTestCase(test_edit_user_profile)
    FindPassword = unittest.TestLoader().loadTestsFromTestCase(FindPassword)
    Register_TestCase = unittest.TestLoader().loadTestsFromTestCase(Register_TestCase)
    add_pet=unittest.TestLoader().loadTestsFromTestCase(AddPet_TestCase)
    edit_pet=unittest.TestLoader().loadTestsFromTestCase(Edit_Pet_Info)
    suite = unittest.TestSuite([testcase,add_pet,edit_pet,test_edit_user_profile,FindPassword,Register_TestCase])
    report='/Users/kefeng/Documents/TestCases/reports/testcase_report.html'
    with(open(report, 'wb')) as fp:
        runner = HTMLTestRunner(
            stream=fp,
            title='<project name> iOS 测试报告',
            description='describe: iOS 测试报告'
        )
        runner.run(suite)

原先想着可以录屏给亲们看个效果,但是发现模拟器似乎没有录屏功能,如果下次拿到录屏,一定给补上🤣

一下截图是测试结束后的报告,全部59个testcase可以在17分钟完成测试,下次可以喝着肥宅水,看着自动化脚本运行即可,当然目前代码的健壮性需要加强,大家一起努力吧

目录

6:告一段落


祝愿和我一样的菜鸟能快速成长,开心每一天。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值