appium随笔

目录结构如下:

Test_edaike---page object设计思想 定位元素和脚本分离
Images目录---用例失败截图
case目录
  eTestfastfood.py---定位app界面元素<id,xpath>
  input开头的函数---调用sendkeys()方法
  click开头的函数---调用click()方法
  element/elements开头的函数---调用find_element/find_elements方法
test_EdaikeFastFood.py---测试用例。
  进入客位列表界面,随机选择桌位;
  判断是否开台;判断账单金额是否为0<区分加菜和查看账单操作>;
  获取bill_num,传给sqlConnect.py,核对数据库金额;
  随机使用会员价或者打折;
  随机选择付款方式;
date目录---参数化数据。暂时只做了登录的参数化
logs目录---打印日志的存储目录
pulic目录---公共文件目录
complete.py---第二次封装。click、send_kenys...
logger.py---封装logs模块,打印日志
sqlConnect.py---封装连接数据库psycopg2模块
report目录---存储生成的html报告目录
main.py---unittest执行用例,HTMLTestRunner模块生成html报告,发送邮件

附测试用例代码:

# 随机数、时间、运行cmd命令
import random, time, unittest, os, subprocess
from appium import webdriver
# 异常类
from selenium.common.exceptions import *
# 日志
from Test_edaike.public.logger import Log
# 连接数据库
from Test_edaike.public.sqlFastFood import SqL
# 元素类
from Test_edaike.case.eTestFastFood import eTestFastFood

PATH = lambda p: os.path.abspath(p)
# print(PATH)
alertTitle = ('id', 'android:id/alertTitle')


