zoukankan      html  css  js  c++  java
  • 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...
    愿你走出半生,归来仍是少年!
  • 相关阅读:
    看完动画你还会不懂 快速排序么
    看动画轻松理解时间复杂度(一)
    LeetCode Animation 题目图解汇总(持续更新中...)
    分而治之,归并排序的动画演示
    在Object-C中学习数据结构与算法之排序算法
    iOS面试准备之思维导图
    .net core跨域设置
    .NET Core WebAPI Swagger使用
    vue-resource emulateJSON的作用
    百度地图API简单初始化
  • 原文地址:https://www.cnblogs.com/changqing8023/p/7571786.html
Copyright © 2011-2022 走看看