直接划 1/4 是有点粗暴了,确实任意 1/4 好点。但没想好具体要怎么判定,直接连接 4 个 label 中心点,有可以出现凹多边形,面积不够 1/4 但如果忽略凹点可能就够 1/4,应该也算作有问题
可以直接写下伪代码分享一下完整算法?
感觉这个像是比较另类的算法题,包了个导航的壳,实际考察内容和导航算法啥的没半毛钱关系。题目里已经给了可用的变量和函数(function 翻译为模块感觉怪怪的,个人更喜欢用函数这个名字),并且限制只能用标准库,意思就是根据变量和函数的组合来解题。
大概写了下:
a.从性能角度考虑,地图中每四分之一的部分中不能显示超过三个 POI 标识
def is_more_than_3_label_in_each_quater_screen():
"""
判断地图中每四分之一的部分中不能显示超过三个 POI 标识。如果超过返回 True ,否则返回 False
"""
# 把图拆为4部分(每个大小540*245)
areas = [
{"startX": 0, "startY": 0, "endX": 540, "endY":245},
{"startX": 541, "startY": 0, "endX": 1080, "endY":245},
{"startX": 0, "startY": 246, "endX": 540, "endY":490},
{"startX": 541, "startY": 246, "endX": 1080, "endY":290}
]
for area in areas:
# 每个部分分别先用 getText 看下有没有文本。没有文本说明没有标签,直接略过
if getText(area["starX"], area["startY"], area["endX"], area["endY"]):
# 有文字,进一步判定有没有标签。实际这个判断可以融合到上面 if 里面,只是为了便于阅读单独拎出来
if _is_has_more_than_3_label(area):
return True
return False
def _is_has_more_than_3_label(area):
"""
判断当前区域里面是否有3个 PIO label
Args:
area: 一个记录区域起始结束位置的字典。示例:{"startX": 0, "startY": 0, "endX": 540, "endY":245}
"""
label_count = 0
label = {"width": 100, "height": 30}
# 判定下有没有标签。标签特征是大小为100*30,且最外面2px是红色。可以通过获取像素颜色值判定下
current_x = area["startX"]
current_y = area["startY"]
# 遍历每个像素点
while current_x <= area["endX"]:
while current_y <= area["endY"]:
# 判定是不是红色,是的话说明有标签,因为只有标签会有红色
if getColor(current_x, current_y) == "red":
label_count += 1
# 有标签,直接可以跳过这个标签大小区域了。
# 如果刚好某个标签横跨2个区域,那它在当前区域的大小就不一定是这个固定值
# (这里暂且把这种只有一部分在区域内的也算作这个区域内标签,实际可能还得搞个判定算法,达到几分之几才算在这个区域内)
# ,不过也不可能会在跳过的位置中间藏了一个标签漏检测,所以不影响标签数量判定。
# 但如果加上标签可能会重叠,那就会更复杂。实际项目个人实在不推荐这么玩哈,直接拿原始接口数据更好
current_x += label["width"]
current_y += label["height"]
# 标签边框里的红色宽度是2,但考虑到有可能命中红色的时候并不是刚好就是边框,所以还是逐个像素遍历吧,也没多少次循环。
y += 1
x += 1
return label_count > 3
到达信息框中显示的预期到达时间应该始终基于到达目的地之前的预期平均速度
写代码有点花时间了,写思路吧:
1、根据 variable 拿到平均车速、当前时间
2、用 getText 直接拿整个地图的 text ,用正则提取出到达信息里的 剩余距离、预计到达时间 (当然也有点风险,比如刚好就有个 PIO Label 也符合正则表达式内容可能就会误判了。最靠谱还是遍历整个图像找那个显示剩余距离剩余时间的框,再从框里提取文字)
3、预计到达时间 - 当前时间获得背后程序计算出来的剩余时长,然后用剩余距离/剩余车速再手动算一个剩余时长,比较一下。特别注意的是 24 小时制这个点,不确定标准库意思是能不能用 datetime 之类的,不允许的话要自己写个小函数来算两个时间差异的小时值
最后,多提一嘴,如果是实际项目,问题一还是找开发去开放一些接口,用于获取背后的数据吧。用图像识别纯黑盒测试,效率不高,投入不少(比如还得像上面这样自己像个算法),直接基于数据简单多了。
问题二的话,这个计算逻辑应该不太复杂,直接 review 代码可能效率更高。
是否可以分享下一些当时提出的问题和你的回答?这个问题好抽象,不同公司,甚至不同人都会有不同的关注点。
要说共性的话,个人感觉更多会关注你的一些主动性、学习潜力、协调能力之类的,就是软技能相关的吧。因为硬技能类前面面试能过说明都没太大问题了。
有用 xcode inspector 来查看 UI 结构不?有的话方便直接截个完整的结构图么?
appium 底层是用 XCUITest 获取控件树的,能拿到的空间 xcode inspector 应该也可以看到。如果 xcode inspector 看不到,说明实际这个控件就是不存在,而不是被别的东西盖住。
另外,如果实在拿不到空间,除了坐标,也可以考虑用图像识别来获取控件位置,相对来说适配性会好一些。
每个人都可以有自己的选择,如果觉得匿名区的一些问题不是自己想浏览的内容,可以屏蔽匿名区哈。
相比吐槽,个人更倾向于引导,吐槽容易引起对抗,引导容易引起改变。并不是每个人都故意做伸手党的,很可能只是他们成长环境让他们提问方面比较直接简单。如楼上不少人所说,很多人都是从小白走过来的,愿大家多一些善意,多一些包容吧。
这描述有点抽象。查了下图例提到的一些容器名字,应该是用了 JXPagingView 这个控件库。暂时没搜到这个控件和 appium 配合使用的相关文章。
建议拿下源码,本地用 xcode debug 看下实际 UI 层级结构有什么特别,是不是可以拿到你图中粉色部分的控件?可以参考 https://blog.csdn.net/PZ0605/article/details/50670285
是不是可以了解下,开发具体改了啥?为啥改完就找不到了?既然都做 UI 自动化了,就不要把被测 app 当黑盒了,去了解下开发改动逻辑吧。
无法找元素 A,是整个树结构变了,还是元素属性变了,还是元素直接从树结构里消失了?这张截图啥都看不出来。
麻烦提问的时候,把这些信息补充完整吧。完整了解问题信息是分析问题的前提,问题是啥都不知道,怎么解决无从谈起。
从你的描述看,服务端应该是根据 cookie 来判定账号的。
requests.session() 本身设计是用来在整个会话过程中保持一些配置继续复用,避免每次都要重复配置的,和你这个需要有多个配置,不同位置要用不同配置有点差异。
如果确实是通过 cookie 判定账号,你可以全局设定每个账号角色的 cookies 值,然后使用 requests.session() 前手动设定里面内置的 cookies 试试?
具体怎么设定 cookies 找到了这篇文章,可以参考下:https://www.jianshu.com/p/264955856e61
adb 命令就可以调起,但出于安全原因需要开发在 app 里设置这个 activity 是可被外部调起的,否则会提示无权限之类的。
还有一种叫 deeplink 的技术,可以直接跳转到想去的页面,更加通用,但需要开发配合,在 app 里面加代码来提供。
很详尽的说明,赞~
多说一句,上面提到的这些问题的修复,可以提 pr 到 appcrawler ?
不知道具体组织情况,仅针对提到的 3 个能力分享下自己大概想到的:
专业能力:内部高级别的同学做定期分享培训、协同外部一些机构提供培训学习机会(如批量购买极客时间课程、设立技术图书库等)、设立专业能力强人之类的奖项定期奖励
创新能力:参加外部会议(如 MTSC、沙龙等)了解外部情况、设立创新能力强人之类奖项、日常工作安排能挤部分时间让能人去做一些创新探索性工作
协同能力:团建、项目复盘、设立技术 PM 统筹他参与需求的全流程进度及风险,为项目按时完成负责,并定期有对应优秀技术 PM 奖项进行奖励(个人觉得,为项目负责的想法是协同的前提,这个技术 PM 能把想法变为职责,让大家去突破。老想着是别人的事自己不去管,容易导致只管自己,协同效率低下)
leetcode
曾经想问大佬练算法题有没有用,想了下还是自己先练下再问吧。
这个点赞!
对于有没有用这个话题,个人感受上来讲是有用的,主要是锻炼编程思维和代码熟练度,也让自己对写代码更自信。
只是从实际工作上,更多时候关键点是是否使用了适当的框架和用法是否正确,很多逻辑都是比较简单的,类似算法题里面这种复杂度的问题比较少,所以直接改变当前工作这种感觉会相对弱一些,所以容易有 “面试造火箭,进来拧螺丝” 的感觉吧。
这个问题略大,不知道怎么回答你。以自己理解简单说下把:
首先需求只有个 峰值 20w 用户 ,是不能直接转化为场景的。需要分析抢券这个场景涉及哪些接口请求(比如查券接口 - 抢券接口),然后这些接口请求的频率大概会多高(比如查券可能一秒一次,抢券从头到尾只有一次),把需求转换为抢券时各个接口大概每秒会承受多少次请求,即要达到多少 tps,接口请求之间比例大概多少这些。这些最好和后端开发沟通下,他们对自己系统最熟悉
建议可以买些书或者极客时间的课程看下,这样效果才好。个人推荐极客时间高楼老师的课,讲得比较简单易懂。
根据日志直译,10 秒内没有获取到界面元素树根节点信息。
一般多见在一些动态界面上,你公众号具体啥内容,可以补充一下相关信息?
java 为主,和开发保持一致,便于查看开发代码逻辑。
额,你这个 java 例子,测试用例还是只有 kotlin 的。我指的是测试用例就是 java 的。
虽然 kotlin 只要有 idea 都很便捷地跑起来,但还得临时学一些语法才知道怎么改里面的内容。如果有直接 java 版会好很多。
针对这个首次打卡的用例,setUp 的时候注册个新账号。其他的不变,这样改动会不会少点?
好,加了仓库后好了。感谢
我特意再限制了只跑 util 包里的,避免依赖其他东西跑不出来。看跑出来结果还有些效果,部分空指针没做好处理的有发现了。但也有一些无效的失败,比如文件名是随机的,导致文件不存在,文件 io 操作报异常导致失败;或者 json 格式错误,导致 Json 解析失败。
从目前情况看,会有一定的误报,测试结果还是得人工二次确认。找空指针或者数组越界有一定效果,但业务逻辑就基本都不怎么能校验到了。
PS:建议给些用 java + maven 的例子? kt + gradle 在 android 比较流行,但非 android 相对比较少。
不清洗数据的话,可以每次都用新数据吗?比如每次注册个新账号,这样比较简单。
对 kotlin 版本啥的有要求么?拿个开源项目加上文档里给的测试代码试了下,没能跑起来
对应项目地址:https://github.com/chenhengjie123/AgileTC/tree/try-randunit ,分支是 try-randunit 。
运行方式是直接在 idea 中点击测试用例前面的执行按钮触发执行。
错误提示:
java.lang.NoClassDefFoundError: org/jeasy/random/EasyRandomParameters
at com.williamfzc.randunit.mock.EasyRandomMocker.genDefaultEasyRandomParameters(EasyRandomMocker.kt:31)
at com.williamfzc.randunit.mock.EasyRandomMocker.<init>(EasyRandomMocker.kt:23)
at com.williamfzc.randunit.models.MockModel.<init>(MockModel.kt:31)
at com.williamfzc.randunit.env.AbstractTestEnv.<init>(AbstractTestEnv.kt:32)
at com.williamfzc.randunit.env.NormalTestEnv.<init>(NormalTestEnv.kt:21)
at com.williamfzc.randunit.env.NormalTestEnv.<init>(NormalTestEnv.kt:20)
at com.xiaoju.framework.SmokeTest.<clinit>(SmokeTest.kt:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.runners.Parameterized.allParameters(Parameterized.java:280)
at org.junit.runners.Parameterized.<init>(Parameterized.java:248)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.ClassNotFoundException: org.jeasy.random.EasyRandomParameters
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 30 more
不知道楼主想要的完整资料,完整到什么程度?
一般自动化框架需要提供三个层次的能力,核心层(提供用例执行管理能力,比如 testng )、工具层(提供触发关键操作的能力,比如接口测试中的 rest-assured,UI 自动化中的 appium、selenium)、适配层(【可选】提供用例编写的模板或规范,减少重复提高编写效率。比如提供 excel 或者 yml 写用例的方式)。
常见组合:
核心层:testng + reportNG/Allure report/extentreports,或直接 junit(比较少见)
工具层:rest-assured(调用接口 + 断言一条龙提供)/基于 httpclient 自行封装/基于其他 http 框架自行封装
适配层:单接口常见用 excel/yml(一般结合 testng 本身提供的 dataProvider 使用),多接口多见直接写代码(代码里区分单接口调用层、多接口业务操作层,用例是通过调用这两层的方法来完成操作)
因为大多都是自行组装,根据各个团队自身水平来决定框架怎么做,不同层根据需要可以用不同的框架去组合完成。因为这里面用的最多的是 testng ,所以它相关文章会比较多也不奇怪。
能不能说明下,为何用例里会存在这个接口调用两次的情况,是本身为了校验两次调用返回值不同故意这么做,还是别的而原因?
个人理解,只要能明确区分接口是第一次被调用还是非第一次,这个断言写起来和普通的没啥差别。至于 message 要不要校验,看业务场景中的重要程度吧。一般前端代码逻辑里只会用 code ,不同 code 走不同的逻辑。而 message 一般直接展示,不会针对性做什么业务逻辑的,所以就算有问题,也只影响用户体验,不一定影响具体功能。当然到底是不是这样,最好你问下项目里的开发同学确认下。
额,这问题有点伸手了,直接搜索引擎找 “cookies 跨域” 都能找到不少相关文章,很常见的问题。
截个图看看?从你发的信息看,这个控件是 safari 浏览器的地址栏。地址栏在滑动时会自动收起的,是不是和这个有关?
PS:不知道你点击地址栏是不是为了设定网页地址,如果是,可以直接用 webdriver 的 api 设定地址的,不用直接点这个地址栏控件。