class FastFood(unittest.TestCase):
    """x自动化测试"""
    def setUp(self):
        """初始化,appium连接设备"""
        desired_caps = {
            'platformName': 'Android',

            'deviceName': 'xx',

            'platformVersion': '5.1.1',

            'appPackage': 'xxx',

            'appActivity': 'xxxx',

            # 隐藏手机默认键盘
            'unicodeKeyboard': True,

            'resetKeyboard': True
        }
        # 关联appium
        self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
        self.E = eTestFastFood(self.driver)
        self.username, self.password, = "", ""
        self.f = open(r'D:TestProjectTest_edaikedateuser.txt', 'r')
        # 是否使用会员储值
        self.isMember = False
        # 会员储值是否需要输入密码
        self.blend = False
        # 是否触发营销活动
        self.mark = False
        # 是否估清
        self.period = False
        # 打折后是否金额是否为0
        self.zero = False
        self.bill_num = ''
        self.sql = SqL('127.0.0.1', 'xxxxx', 'xxxxxx', 'xxxxxxx', '5432')

    def call_function(self):
        """x点菜、下单、打折、结账操作"""
        self.clickItem()
        self.check_alreadyDish()
        self.click_confirm_order()

    # ----------------------------------登录操作-------------------------------------------

    def test_function(self):
        line_one = self.f.readline()
        self.username, self.password = line_one.split(",")
        # Log().info("用户名:%s,密码:%s" % (self.username, self.password))
        print("用户名:%s,密码:%s" % (self.username, self.password))
        self.login(self.username, self.password)
        self.f.close()
        self.call_function()

    def login(self, username, password):
        """参数化用户名、密码"""
        self.E.input_login_user(username)
        self.E.input_login_password(password)
        self.E.click_login_btn()
        self.checkLoginTan()

    def checkLoginTan(self):
        """判断登录弹框"""
        try:
            loginText = self.E.element_msg()
            if loginText == '用户名或密码错误':
                Log().error('用户名、密码错误,重试中...')
                self.E.click_enter_btn()
                line_two = self.f.readline()
                if line_two:
                    self.username, self.password = line_two.split(",")
                    Log().info("用户名:%s,密码:%s" % (self.username, self.password))
                    self.login(self.username, self.password)
                else:
                    self.f.close()
                    Log().error("没有找到正确的用户名和密码")
                    self.screenShot()
                    exit()
            elif loginText == '收银员未签到':
                Log().warning('收银员还没有签到呢,赶紧签去...')
                self.screenShot()
                exit()
            elif loginText == '当前服务设置为快餐,该程序为e待客正餐版不可用于快餐':
                Log().warning('模式不对啊,大兄弟...')
                self.screenShot()
                exit()
            elif '未绑定收银员' in loginText:
                Log().warning('没有绑定收银员?你特么在逗我玩呢...')
                self.screenShot()
                exit()
            elif '网络链接失败' in loginText:
                Log().warning('没有网...无法登录!!!')
                self.screenShot()
                exit()
            else:
                print('登录出现错误...%s' % loginText)
                self.screenShot()
                exit()
        except NoSuchElementException as e:
            Log().info('我了个草,一切正常....%s' % e)
        except AttributeError as e:
            Log().info('没有发生异常,正在登录^_^ %s' % e)

    # ----------------------------------点菜操作-------------------------------------------

    def clickItem(self):
        """点菜"""
        self.checkTitle('点餐', '没有进入点餐界面诶,出错了吗?')
        # 获取菜品小类数
        itemClasses = len(self.E.elements_dish_class_item())
        Log().info('菜品小类数量是:%s' % itemClasses)
        # 滑动函数
        self.swipeUp(itemClasses, 12, 0.1)
        self.swipeDown(itemClasses, 12, 0.1)
        itemClass = random.randint(0, int(itemClasses - 1))
        # itemClass = 0
        # 选择菜品小类
        self.E.elements_dish_class_item()[itemClass].click()
        # 获取菜品小类名称
        className = self.E.elements_dish_name()[itemClass].text
        Log().info('选择的菜品小类是:%s' % className)
        itemNums = len(self.E.elements_dish_info())
        # 调用滑动函数
        self.swipeUp(itemNums, 12, 0.5)
        Log().info('小类下的菜品数量是:%s' % itemNums)
        if itemNums > 6:
            itemNums = 6
        # 随机点击函数
        n = self.random_clicks(itemNums)
        for i in n:
            # 随机选择菜品
            # i = 2
            print('i:%s' % i)
            self.E.elements_dish_info()[i].click()
            self.check_itemUnit()
        # 点击选好了按钮
        self.E.click_go_shop_car_btn()

    def check_itemUnit(self):
        """判断选择菜品样式"""
        unit = self.E.elements_unit()
        reason = self.E.element_reason_num()
        if reason != "":
            reason = reason.text
            print('reason:%s' % reason)
        Log().info('输出unit:%s' % unit)
        if unit == '规格选择':
            # 选择多规格菜品
            Log().info('选择的菜品是多规格菜品')
            self.moreUnitItem()
        elif '套餐数量' in reason:
            # 多选套餐
            itemName = self.E.element_title()
            Log().info('选择的多选套餐的名字是:%s' % itemName)
            self.E.click_enter_btn()
            self.E.click_enter_btn()
        else:
            Log().info('选择的菜品是单品或固定套餐')

    def moreUnitItem(self):
        """选择多规格菜品"""
        moreUnits = len(self.E.elements_unit_item())
        # Log().info('选择的菜品有%s个规格' % moreUnits)
        print('选择的菜品有%s个规格' % moreUnits)
        moreUnit = random.randint(0, int(moreUnits - 1))
        self.E.elements_unit_item()[moreUnit].click()
        # Log().info('选择的规格是第%s个' % (moreUnit + 1))
        print('选择的规格是第%s个' % (moreUnit + 1))

    # ----------------------------------已点菜品界面-------------------------------------------

    def check_alreadyDish(self):
        """是否进入已点菜品界面"""
        alreadyDish = self.E.element_title_tv()
        self.assertEqual(alreadyDish, '已点菜品', '没有进入已点菜品界面吗?lalala....')
        Log().info('进入已点菜品界面 成功!')
        self.bill_remark()
        self.check_marketing()

    def bill_remark(self):
        """选择全单备注"""
        self.E.click_bill_taste()
        self.E.click_enter_btn()
        self.checkTitle('全单备注', '进入全单备注界面失败了呀!')
        try:
            remarkNums = len(self.E.elements_taste_method_select_item())
            self.swipeUp(remarkNums, 18, 0.5)
            r = self.random_clicks(remarkNums)
            for i in r:
                self.E.elements_taste_method_select_item()[i].click()
        except NoSuchElementException as e:
            Log().warning('没有分配全单备注,请分配...%s' % e)
        self.E.click_enter_btn()

    def check_marketing(self):
        """判断是否存在估清菜品"""
        self.E.click_marketing()
        # 估清函数
        self.check_gu()
        if self.period:
            self.call_function()
        else:
            self.marketing()
            if self.mark:
                self.check_discount_money()

    def check_gu(self):
        """检查估清提示"""
        try:
            textG = self.E.element_msg()
            if textG == '点菜数量大于沽清数量':
                self.period = True
                Log().warning('点菜数量大于沽清数量,正在清除购物车,重新点菜。%s' % self.period)
                self.E.click_enter_btn()
                self.E.click_go_shop_car_btn()
                self.E.click_clear_shop_car_btn()
                self.E.click_enter_btn()
                self.driver.press_keycode(4)
        except NoSuchElementException as e:
            print('所点菜品不包含估清菜品...%s' % e)
        except AttributeError as e:
            print('所点菜品无估清菜品...%s' % e)

    def marketing(self):
        try:
            textM = self.E.element_msg()
            if textM == '没有可用活动!':
                Log().error('选择的菜品没有触发活动...')
                self.E.click_enter_btn()
            else:
                print('选择活动出现错误...%s' % textM)
                self.screenShot()
                exit()
        except AttributeError as e:
            self.mark = True
            Log().info('选择菜品已触发活动,正在选择...self.mark:%s...%s' % (self.mark, e))
            self.checkTitle('营销活动', '没有进入营销活动界面qaq...')
            marketingNums = len(self.E.elements_group_order())
            self.swipeUp(marketingNums, 9, 0.5)
            marketingNum = random.randint(0, int(marketingNums - 1))
            # marketingNum = 0
            # 随机选择活动
            self.E.elements_group_order()[marketingNum].click()
            marketingName = self.E.elements_group_order()[marketingNum].text
            Log().info('随机选择的活动名称是:%s' % marketingName)
            try:
                # 活动是否存在赠送菜品
                marketingItemNums = len(self.E.elements_child_order())
                marketingItemNum = random.randint(0, int(marketingItemNums - 1))
                # 随机选择赠送菜品
                self.E.elements_child_order()[marketingItemNum].click()
                marketingItemName = self.E.elements_child_order()[marketingItemNum].text
                Log().info('赠送的菜品名称是:%s' % marketingItemName)
            except NoSuchElementException as e:
                Log().warning('没有复现元素,选择的活动没有赠送菜品...%s' % e)
            except TimeoutException as e:
                Log().warning('获取元素超时,选择的活动没有赠送菜品..%s.' % e)
            self.E.click_config_btn()

    def check_discount_money(self):
        """核对活动优惠金额"""
        itemNum = len(self.E.elements_dish_name2())
        print('已点菜品界面的菜品数量是:%s' % itemNum)
        self.swipeUp(itemNum, 6, 0.5)
        d_money = self.E.element_discount_money()
        d_money = str(d_money).replace('-¥', '')
        Log().info('参与活动的界面优惠金额是:%s' % d_money)
        p_money = self.sql.decimal_format(
            self.sql.getDate('select discountr_amount from pos_bill a order by a.bill_num desc limit 1;'))
        self.bill_num = self.sql.decimal_format(
            self.sql.getDate('select bill_num from pos_bill a order by a.bill_num desc limit 1;'))
        Log().info('账单%s在数据库显示优惠金额是:%s' % (self.bill_num, p_money))
        self.assertEqual(d_money, str(p_money), '优惠金额核对出错')
        Log().info('账单%s核对优惠金额显示正确!' % self.bill_num)

    # ----------------------------------付款、打折-------------------------------------------

    def click_confirm_order(self):
        """"点击结账按钮"""
        self.E.click_confirm_order_btn()
        self.E.input_table_code()
        time.sleep(1)
        self.driver.press_keycode(66)
        self.E.input_table_remark()
        time.sleep(1)
        self.driver.press_keycode(66)
        self.E.click_enter_btn()
        self.check_gu()
        if self.period:
            self.call_function()
        else:
            self.payment()

    def payment(self):
        """选择付款方式"""
        paymentTitle = self.E.element_title()
        self.assertIn('付款', paymentTitle, '没有进入付款页面?跑那去了?QAQ...')
        Log().info('进入付款页面 成功!')
        self.discount()
        self.check_bill()
        if self.zero:
            self.check_pay_success()
        else:
            p = len(self.E.elements_payment_name())
            Log().info('付款方式有:%s个' % p)
            p1 = random.randint(0, int(p - 1))
            # p1 = 1
            # 调用滑动函数
            self.swipeUp(p, 7, 0.5)
            if self.isMember:
                Log().info('选择会员储值支付方式.%s' % self.isMember)
                self.check_payment_differ()
            else:
                paymentName = self.E.elements_payment_name()[p1].text
                Log().info('选择的付款方式是%s' % paymentName)
                if paymentName == '会员储值':
                    self.E.elements_payment_name()[p1].click()
                    self.search_card()
                    self.check_payment_differ()
                elif paymentName == '会员积分':
                    self.E.elements_payment_name()[p1].click()
                    self.search_card()
                    self.check_payment_differ()
                elif paymentName == '会员票券':
                    self.E.elements_payment_name()[p1].click()
                    self.search_card()
                    self.check_payment_differ()
                elif paymentName == '微信支付':
                    self.E.elements_payment_name()[p1].click()
                    self.third_payment('微信', p1)
                elif paymentName == '支付宝支付':
                    self.E.elements_payment_name()[p1].click()
                    self.third_payment('支付宝', p1)
                elif paymentName == '人民币':
                    self.rmb_pay()
                elif paymentName == 'xxxx':
                    self.rmb_pay()
                else:
                    Log().warning('付款出现异常...%s' % paymentName)

    def discount(self):
        """打折"""
        self.E.click_discount()
        self.checkTitle('打折', '没有进入打折页面?跑那去了?QAQ...')
        r = random.randint(0, 3)
        # r = 1
        Log().info('打折,随机数是:%d' % r)
        if r == 0:
            Log().info('选择折扣方式固定折扣')
            self.E.input_discount_rate()
            self.E.input_discount_money2('0.05')
            self.E.click_enter_btn()
            self.allowance()
            self.discount_reason('打折成功!')
        elif r == 1:
            Log().info('选择折扣方式折扣方案')
            self.E.click_special_discount()
            self.discount_scheme()
            self.E.input_discount_money2('0.05')
            self.E.click_enter_btn()
            self.allowance()
            self.discount_reason('打折成功!')
        elif r == 2:
            Log().info('选择折扣方式会员优惠')
            self.E.click_vip_discount()
            self.isMember = True
            self.vip_card()
        elif r == 3:
            Log().info('选择折扣方式整单折扣')
            self.E.input_bill_discount()
            self.E.input_discount_money2('0.05')
            self.E.click_enter_btn()
            self.allowance()
            self.discount_reason('打折成功!')

    def discount_scheme(self):
        self.checkTitle('折扣方案选择', '没有进入折扣方案选择页面?跑那去了?QAQ...')
        try:
            selected_discounts = len(self.E.elements_discount_name())
            selected_discount = random.randint(0, int(selected_discounts - 1))
            self.E.elements_discount_name()[selected_discount].click()
            self.E.click_enter_btn()
        except NoSuchElementException as e:
            Log().error('没有分配折扣方案,请分配...%s' % e)
            self.screenShot()
            exit()
        except TimeoutException as e:
            print('没有分配折扣方案,请分配...%s' % e)
            self.screenShot()
            exit()


    def vip_card(self):
        """正常流程下的绑定会员卡"""
        self.search_card()
        self.checkTitle('会员消费', '没有进入会员消费页面?跑那去了?QAQ...')
        rate = self.E.element_rate()
        print('rate:%s' % rate)
        if rate == '会员价':
            self.E.click_enter()
            self.discount_reason('会员价使用成功!')
        elif '' in rate:
            self.E.click_enter()
            self.check_discount_success('会员卡绑卡打折成功!')

    def search_card(self):
        """查询会员卡,桌位是否已经绑定会员卡"""
        self.checkTitle('会员检索', '没有进入会员检索页面?跑那去了?QAQ...')
        self.E.input_phone_num()
        self.E.click_search_btn()
        y = self.E.is_text_in_element(alertTitle, '选择会员卡')
        if y:
            Log().info('正在选择会员卡')
            cards = len(self.E.elements_card())
            cardNum = random.randint(0, int(cards - 1))
            # cardNum = 0
            self.E.elements_card()[cardNum].click()
        else:
            Log().error('该会员只有一张会员卡')

    def allowance(self):
        """折让金额大于账单金额"""
        try:
            allowanceText = self.E.element_msg()
            if allowanceText == '折让金额不能大于账单金额':
                Log().warning('折让金额不能大于账单金额,请重新输入折让金额...')
                self.E.click_enter_btn()
                self.E.input_discount_money2('0.00')
                self.E.click_enter_btn()
        except NoSuchElementException as e:
            Log().info('allowance(),没有发现元素:%s' % e)
        except AttributeError as e:
            Log().info('没有出现折让金额不能大于账单金额异常%s...allowance()' % e)

    def discount_reason(self, msg):
        """"选择折扣原因 ---加异常,判断后台是否分配折扣原因"""
        self.E.click_enter()
        self.checkTitle('折扣原因', '没有进入折扣原因页面?跑那去了?QAQ...')
        try:
            discounts = len(self.E.elements_discount_name2())
            discount =  random.randint(0, int(discounts - 1))
            self.E.elements_discount_name2()[discount].click()
            self.E.click_enter_btn()
            self.check_discount_success(msg)
        except NoSuchElementException as e:
            Log().error('没有分配折扣原因,请设置...%s' % e)
            self.screenShot()
            exit()

    def check_discount_success(self, msg):
        """判断是否打折成功"""
        text = self.E.element_msg()
        if text == msg:
            Log().info(msg)
            self.E.click_enter_btn()
        # elif text == '没有达到该折扣的最低账单限额':
        #     Log().warning('没有达到该折扣的最低账单限额!!!')
        #     self.E.click_enter_btn()
        #     self.driver.press_keycode(4)
        #     self.payment()
        else:
            Log().error('check_discount_success()出现错误...%s' % text)
            self.screenShot()
            exit()

    def check_bill(self):
        """检查账单信息,判断使用的打折方式,核对界面显示金额和数据库金额"""
        # 界面显示金额
        payment_money = self.E.element_payment_money()
        # 替换¥
        payment_money = str(payment_money).replace('¥','')
        Log().info('界面显示应收金额:%s' % payment_money)
        money_sql = self.sql.decimal_format(
            self.sql.getDate('select payment_amount from pos_bill order by bill_num desc limit 1'))
        self.bill_num = self.sql.decimal_format(
            self.sql.getDate('select bill_num from pos_bill a order by a.bill_num desc limit 1;'))
        Log().info('数据库金额是:%s' % money_sql)
        try:
            self.assertEqual(payment_money, str(money_sql), '账单应收金额和数据库payment_money不一致,,,')
            Log().info('账单:%s 应收金额和数据库payment_money一致' % self.bill_num)
        except:
            Log().error('-------------金额错误------------')
        if payment_money == '0.00':
            self.zero = True
            Log().info('账单:%s打折后为0元账单...%s' % (self.bill_num, self.zero))

    def check_payment_differ(self):
        """检查付款差额"""
        payment_differ = self.E.element_payment_differ()
        discount_money = str(payment_differ).replace('付款差额:¥ ', '').strip()
        Log().info('付款差额:%s' % discount_money)
        payment_money = self.E.element_payment_money()
        payment_money = str(payment_money).replace('¥', '').strip()
        Log().info('应收金额:' % payment_money)
        if discount_money == '0':
            self.E.click_payment()
            self.E.input_vip_pwd()
            self.driver.press_keycode(66)
            self.check_pay_success()
        # 付款金额和付款差额判断,如果等于0,结账;大于0,差额小于付款金额,会员卡金额不足,rmb支付,需要输入会员密码
        elif discount_money != payment_money:
            self.blend = True
            self.rmb_pay()
        else:
            # 直接人民币支付,不需要输入会员密码
            self.rmb_pay()

    def third_payment(self, third_name, p1):
        """第三方支付"""
        try:
            a = 3
            while a > 0:
                third_paymentTitle = self.E.element_title()
                if third_paymentTitle == third_name:
                    Log().info('打开%s二维码 成功!' % third_name)
                    self.driver.press_keycode(4)
                    self.E.click_cancel_btn()
                    a = a - 1
                    if a != 0:
                        self.E.elements_payment_name()[p1].click()
            self.rmb_pay()
        except:
            third_paymentText = self.E.element_msg()
            Log().error('%s支付出错,原因:%s' % (third_name, third_paymentText))
            self.screenShot()
            exit()

    def rmb_pay(self):
        """人民币支付,需保证rmb支付在支付列表最后一个"""
        Log().info('选择人名币支付方式')
        p = len(self.E.elements_payment_name())
        self.E.elements_payment_name()[p - 1].click()
        self.driver.press_keycode(66)
        if self.blend:
            self.E.input_vip_pwd()
            self.driver.press_keycode(66)
        self.check_pay_success()

    def check_pay_success(self):
        """检查是否弹出支付成功提示"""
        msg = self.E.element_msg()
        if msg == '支付成功!':
            Log().info('支付成功!')
            self.E.click_enter_btn()
            self.call_function()
        else:
            Log().info('出现异常,支付失败!%s' % msg)
            self.screenShot()
            exit()

    # ----------------------------------公共方法-------------------------------------------

    def checkTitle(self, title, errorMsg):
        """封装check title方法"""
        t = self.E.element_title()
        self.assertEqual(t, title, errorMsg)
        Log().info('进入%s页面 成功!' % title)

    def swipeUp(self, total, number, w):
        """向上滑动函数"""
        if total >= number:
            t = 3000
            x = self.driver.get_window_size('width')
            y = self.driver.get_window_size('height')
            # print(x, y)
            x1 = int(x['width'] * w)
            y1 = int(y['height'] * 0.75)
            y2 = int(y['height'] * 0.25)
            self.driver.swipe(x1, y1, x1, y2, t)
            # Log().info('拖拽ing,正在滑动中...')
            print('拖拽ing,正在向上滑动中..')

    def swipeDown(self, total, number, w):
        """向下滑动"""
        if total >= number:
            t = 3000
            x = self.driver.get_window_size('width')
            y = self.driver.get_window_size('height')
            x1 = int(x['width'] * w)
            y1 = int(y['height'] * 0.25)
            y2 = int(y['height'] * 0.75)
            self.driver.swipe(x1, y1, x1, y2, t)
            print('拖拽ing,正在向下滑动中..')

    def screenShot(self):
        """错误截图"""
        path = PATH(os.getcwd() + "/Images")
        # print(path)
        timestamp = time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime(time.time()))
        print('截图时间:%s' % timestamp)
        subprocess.check_call("adb wait-for-device")
        subprocess.check_call("adb shell screencap -p /data/local/tmp/tmp.png")
        if not os.path.isdir(PATH(os.getcwd() + "/Images")):
            os.makedirs(path)
        subprocess.check_call("adb pull /data/local/tmp/tmp.png " + PATH(path + "/" + timestamp + ".png"))
        subprocess.check_call("adb shell rm /data/local/tmp/tmp.png")
        print("screenShot Success!!!")

    def random_clicks(self, amount):
        """定义随机点击次数"""
        clicks = random.randint(0, int(amount - 1))
        # Log().info('随机点击的次数是:%s' % clicks)
        print('随机点击的次数是:%s' % clicks)
        if clicks == 0:
            clicks =1
        # clicks = 6
        t, m = [], 0
        while m < clicks:
            num = random.randint(0, int(amount - 1))
            t.append(num)
            m += 1
        return t

    # ----------------------------------退出-------------------------------------------

    def tearDown(self):
        """退出"""
        self.sql.quitSql()
        self.E.quit()

if __name__ == '__main__':
    unittest.main()
app自动化刚接触没多久,自己摸索中...目前写的只是跑流程<死循环...>...希望看到的大大们留下宝贵的意见...小生在此跪谢ing...
愿你走出半生,归来仍是少年!
原文地址:https://www.cnblogs.com/changqing8023/p/7571786.html