用户端App自动化测试
一、capability 进阶用法
1、 deviceName
- 只是设备的名字,别名
- 随便起
- 不能锁定唯一一个设备
2、 uid
- 多设备选择的时候,要指定 uid
- 默认读取设备列表的第一个设备
- 设备列表获取
adb devices
3、 newCommandTimeout
- appium 程序应等待来自客户端的新命令多长时间
- 超时后==会话删除==
- 默认
60
秒 - 设置为 0 禁用
4、 autoGrantPermissions
- 授予启动的应用程序某些权限
5、 PRINT_PAGE_SOURCE_ON_FIND_FAILURE
- 默认为
false
- 发生任何错误,强制服务器将实际的 XML 页面源转储到日志中.
6、 测试策略
- noReset
- fullReset
- dontStopAppOnReset
7、 noReset
- 默认为
false
- 安卓
true
- 不停止应用程序
- 不清除应用程序数据
- 不卸载 apk
8、 fullReset
- 默认为
false
。true
:新会话之前完全卸载被测应用程序 - 安卓
- 在会话开始之前(appium 启动 app)和测试之后停止应用程序
- 清除应用程序数据并卸载 apk
9、 dontStopAppOnReset
- 默认为
false
。 - 不希望应用程序在运行时重新启动,设置为
true
#打开的app退出后重新启动
adb shell am start -S 包名/activity名#打开的app不需要退出,直接使用当前页面
adb shell am start 包名/activity名
二、元素定位工具
1、uiautomatorviewer 工具安装
- 工具的安装:Android SDK 自带的界面分析工具
- 打开
tools/bin
目录下的uiautomatorviewer
程序
2、 uiautomatorviewer 工具功能介绍
- 第一个是通过分析给定的文件定位
- 第二个是将当前界面截图并分析xml结构
- 第三个与第二个功能类似,但它会对页面内容进行压缩,导致一些控件定位不准确
- 第四个是保存当前界面的截图以及xml结构
UiAutomatorViewer界面
3、 weditor 安装与运行
- 要求:python 3.6+ 以上
- 安装:weditor 是 python 的第三方库
pip install weditor
进行安装
- 运行:安装完成之后,在命令行运行
python -m weditor
即可
4、 weditor 功能介绍
- 支持 Android 和 iOS 的界面分析
- 通过设备的 uuid 连接设备
- 展示页面结构
5、 appium inspector 安装与运行
- 下载:下载链接
- 运行 appium inspector
- 运行 appium server
- 本地的 adb 已连接设备
- Desired Capabilities 参数填写
- 点击 Start Session
- 注意:在运行appium inspect 的时候需要检查一下weditor在手机上安装的ATX服务是否停止,因为ATX服务会占用uiautomator2的
6、 appium inspector 功能简介
- 定位的模式相关
- 原生app模式
- 混合模式
- 界面操作相关
- 选择元素
- 坐标滑动界面
- 坐标点击元素
- 其他功能
- 返回
- 刷新页面
- 录制
- 搜索元素
- 复制 xml 结构
7、 对选中元素操作
- 点击
- 输入
- 清空
- 复制元素的属性
- 获取元素的响应时间
- 元素的属性
三、高级定位技巧-xpath 定位
1、 * xpath 函数:包含-contains()
Xpath
表达式中的一个函数contains()
函数匹配==属性值==中包含的==字符串==
//*[contains(@属性,"属性值")]
2、 总结
contains()
函数定位的元素很容易为list
contains()
函数内的属性名需要用@
开始
3、 XPath 轴
- 父子
- 爷孙
- 祖先
- 兄弟姐妹
父子-当前节点的父节点
//*[@text="HK"]/..
//*[@text="HK"]/parent::*
父子-当前节点的子节点
- 当前节点的儿子
//*[@resource-id="com.xueqiu.android:id/stock_layout"]/child::*
爷孙-当前节点的爷爷
- 当前节点的父级的父级
//*[@text="HK"]/../..
//*[@text="HK"]/parent::*/parent::*
爷孙-当前节点的孙子
- 当前节点的儿子的儿子
//*[@resource-id="com.xueqiu.android:id/stock_layout"]/child::*/child::*
祖先-ancestor
- 返回当前节点的所有祖先
//*[@text="HK"]/ancestor::android.widget.RelativeLayout
- 显式指定要返回的祖先
//*[@text="HK"]/ancestor::android.widget.RelativeLayout[1]
兄弟姐妹-sibling
- 节点后的兄弟姐妹节点
- 节点前的兄弟姐妹节点
following-sibling
- 选择当前节点之后的所有兄弟节点
- 节点后有一个兄弟节点
//*[@text="HK"]/following-sibling::*
- 节点后有多个兄弟节点
//*[@resource-id="com.xueqiu.android:id/stock_layout"]/following-sibling::*[@resource-id="com.xueqiu.android:id/price_layout"]
preceding-sibling
- 选择当前节点之前的所有兄弟节点
- 节点前有一个兄弟节点
//*[@text="09988"]/preceding-sibling::*
- 节点前有多个兄弟节点
//*[@resource-id="com.xueqiu.android:id/add_attention"]/preceding-sibling::*[@resource-id="com.xueqiu.android:id/price_layout"]
4、 XPath 运算符
(1)AND
- 可以在
XPath
表达式中放置 2 个条件 - 在
AND
两个条件都应该为真的情况下,才能找到元素
//*[@resource-id="com.xueqiu.android:id/current_price" and @text="107.8"]
(2) OR
- 可以在
XPath
表达式中放置 2 个条件 - 在
OR
的情况下,两个条件中的任何一个为真,就可找到元素。 OR
定位获取的是并集
//*[@resource-id="com.xueqiu.android:id/tv_stock_add_follow" or @text="加自选"]
5、 总结
and
定位是 2 个条件的交集or
定位是 2 个条件的是并集
四、 CSS 定位与原生定位
1、 原生定位
- 官网地址
- 元素属性定位
- 组合定位
# ID 定位
driver.find_element_by_android_uiautomator('\new UiSelector().resourceId("<element-ID>")')# 组合定位
driver.find_element_by_android_uiautomator('\new UiSelector().resourceId("com.xueqiu.android:id/tab_name").\text("我的")')
2、 css selector 定位介绍
- 官网说明
- Android: Appium Server 版本 >= 1.19.0
- iOS:Appium Server>= 1.21.0
driver.find_element(AppiumBy.CSS_SELECTOR,\"#com\.xueqiu\.android\:id\/tv_search")解析前:
{"using":"css selector",\"value":"#com\\.xueqiu\\.android\\:id\\/tv_search"}解析后:
{"strategy":"-android uiautomator",\"selector":"new UiSelector().resourceId(\"com.xueqiu.android:id/tv_search\")",...}
3、 css selector 用法
- 官方示例
# 通过 id
elementById("someResourceID")`-> `elementsByCss("#someResourceID")
# 通过 class
elementsByClassName("android.widget.TextView")`-> `elementsByCss("android.widget.TextView")
# 通过 accessibility id
elementsByAccessibilityId("Some Content Description")`-> `elementsByCss('*[description="Some Content Description"]')
# 通过 xpath
elementsByXpath("//android.widget.TextView[@description='Accessibility']")`-> `elementsByCss("android.widget.TextView[description='Accessibility']")
4、 示例
- 打开【雪球】应用首页
- 点击搜索框
- 向搜索框输入:alibaba
- 判断【阿里巴巴】可见
def test_search1(self):# 点击搜索框element = self.driver.find_element(\AppiumBy.CSS_SELECTOR,"#com\.xueqiu\.android\:id\/tv_search")element.click()# 向搜索框输入:alibabaself.driver.find_element(AppiumBy.CSS_SELECTOR,"#com\.xueqiu\.android\:id\/search_input_text"). \send_keys("alibaba")alibaba_element = self.driver.find_element(\AppiumBy.CSS_SELECTOR, "*[text='阿里巴巴']")displayed = alibaba_element.get_attribute("displayed")print(displayed)# 判断【阿里巴巴】可见assert displayed == "true"print(f"结束时间:{self.get_time()}")
5、 iOS css selector 定位
- Appium Server 版本>=1.21.0
- 官网:Release v1.21.0 · appium/appium · GitHub
6、 总结
- Appium Server 版本>=1.21.0
- css selector 会转化为 Android/iOS 原生定位的定位策略
- Android 转为 Android Uiautomator 定位方式
- iOS 转为 class chain 定位方式
五、特殊控件 toast 识别
1、 Toast 是什么
- 一种消息框类型
- 永远不会获得焦点
- 无法被点击
- Toast显示的时间有限,Toast会根据用户设置的显示时间后自动消失
- 是系统级别的控件,属于系统settings
- Toast类的思想:
- 就是尽可能不引人注意,同时还向用户显示信息,希望他们看到
2、 Toast 定位
- appium 用的是uiautomator底层来抓取toast,
- 再把toast放到控件树内,但是它本身不属于空间
- 使用的是uiautomator2
xpath
可以找到 ``` //*[@class=“android.widget.Toast”]
//*[contains(@text,“xxx”)] ``` xxx:toast的文本内容
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(50));
driver.findElement(AppiumBy.xpath("//*[@class=\"android.widget.Toast\"]"));
from appium import webdriver
from appium.webdriver.common.mobileby import MobileByclass TestToast():def setup(self):desire = {'platformName': 'android','platformVersion': '6.0','deviceName': 'emulator-5554','appPackage': 'io.appium.android.apis','appActivity': 'io.appium.android.apis.view.PopupMenu1',#可以加也可以不加,现在默认就是uiautomator2'automationName' : 'uiautomator2'}self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desire)self.driver.implicitly_wait(5)def teardown(self):self.driver.quit()def test_toast(self):self.driver.find_element(MobileBy.ACCESSIBILITY_ID,"Make a Popup!").click()self.driver.find_element(MobileBy.XPATH,"//*[@text='Search']").click()# print(self.driver.page_source)# print(self.driver.find_element(MobileBy.XPATH, "//*[@class='android.widget.Toast']").text)#获取toast弹框信息print(self.driver.find_element(MobileBy.XPATH, "//*[contains(@text, 'Clicked popup')]").text)
六、显式等待高级使用
1、 Wait 等待
- 强制等待:sleep 不推荐
- 全局隐式等待
- 在服务端等待
driver.implicitly_wait(TIMEOUT)
- 显式等待
- 在客户端等待
WebDriverWait(self.driver,10).until(expected_conditions.visibility_of_element_located(LOCATOR))
2、 显式等待
- 显式等待
- 显示等待与隐式等待相对,显示等待必须在每个需要等待的元素前面进行声明。
- 是针对于某个特定的元素设置的等待时间,在设置时间内,默认每隔一段时间检测一次当前页面某个元素是否存在,
- 如果在规定的时间内找到了元素,则直接执行,即找到元素就执行相关操作,
- 如果超过设置时间检测不到则抛出异常。默认检测频率为 0.5s,默认抛出异常为:
NoSuchElementException
- 显示等待用到的两个类:
WebDriverWait
和expected_conditions
两个类
3、 显式等待
- 显式等待可以等待动态加载的 ajax 元素,显式等待需要使 ExpectedCondtions 来检查条件
- 一般页面上元素的呈现
- title 出现 首先出现 title
- dom 树出现 presence ,还不完整
- css 出现 (可见 visibility)
- js 出现,js 特效执行 ( 可点击 clickable)
- html 文档是自上而下加载的,
- js 文件加载会阻塞 Html 内容的加载,有些 JS 异步加载的方式来完成 js 的加载
- 样式表下载完成之后会跟之前的样式表一起进行解析,会对之前的元素重新渲染
4、 WebDriverWait 用法
- WebDriverWait 用法
- WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
- driver:浏览器驱动
- timeout:最长超时时间,默认以秒为单位
- poll_frequency:检测的间隔步长,默认为 0.5s
- ignored_exceptions:超时后的抛出的异常信息,默认抛出 NoSuchElementExeception 异常。
- WebDriverWait 的 until()和 until_not()方法:
- method: 在等待期间,每隔一段时间(init中的 poll_frequency)调用这个传入的方法,直到返回值不是 False , message: 如果超时,抛出 TimeoutException,将 message 传入异常
- until_not: 与 until 相反,until 是当某元素出现或什么条件成立则继续执行,until_not 是当某元素消失或什么条件不成立则继续执行,参数也相同。
5、 expected_conditions 类
presence_of_element_located
判断元素是否被加到了 DOM 树里,并不代表该元素一定可见- 用法:
WebDriverWait().until(expected_conditions.presence_of_element_located(元素对象))
- 用法:
visibility_of_element_located
判断某个元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于 0- 用法:
WebDriverWait().until(expected_conditions.visibility_of_element_located(元素定位符))
6、 使用 lambda 表达式
WebDriverWait(driver,time).until(lambda x:x.find_element_by_id("someId")
- 返回一个元素
7、 显式等待案例
8、 总结三种等待方式
- 隐式等待,尽量默认都加上,时间限定在 3-6s,不要太长, 为了所有的 find_element 方法都有一个很好的缓冲
- 显式等待,用来处理隐式等待无法解决的一些问题,比如:文件上传(可以设置长一点),文件上传需要设置 20s 以上, 但是如果设置隐式等待, 它会在每个 find 方法都等这么长时间 , 一旦发现没有找到元素, 就会等 20s 以后才抛出异常, 影响 case 的执行效率,这时候就需要用显式等待,显式等待可以设置的长一点
- 强制等待:一般不推荐,前两种基本能解决绝大部分问题,如果某个控件没有任何特征,只能强制等待,这种情况比较少
七、高级控件交互方法
1、 Actions
- Actions
- 执行一系列或多个键盘和指针(触摸、鼠标、触控笔)操作链
- w3c
2、 W3C 事件流
3、 用法
- 定义 ActionChains 实例
- 定义输入源
- 定义动作
# 定义ActionChains 实例
actions = ActionChains(driver)
# 第一步:定义输入源
# ActionChains里有个属性是ActionBuilder类型的, 使用的就是w3c协议
# 可以定义鼠标指针源,键盘源,滚轮源事件
actions.w3c_actions = ActionBuilder(driver, mouse=PointerInput(interaction.POINTER_TOUCH, "touch"))
# 第二步:定义动作
# 移动到起点-> 按下-> 滑动-> 抬起
actions.w3c_actions.pointer_action.move_to_location(115, 183)
actions.w3c_actions.pointer_action.pointer_down()
actions.w3c_actions.pointer_action.move_to_location(362, 179)
actions.w3c_actions.pointer_action.release()
actions.perform()
八、设备交互api
1、 常用的设备交互命令
- 模拟电话、短信
- 网络模式
- 横竖屏切换
- App处理
- 录屏
- 官方地址:http://appium.io/docs/en/about-appium/intro/
2、 官方参考
3、 模拟电话、短信
- appium可以模拟来电话,来短信功能,在app运行过程中收到短信/电话,app如何做处理的,专属的一些场景
- 只支持原生模拟器,不支持mumu,genimotion等
driver.makeGsmCall(PHONE_NUMBER, GsmCallActions.CALL);
driver.makeGsmCall(PHONE_NUMBER, GsmCallActions.ACCEPT);
driver.makeGsmCall(PHONE_NUMBER, GsmCallActions.CANCEL);
driver.sendSMS("555-123-4567", “Appium Test”);
4、 网络设置
self.driver.set_network_connection(1)
self.driver.set_network_connection(4)
def set_network_connection(self, connection_type: int) -> int:"""Sets the network connection type. Android only.Possible values:+--------------------+------+------+---------------+| Value (Alias) | Data | Wifi | Airplane Mode |+====================+======+======+===============+| 0 (None) | 0 | 0 | 0 |+--------------------+------+------+---------------+| 1 (Airplane Mode) | 0 | 0 | 1 |+--------------------+------+------+---------------+| 2 (Wifi only) | 0 | 1 | 0 |+--------------------+------+------+---------------+| 4 (Data only) | 1 | 0 | 0 |+--------------------+------+------+---------------+| 6 (All network on) | 1 | 1 | 0 |+--------------------+------+------+---------------+
5、 横竖屏切换
- 横竖屏切换,官方暂不支持python,以下是java代码。
- 切换成横屏
driver.rotate(Screenorientation.LANDSCAPE)
- 切换成竖屏
driver.rotate(Screenorientation.PORTRAIT)
6、 获取日志
self.driver.log_types
self.driver.get_log("logcat")
7、 其它常用操作
- 锁屏
driver.lock()
- 截图
driver.get_screenshot_as_file('./photos/img.png')
- 录屏:模拟器需要 androidAPI>27,华为不支持,只支持 8.0以上的版本
- 开始录制:
self.driver.start_recording_screen()
- 结束录制:
self.driver.stop_recording_screen()
- 开始录制:
九、模拟器控制
1、 主要内容
- 模拟器自动启动与自动执行测试用例
2、 android 模拟器创建
- Android Studio
- 在命令行启动模拟器
- emulator -list-avds 模拟器列表
- emulator ‘@foo’ or ‘-avd foo’
3、配置
- desirecap里面需要配置
- avd: ‘模拟器名’
- 注意自动启动模拟器,只能是sdk的模拟器,第三方模拟器不支持,7.0不支持
最后:下面是配套学习资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!【100%无套路免费领取】
软件测试面试小程序
被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!
涵盖以下这些面试题板块:
1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux
6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础
全套资料获取方式:点击下方小卡片自行领取即可
相关文章:
用户端App自动化测试
一、capability 进阶用法 1、 deviceName 只是设备的名字,别名随便起不能锁定唯一一个设备 2、 uid 多设备选择的时候,要指定 uid默认读取设备列表的第一个设备设备列表获取 adb devices 3、 newCommandTimeout appium 程序应等待来自客户端的新命…...
[洛谷]P2697 宝石串(经典好题!)
思路: 对于一个类似的东西进行前缀和: G R G G R G G:1 1 2 3 3 4 R:0 1 1 1 2 2 差:1 0 1 2 1 2 所得关于差的数列,同样的数最左最右的位置差为一个答案,选取最大的答案即为解࿰…...
毫米波汽车雷达测试应用指南
汽车毫米波雷达测试背景 车载毫米波雷达通过天线向外发射毫米波,接收目标反射信号,经后方处理后快速准确地获取汽车车身周围的物理环境信息(如汽车与其他物体之间的相对距离、相对速度、角度、运动方向等),然后根据所…...
抖音账号矩阵系统开发源码----技术研发
一、技术自研框架开发背景: 抖音账号矩阵系统是一种基于数据分析和管理的全新平台,能够帮助用户更好地管理、扩展和营销抖音账号。 抖音账号矩阵系统开发源码 部分源码分享: ic function indexAction() { //面包屑 $breadc…...
C++ 33.学习C++的意义-狄泰软件学院
一些历史 UNIX操作系统诞生之初是直接用汇编语言编写的随着UNIX系统的发展,汇编语言的开发效率成为瓶颈,所以需要一个新的语言替代汇编语言1971年通过对B语言改良,使其能直接产生机器代码,C语言诞生UNIX使用C语言重写,…...
[C++基础]-多态
前言 作者:小蜗牛向前冲 名言:我可以接受失败,但我不能接受放弃 如果觉的博主的文章还不错的话,还请点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正。 本期学习目标&am…...
【Kubernetes】当K8s出现问题时,我们可以从哪些方面排查出
前言 kubernetes,简称K8s,是用8代替名字中间的8个字符“ubernete”而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kub…...
SentenceTransformer 之论文解读
摘要 原文标题:Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks 链接:https://arxiv.org/pdf/1908.10084.pdf 尽管Bert和RoBERTa在句子对回归任务上,例如语义文本相似度(Semantic Text Similarity)…...
AI发展历史
一、AI的发展历史 二、AI发展的第五阶段 (一)、第一阶段 1.艾伦图灵与模仿游戏 艾伦•图灵(Alan Turing,1912~1954)是英国数学家、逻辑学家,被称为计算机科学之父,人工智能之父。二战中协助军…...
想要精通算法和SQL的成长之路 - 简化路径
想要精通算法和SQL的成长之路 - 简化路径 前言一. 简化路径 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 简化路径 原题连接 思路如下: 我们根据 "/" 去拆分字符串,得到每个子目录。这里拿到的子目录可能是空字符串,需要…...
【哈士奇赠书活动 - 41期】- 〖产品设计软技能:创业公司篇〗
文章目录 ⭐️ 赠书 - 《产品设计软技能:创业公司篇》⭐️ 内容简介⭐️ 作者简介⭐️ 编辑推荐⭐️ 赠书活动 → 获奖名单 ⭐️ 赠书 - 《产品设计软技能:创业公司篇》 ⭐️ 内容简介 在创业公司设计产品与在成熟公司设计产品存在明显差异。《产品设计软…...
MARS: An Instance-aware, Modular and Realistic Simulator for Autonomous Driving
MARS: An Instance-aware, Modular and Realistic Simulator for Autonomous Driving(基于神经辐射场的自动驾驶仿真器)https://github.com/OPEN-AIR-SUN/marshttps://arxiv.org/pdf/2307.15058.pdfhttps://mp.weixin.qq.com/s/6Ion_DZGJwzs8JOoWMMbPw …...
关联规则挖掘(上):数据分析 | 数据挖掘 | 十大算法之一
⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据开发、数据分析等。 🐴欢迎小伙伴们点赞👍🏻、收藏⭐️、…...
centos7 + citus12 + postgresql 14 安装
1 安装及编译 yum install -y centos-release-scl-rh epel-release yum update -y yum groupinstall -y Development Tools yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm yum install -y postg…...
MySQL、Oracle、SQL Server / MS Access 中的 NULL函数用法
一、MySQL: isnull(exper) 判断exper是否为空,是则返回1,否则返回0 ifnull(exper1,exper2)判断exper1是否为空,是则用exper2代替 nullif(exper1,exper2)如果expr1 expr2 成立,那么返回值为NULL,否则返回值…...
App Store审核被拒原因与解决方案
为了避免不必要的上线延迟及成本增加,了解App Store审核被拒的常见原因以及对应的解决方案是开发人员以及营销人员的必修课。 CSDN相关的解决方案 App Store审核被拒的12个常见原因与快速过审解决方法...
LeetCode解法汇总121. 买卖股票的最佳时机
目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 描述: 给定一个数…...
【Go】go-es统计接口被刷数和ip访问来源
go-es模块统计日志中接口被刷数和ip访问来源 以下是使用go的web框架gin作为后端,展示的统计页面 背景 上面的数据来自elk日志统计。因为elk通过kibana进行展示,但是kibana有一定学习成本且不太能满足定制化的需求,所以考虑用编程的方式…...
debian 安装 pg --chatGpt
pgt: 要在Debian上安装PostgreSQL (通常缩写为PG) 数据库,您可以使用apt包管理器来执行安装操作。以下是安装PostgreSQL的步骤: 1. 打开终端。 2. 使用sudo权限以管理员身份运行以下命令,以更新包信息并安装PostgreSQL: bash …...
商城小程序代客下单程序开发演示
一款专为传统电商、实体商家开发的商城系统小程序,做私域、做留存、做社交必备功能全都有。 1、丰富的营销玩法:拼团、秒杀、定金预售、分销、社区团购、积分商城、支付有礼等主流获客玩法都有。 2、强大的会员体系:普通会员、付费会员、会…...
SpringBoot 整合 jetcache缓存
目前 jetcache 支持的本地缓存方案有两种,远程缓存支持两种,分别如下: 本地缓存(Local) LinkedHashMapCaffeine 远程缓存(Remote) Redis Tair 依赖导入 <dependency><groupId>…...
HTML5+CSS3+移动web 前端开发入门笔记(二)HTML标签详解
HTML标签:排版标签 排版标签用于对网页内容进行布局和样式的调整。下面是对常见排版标签的详细介绍: <h1>: 定义一级标题,通常用于标题栏或页面主要内容的标题。<p>: 定义段落,用于将文字分段展示,段落之…...
Maven 配置阿里云镜像
1. 查找maven setting.xml配置文件 find / -name "setting.xml" 2. 添加阿里云镜像 修改maven根目录下的conf文件夹中的setting.xml文件中的mirrors下添加mirror标签 <settings> <localRepository>E:\Maven\repository</localRepository> <…...
矢量图绘制软件EazyDraw mac中文版软件介绍
EazyDraw mac是一款功能强大且易于使用的矢量绘图软件。 EazyDraw mac软件介绍 矢量绘图工具:EazyDraw 提供了一套全面的矢量绘图工具,包括直线、曲线、多边形、文本框、图形填充等。用户可以使用这些工具创建和编辑精确的矢量图形,无论是简…...
Cocos Creator3.8 项目实战(四)巧用九宫格图像拉伸
一、为什么要使用九宫格图像拉伸 相信做过前端的同学都知道,ui (图片)资源对包体大小和内存都有非常直接的影响。 通常ui 资源都是图片,也是最占资源量的资源类型,游戏中的ui 资源还是人机交互的最重要的部分ÿ…...
怎么使用jenkins设置web自动打包
在Jenkins中设置Web自动打包需要完成以下步骤: 1.环境基础 安装Jenkins:首先,你需要在服务器上安装Jenkins。 你可以从Jenkins官网下载Jenkins的安装包,并按照官方指导进行安装。 2.使用jenkins设置web自动打包步骤 创建Jenk…...
完美解决 flex 实现一行三个,显示多行,左对齐
效果图 代码 <body><section class"content"><div class"item">元素</div><div class"item">元素</div><div class"item">元素</div><div class"item">元素</di…...
初识Spring
目录 1.Spring 基础 2.传统程序开发 3.IoC程序开发(解耦) 4.DI 4.1 IoC 和 DI 有什么区别 1.Spring 基础 Spring 指的是 Spring Framework(Spring 框架),它是⼀个开源框架,有着活跃⽽庞⼤的社区&…...
Mybatis 使用参数时$与#的区别
之前我们介绍了mybatis中参数的使用,本篇我们在此基础上介绍Mybatis中使用参数时$与#的区别。 如果您对mybatis中参数的使用不太了解,建议您先进行了解后再阅读本篇,可以参考: Mybatis参数(parameterType)https://blog.csdn.net…...
网络公司网站建设/昆明百度推广开户费用
中科院外籍院士姚期智:科学家与科学之路 ■姚期智我从事科学工作几十年,也认识了很多杰出的科学家。我自己觉得科学家的生涯很有收获,当科学家是一个非常好的体验,从中可以品尝到巨大的乐趣。首先,我要谈一谈什么是科…...
做橙光游戏的网站/web成品网站源码免费
一、集合操作 1.UNION:并集运算。 语法结构: SQL>select 表1的列1, 表1的列2 from 表1 union select表2的列1, 表2的列2 from表2; 其中表1的列1和表1的列2是来自于表1的两列,表2的列1和表2的列2是来自于表2的两列,需要注意…...
哪个网站可以做加工代理的/seo培训机构
参考资料:http://blog.csdn.net/wo_984633714/article/details/52869851 安装tfs2015的时候,提示需要安装KB2919355的更新。然后我就去下载了,使用了百度云网盘的那个离线安装。然后安装这个更新。 提示KB2919355这个更新有问题? …...
wordpress如何设置301/武汉企业seo推广
模板介绍 精美PPT模板设计,淡雅个人简历自我介绍PPT模板。一套个人简历幻灯片模板,内含蓝色多种配色,精美风格设计,动态播放效果,精美实用。 一份设计精美的PPT模板,可以让你在汇报演讲时脱颖而出。 希望…...
做自媒体的网站/深圳seo关键词优化外包公司
$()、用来作命令替换${ }用来作变量替换(以下内容来自shell十三问)(1). 变量的界定$ AB$ echo $AB该命令执行时,将AB整体看作一个变量,而不是变量$A与字母B的连接。$ AB$ echo ${A}B该命令执行后将输出:BB(2). 特…...
佛山网站制作建设/美国最新消息今天 新闻
作者:朱金灿 来源:clever101的专栏 CMake的优点 CMake在开源代码中最常见的应用场景之一是生成很多平台的makefile或者project文件,这种统一管理的方式确实有其方便之处。尽管CMake有一些优点,我依然不建议使用CMake。下面我要谈…...