目录结构如下:
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, subprocessfrom 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:\TestProject\Test_edaike\date\user.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...
时间: 2024-10-06 02:28:27