最新要闻
- 难念的经是哪个电视剧主题曲?难念的经粤语谐音歌词
- 电视剧小爸爸插曲有哪几个?电视剧小爸爸插曲大全
- 女生熬夜打游戏角膜上皮脱落!医生称严重需手术换角膜:一定要控制
- 今日要闻!后路堵死!苹果关闭iOS 16.3验证通道
- 洁癖福音!通用汽车申请自清洁触摸屏新专利:可自动清除屏幕指纹
- 36个月超长质保行业天花板!魅族20系列超前预订来了:只要1元
- 天天快消息!二步法免疫组化试剂盒的详细介绍
- 世界视讯!每年分红不低于净利润一半!格力宣布将发56亿现金分红
- 热门看点:土耳其再发生6.4级地震 现场视频曝光:地动山摇
- 爱奇艺恢复会员投屏!“限制投屏案”原告:集体发声的结果
- 周鸿祎:比尔盖茨低估了ChatGPT的价值
- 当前播报:日本游客不舍告别 旅日大熊猫“香香”今天回家了!下午飞抵成都
- 环球看点!买部iPhone 14要花你多少年薪?各国对比:国人要12% 印度近50%
- 环球焦点!山东人坐地铁不拉手环直接抓杆引围观:人均身高1米8名不虚传
- 12岁女孩玩手游充值近3万 父亲要求退被拒:网友热议不该退 家长原因
- 中秋节的儿童画怎么画_中秋节的儿童画怎么画简单的
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
【天天播资讯】一台不容错过的Java单元测试代码“永动机”
作者:京东零售 陈志良
(资料图片仅供参考)
作为一名京东的软件匠人,我们开发的软件支撑着数亿的用户,责任是重大的,因此我们深深地敬畏每一行代码,那如何将我们的失误降到最低呢?那就是单元测试,它会让我们树立对代码的自信心。为此我们期望能打造一台生产Java单元测试代码的“永动机”,源源不断地为开发者生产代码,辅助大家高效地做好单元测试,节省精力能投入到更多的业务创新中去。
一、开发者对代码的自信心来自哪里?
京东随着业务高速发展,我们缔造的、承载着数亿用户的、功能强大的系统,在经过十多年的打磨,也变得日益复杂。作为JD软件开发者,我们是自豪的,但我们承担的责任也是重大的。我们每一次的创新,就像打造一座下图这样的过山车。我们在为客户带来如此顶级体验的同时,更重要的是保障每一次的旅行都可以安全地着陆。所以我们深深敬畏每一行代码,努力将我们的失误降到最低,为业务保驾护航。
然而,业务的迭代速度之快,交付压力之大,作为“过山车”的缔造者,你是否有以下的经历?
1)每一次上线也像坐了一次过山车呢?
2)你亲手打造的“过山车”,自己是否亲身体验过呢?
3)你是否曾对测试同学说,“你们先上去坐坐看,遇到了问题再下来找我”?
如果你的答案是:每一次上线也像坐了一次过山车,我们自己打造的“过山车”自己不敢坐,我们的代码要靠测试同学兜底,那么就说明我们对自己的代码是缺乏信心的,我们的工作还有待提升的空间;反之则说明,作为一个开发者你已经相当优秀了。
那么如何让我们开发者建立对自己代码的信心呢,一般来说有两种方式:
1)对“过山车”的每个零件都进行充分的测试,保证每一部分在各种场景下都可以正常工作,对所有的异常也能够处理得当,这即是单元测试。
2)对“过山车”启动前做好充分“检查”,这即是代码评审,我们邀请其他大佬帮我们把关,及时发现问题。
这两部分工作在开发阶段都是必要的工作,二者缺一不可。
代码评审是借助了外力,单元测试则是内功,靠自己,靠开发者自测来增强对代码的信心。
本文主要和大家一起探讨单元测试,如何把这单元测试的内功练好。
二、做好单测,慢即是快
对于单元测试的看法,业界同仁理解多有不同,尤其是在业务变化快速的互联网行业,通常的问题主要有,必须要做吗?做到多少合适?现在没做不也挺好的吗?甚至一些大佬们也是存在不同的看法。我们如下先看一组数字:
“在 STICKYMINDS 网站上的一篇名为 《 The Shift-Left Approach to Software Testing 》 的文章中提到,假如在编码阶段发现的缺陷只需要 1 分钟就能解决,那么单元测试阶段需要 4 分钟,功能测试阶段需要 10 分钟,系统测试阶段需要 40 分钟,而到了发布之后可能就需要 640 分钟来修复。”——来自知乎网站节选
对于这些数字的准确性我们暂且持保留意见。大家可以想想我们实际中遇到的线上问题大概需要消耗多少工时,除了要快速找到bug,修复bug上线,还要修复因为bug引发的数据问题,最后还要复盘,看后续如何能避免线上问题,这样下来保守估计应该不止几人日吧。所以这篇文章作者所做的调研数据可信度还是很高的,
缺陷发现越到交付流程的后端,其修复成本就越高。
有人说写单测太耗费时间了,会延长交付时间,其实不然:
1)研测同学大量的往返交互比编写单测的时间要长的多,集成测试的时间被拖长。
2)没经过单测的代码bug会多,开发同学忙于修复各种bug,对代码debug跟踪调试找问题,也要消耗很多精力。
3)后期的线上问题也会需要大量的精力去弥补。
如果有了单元测试的代码,且能实现一个较高的行覆盖率,则可以将问题尽可能消灭在开发阶段。同时有了单测代码的积累,每次代码改动后可以提前发现这次改动引发的其他关联问题,上线也更加放心。单测虽然使提测变慢了一些,软件质量更加有保障,从而节省了后续同学的精力,从整体看其实效率更高。
所以做好单测,慢即是快。
我们集团技术委员会大佬们从去年开始也在倡议大家做单元测试,
做为一名开发者我们需要对自己的代码质量负责,
也更能体现我们大厂开发者的工匠精神。
三、如何编写单元测试
1、单元测试的主流框架及核心思想
以下我们先通过一个案例介绍下主流框架的思想。下图为一个简单的函数执行逻辑,在函数体内直接调用了函数1、函数2、函数3,间接调用了函数2.1,其中1和2分别是普通函数,2.1和3涉及到外部系统调用,例如JSF、Redis、MySQL等操作,最后返回结果。
代码大致如下:
public class MyObject { @Autowired private RedisHelper redisHelper; public MyResult myFunction(InputParam inputParam){ MyResult myResult = new MyResult();//普通代码块 if(inputParam.isFlag()) { //如果标记flag为true,则执行函数1 String f1 = invokeFunction1(); //调用函数3,函数3封装了redis中间件操作 String f3 = redisHelper.get(f1); myResult.setResult(f3); } else { //调用函数2,在函数2内部又调用远程服务接口2.1 String f2 = invokeFunction2(); myResult.setResult(f2); } return myResult; }
在当下微服务时代,系统间的交互变得更加日益复杂,以上图例只是简化的例子,实际系统中的上下游外部依赖多达十几个,甚至几十个。
在这种情况下,如果过度依赖外部服务就很难保障每次用例执行成功,会影响到单元测试的执行效果。
所以,当前主流的单元测试框架大都采用了mock技术,来屏蔽对外部服务的依赖,例如:mockito、powermock、Spock等。
图例中2.1和3即是对外部系统的调用,单元测试代码中需要将其API进行mock,在用例运行时运用mock技术模拟外部API接口的返回值,具体写法此处不作举例。
要注意的是,使用Mock技术的框架需要注意两个前提:
1)接口契约是相对稳定的(例如redis的api暂时不会发生变化),否则就需要调整测试用例代码以适应最新的接口契约,如果不调整则此单元测试用例代码是无效的。
2)接口调用是幂等的,同样的入参需要返回相同的结果,否则用例中的断言会失败或者需要对断言进行特殊的处理,例如比较时忽略某些变化的内容(如id、时间等)。
2、第1种单元测试用例的编写方案
接下来写一段基于mockito框架的测试代码,下图中的做法是,开发者编写了一个用例,对外部函数2.1和3进行了mock,然后在测试用例中调用待测函数,再对返回值进行断言。
示意代码如下:
//创建函数2.1的mock对象 @MockBean private JSFService myJSFService; //创建函数3的mock对象 @MockBean private RedisHelper redisHelper; @Autowired MyObject myObject; @Test public void testMyFunction(InputParameter parameter) { //根据入参mock返回数据 when(myJSFService.invoke(parameter.getX())).thenReturn(X); when(redisHelper.get(parameter.getY())).thenReturn(Y); //期望结果 MyResult expect = new Result(XXX); //实际调用被测试函数,返回结果 MyResult actual = vmyObject.myFunction(parameter); //断言 Assert.assertEquals(actual.toString(), expect.toString());
运行该用例后,除了待测函数,连带函数1、2一起都被测试到了,在实际中调用链路会更加复杂,那么这种写法如何呢?我们做个简要的分析:
1)优点:用例的编码量较少,实现速度快,一个用例覆盖了3个函数,整个业务执行路径也都被测试到了,另外单测覆盖率的指标不受影响,只要执行过的代码都会被统计到。
2)缺点:如果用例失败,那么去定位问题会较慢,实际项目中链路会更加复杂,因此排查问题的时间会大幅度增加,假设问题发生在函数1或2中,那么就需要通过debug跟踪逐步排查。
那么这样的做法究竟如何?到这里如果测试的同学看到肯定会有疑问,这样做的用例跟集成测试阶段的自动化用例有啥区别?是的,从效果上看是一样的,只不过将运行转移到了开发阶段。对于排查和定位问题仍然比较困难,所以从真正的效果出发,不建议只是这样做,请往下看。
3、第2种单元测试用例的编写方案
第2种方案是对每一个方法都写用例代码,每个方法是独立的功能单元,隔离该被测方法的全部依赖,将外部依赖的调用都做好mock。大致的做法类似下图:
待测函数的测试用例中会涉及到3个mock,分别是函数1、2、3;函数1、函数2也都有自己的测试用例,这样做出来的单元测试效果会更好。在Java中方法是一个最小存在的可测试单元,所以对每个方法进行独立的充分测试,那么组装后就可以充分保障代码的整体质量,同时也能快速的定位问题,实现快速交付。
目前,业界开发者大多采用第一种偏集成测试的写法,因其工作量相对较小,在交付压力较大的时候,甚至会放弃单元测试,这种情况在互联网行业尤为普遍。在单元测试不足的情况下,则需要靠增强测试人员的人力来缓解质量问题,但当前业务增长压力渐渐显现,各大公司都聚焦于内部提效,人力成本控制更加严格。打铁还需自身硬,当下我们每一位开发者都需要加强自身的内功修炼。
综合以上两种方案,小结如下:
1)为每个方法写单元测试的测试用例,本方法外部调用均为mock。
2)编写一小部分集成测试用例,对整体功能进行部分验证,集成测试主要工作还是交给测试同学。
四、单元测试应遵循的一些原则
目前行业比较流行的有FIRST原则,整理如下
1)Fast,快速
单元测试用例是执行一个特定任务的一小段代码。与集成测试不同的是,单元测试很小很轻,尽量做到没有网络通信,不执行数据库操作,不启动web容器等耗时操作,使它们能快速执行。开发者在实现应用程序功能时,或者调试bug时,需要频繁去运行单元测试验证结果是否正确。如果单元测试足够快速,就可以省去不必要浪费的时间,提高工作效率。
2)Independent/Isolated,独立/隔离
单元测试的用例需要是相互独立的。一个单元测试不要依赖其它单元测试所产生的结果,因为在大多数情况下,单元测试是以随机的顺序运行的。另外,用例代码也不应该依赖和修改外部数据或服务等共享资源,做到测试前后共享资源数据一致,可以用mock或stub的方式对依赖项进行模拟,屏蔽这些依赖项的不确定性,确保单元测试结果的准确性。
3)Repeatable,可重复
单元测试需要保持运行稳定,在不同的计算机、不同的时间点多次运行,都应该产生相同的结果,如果间歇性的失败,会导致我们不断的去查看这个测试,不可靠的测试也就失去了意义。
4)Self-Validating,自我验证
单元测试需要采用Assert相关断言函数等进行自我验证,即当单元测试执行完毕之后就可得知测试结果,全程无需人工介入,不应该在测试完成后做任何额外的人工检查。注意在单元测试中不要添加任何打印日志的语句,避免通过打印出日志才能判断单元测试是否通过。
5)Thorough/Timely,彻底/及时
在测试一个功能时,我们除了考虑主要逻辑路径以外,还要关注边界或异常场景。因此在多数时候,我们除了要创建一个具有有效入参的单元测试,还需要准备其他使用了无效入参的单元测试。例如被测方法入参有一个范围,从MIN到MAX,那么应该创建额外的单元测试来测试输入为MIN和MAX时是否能正确处理。另外就是及时性,等代码稳定运行再来补齐单元测试可能是低效的,最有效的方式是在写好功能函数接口后(实现函数功能前)进行单元测试。
五、单元测试的现状及痛点
1、我们通过对行业现状进行调研后,有以下发现:
1)从行业特点看:传统行业软件(ERP、CRM等)单测覆盖率至少达到80%以上,互联网行业软件较低,一般低于50%,大部分没有。
2)从软件特点看:用户量较大的软件(工具类、中间件等)基础软件覆盖率相对较高,至少80%以上,需求变化快的业务类软件相对较低。
3)从开发习惯看:国外开发的软件较高,更加重视软件的质量,大多数开源软件覆盖率至少都在60%以上。国内开发者多数未养成习惯。
2、单元测试这么重要的事情,为什么在企业中实际中却很难做好呢,主要有以下几个痛点:
1)开发者需要投入更多的工作量:一个应用系统的单元测试代码行数与应用功能代码行数比至少为1:1,复杂应用则更高。通常来说每提升1%的单测行覆盖率,则需要编写业务代码1%的测试代码,所以开发者需要付出更多工作量。随着单元测试覆盖率的提升,每提升1%,都需要编写大量的用例,因为后续的用例至少有80%,甚至是90%以上的代码运行路径是重叠的,最坏的情况是增加了一个用例,只多了一行的覆盖。
2)存量代码数量庞大:我们目前关注的指标还只是核心系统的覆盖率,全量代码覆盖率提升更加困难,经年积累的应用中保持代码活跃的数量依然很庞大,要做现有代码的单元测试编码需要消耗大量人力。
3)单元测试代码容易失效:单元测试的代码需要持续维护,新业务需求引发的代码变更会导致原有的单测代码失效,在业务高速迭代的情况下,没有额外精力投入,要么忽略,要么删除,在这种情况下,很难持续维持一个较高的覆盖率指标。
归根结底,单元测试最大的困难就是成本问题,做好单元测试,我们的开发者需要持续投入大量的精力,而在业务需求高速迭代的情况下,我们该如何破局?答案就是:自动化技术
六、单元测试自动化调研
其实,单测自动化技术的发展至少已有15年以上的历史,目前主流的技术是静态代码分析技术,它是指无需运行被测代码,仅通过分析或检查源程序的语法、结构、过程、接口等来检查程序的正确性,找出代码隐藏的错误和缺陷。主要的代表产品有:EvoSuite、Squaretest等。
上图是EvoSuite工具根据现有被测代码自动生成的测试代码,目前这类产品生成的单测代码的行覆盖率一般可以达到30%左右,代码越复杂效果越差,它们可以作为简单业务场景的单测代码生成方案。
主要的优点有:纯客户端工具,安装即可使用,不需复杂配置。支持多种开发平台:支持idea、eclipse、命令行等多种工具。
主要的不足:生成代码质量不高、单测覆盖率较低:受限于代码分析技术和现实技术框架的复杂多样,生成的代码质量不高,单测覆盖率较低,只能适用于简单业务场景,且生成的代码需要人工判断有效性。例如订单sendpay这样的标记包含了丰富的业务语义,则很难通过静态分析生成有效的用例代码。
七、我们的一些想法与技术突破
1、将录制的数据转化为单元测试用例
基于静态代码分析局限性,我们需要寻找一个新的方向,那么如何能够获得更加丰富的业务数据呢,而不是通过一些策略生产数据,前年咱们零售交易研发创新了月光宝盒,完全可以将数据录制下来,于是我们就想到是否可以利用宝盒录制到的数据,反向生成测试用例呢,以此来实现快速生产单元测试的用例代码。大致的方案思路如下:
2、标杆验证的效果给了我们信心
乍一听这个想法有点疯狂,我们针对这个想法做了效果验证,虽然还没有达到奇效,但整体思路得到了检验,事实证明,这个方案虽然很难,但是是可行的,以下为Y侧做的标杆案例的尝试。通过4个标杆的试运行情况分析,接入一周内,生成代码2.3万行,单测行覆盖率提升幅度均在30%以上。
3、然而,该方案还并不完美,我们还有些建议
如果你仔细看过前面提到的单元测试原则,针对该方案一定会有疑问,没错,它违反了及时性原则,我们应该在写代码时或者提测前完成啊,测试阶段再录制生成已经晚了。的确,该方案不是完美的,为此我们给出的建议是:
1)针对存量代码,由于目前我们的存量代码数量较大,该方案将会产生较大的效果,开发者只要将录制工具集成到被测应用即可,接入成功后,如果测试同学能帮忙跑一次全量回归测试最佳,则可以快速生成大量的用例代码,如果测试同学时间不充足,则借助测试同学的日常测试逐渐积累数据,经过一两周后也能获得大量用例代码。
2)对于新开发代码,在开发者完成编码后的自测阶段,由开发者自己本地运行程序进行自测、录制,也能帮助我们生成一大批用例,然后可以基于生成的用例,再通过复制、手工调整进行快速扩充用例,从而保证单元测测的及时性。
3)特殊业务场景处理,对于边界或异常用例很难录制到,则可以通过手工复制用例,再修改用例数据,来扩充用例,这种方式比纯手工编写还是快很多,尤其是mock对象非常复杂的时候,用该方案可以在1分钟内即可基于已有用例扩展一个新用例。
4、生成的单元测试用例是什么样子
下面举一个生成单元测试用例代码的实际例子,该例子基于Mockito框架,每一个用例方法对应一个JSON文件,JSON文件中存储着用例运行时需要的出入参、全部外部调用的数据,用例代码和数据全部由工具自动生成,生成的大部分代码都是在帮助开发者将录制的数据组装Mock对象,这部分工作量在实际开发中是最大的,因此可以大幅度减小开发者自己纯手工编码工作。当需要手工扩充用例时,只需要将用例方法和数据文件复制一份,再对用例数据做出调整即可制作出新的用例。
数据文件样例:/artt/StockStatusReOccupySplitServiceImpl1#HpCm.json
5、我们所遇到的技术挑战
我们遇到了很多技术难点,由于基于宝盒录制的数据在还原代码时信息还不足,需要增加更多的录制信息与特殊应用场景处理,主要难点有:
1)结构化数据的录制与还原,复杂泛型的还原、复杂对象的序列化和反序列化
2)基于动态代理技术实现代码的特殊处理,如mybatis、JSF
3)用例的采样控制,重复用例的识别与剔除,
4)用例结果断言的多样性,需要丰富的比对策略
期间涉及到了大量的底层技术研究,截至目前我们仍然有很多技术点需要攻克。例如,我们正在做的应用接入提升,将Spring AOP的方式用agent+ASM方式进行替换,实现代码增强在不重启服务的情况下动态挂载、卸载,也进一步降低接入成本,减少对应用的入侵。
八、单测自动化平台的架构
整体分为三部分:
1)录制端,采用月光宝盒为基座,基于Spring AOP和ASM字节码增强agent技术,开发者在应用内部进行集成,同时在应用启动中增加agent代理脚本设置。
2)平台端,采集到的数据将被发往平台端,平台端主要负责应用注册、录制用例的统一管理等,并为生成端提供用例抽取服务。
3)生成端,以idea插件、命令行脚本的形式,为用户的应用生成代码,并且按照每个用例覆盖业务代码的行号进行去重。最终生成的代码提交到代码库,bamboo集成获取代码进行单测运行与指标的采集。
九、单测平台的共建与接入
单元测试自动化技术是当今软件领域的一个难题,行业的开发者也都在积极寻求突破
我们愿意做一只啄木鸟
帮助开发者找到代码里的虫子
通过自动化技术建立单测的信心
但啄木鸟还做不到全面自动化
大家不要因为它的存在而变得懈怠
每位开发者仍然要发扬:
工匠精神,以人为本,工具为辅
在提测前轻松做好单元测试
-
若依框架的MVC各层功能解释
WhatisMVC?Model–RepresentsthebusinesslayeroftheapplicationView–Definesthepresentatio
来源: 【天天播资讯】一台不容错过的Java单元测试代码“永动机”
全球动态:火爆全球的ChatGPT是什么?
环球要闻:数据结构刷题2023.02.21小记
若依框架的MVC各层功能解释
全球观速讯丨借力英特尔® Smart Edge,灵雀云 ACP 5G 专网解决方案获得多维度优化加速
难念的经是哪个电视剧主题曲?难念的经粤语谐音歌词
电视剧小爸爸插曲有哪几个?电视剧小爸爸插曲大全
三星4521打印机怎么连接手机?三星4521打印机卡纸怎么拿出来?
SBSetting怎么打开?sbsettings怎么安装到手机?
万能遥控器怎么使用?万能遥控器怎么配对机顶盒?
三星G810上市价格是多少?三星G810手机参数
数字电视遥控器怎么配对?数字电视遥控器没反应怎么办?
女生熬夜打游戏角膜上皮脱落!医生称严重需手术换角膜:一定要控制
今日要闻!后路堵死!苹果关闭iOS 16.3验证通道
洁癖福音!通用汽车申请自清洁触摸屏新专利:可自动清除屏幕指纹
36个月超长质保行业天花板!魅族20系列超前预订来了:只要1元
2023新年反思、总结、规划
SLA探活工具EaseProbe简介
天天快消息!二步法免疫组化试剂盒的详细介绍
世界视讯!每年分红不低于净利润一半!格力宣布将发56亿现金分红
热门看点:土耳其再发生6.4级地震 现场视频曝光:地动山摇
爱奇艺恢复会员投屏!“限制投屏案”原告:集体发声的结果
周鸿祎:比尔盖茨低估了ChatGPT的价值
当前播报:日本游客不舍告别 旅日大熊猫“香香”今天回家了!下午飞抵成都
当前动态:ETL的架构设计和实现及其优势
K8S-namespace 六大类型
信息:原来建造者模式是这样用的
环球看点!买部iPhone 14要花你多少年薪?各国对比:国人要12% 印度近50%
环球焦点!山东人坐地铁不拉手环直接抓杆引围观:人均身高1米8名不虚传
12岁女孩玩手游充值近3万 父亲要求退被拒:网友热议不该退 家长原因
中秋节的儿童画怎么画_中秋节的儿童画怎么画简单的
今天二月二龙抬头!四六级、考研初试今起可查分 方法来了
天天百事通!一加11概念机官宣:背部蓝色灯带抢眼 极具辨识度
每日消息!读Java实战(第二版)笔记16_组合式异步编程
天天热文:小米13系列本周MWC 2023发布!卢伟冰:海外米粉翘首以盼
你怎么看?日本66%的高端外国人才是中国人:远超印度、韩国
热门:kubernetes二进制部署(单节点)
环球速看:MyBatis plus 代码生成器
【世界聚看点】CSS概念与CSS选择器
环球观天下!NVIDIA为游戏玩家做了哪些贡献?DLSS、光追等4项技术还真少不了
世界观点:残忍没法看!大白鲨罕见"斩首"潜水员 2023年第一例鲨鱼吃人
27岁身高186cm的研究生 想捐精被拒:因为要不了那么多
【环球热闻】真服了 到底是谁还在支付宝里种树啊?
环球观天下!比亚迪立功 磷酸铁锂电芯份额暴增至67.5% 三元锂被甩远
世界热推荐:曲艺杂谈歌曲_曲艺杂谈
天天速递!vue-cli创建前端项目以及前后端交互
世界微动态丨记录一次HAWQ手工启动
当前快讯:教育部寒假促就业“暖心行动”超9100家用人单位参加 提供岗位信息超49.1万条
全球今亮点!射击游戏大作《原子之心》8分好评 继承《生化奇兵》的遗志
【世界播资讯】三步实现在ASP.NET Core Web API集成ChatGPT
环球即时:弯道超车 中国动力电池企业 “狂飙”入欧
全球快消息!i9-13900H+RTX 4060满血加持!华硕天选4酷睿版图赏
AMD不赞同NVIDIA:游戏卡加太多AI徒增成本 玩家买单
环球关注:AtCoder Beginner Contest 289
当前看点!女子因宠物猫去世欲轻生 网友吵翻:猫是“家人”为何不可?
4799元 小米Redmi Book Pro15增强版上架:8核升级12核
6.1英寸小屏手感绝佳!三星Galaxy S23图赏
环球快报:肯德基麦当劳的汉堡越卖越小引热议:20年基本没涨价真良心?
焦点滚动:02月20日20时山东滨州昨日累计报告阳性感染者确诊250例 怎么判断自己是否属于轻型感染者
火山引擎 DataTester:在广告投放场景下的 A/B 实验实践
第120篇: DOM编程(常用操作、动态脚本、样式及动态表格)
世界讯息:可孚医用N95口罩30只装 灭菌独立包装19.9元大促
男子因缺钙CT图像中没有肋骨:“像一个透明人”
全球新消息丨189元 OPPO Enco Air3无线耳机上架:HiFi 5 DSP、支持蓝牙5.3
腾讯XR业务转向:或将合作引进Quest 2头显
闲鱼上买显示器靠谱吗?注意这几点就可以
世界要闻:物联网平台选型葵花宝典:盘点开源、SaaS及通用型平台的优劣对比
【Unity AR】
AR精灵制作学习记录 【天天快播报】项目开发软件架构选择指南
飞利浦推出两款44.5英寸带鱼屏:1500R大曲率、75Hz刷新率
行驶中小车后备箱塞人露双脚!司机称其喝醉了:遭网友谴责
世界播报:低头族注意了!9岁女孩长期低头颈椎老如50岁
领1030元大额券:骆驼户外徒步鞋179元起大促
世界观点:亚马逊要求员工一周到岗工作3天:公司一度像个鬼城
K8S-deployment.yaml文件详解
开心档-Git 基本操作
资讯推荐:制造业做信息化(IT管理、程序员)有前途吗?---浅谈信息系统规划
全球观点:记录--什么时候会阻塞HTML文档渲染过程?
【Oculus Interaction SDK】(十一)关于手势识别中手势设置的详细信息
天天热资讯!埃塞俄比亚政府和“提人阵”武装达成停火协议
天天新消息丨义乌自己的全球支付工具!义支付发布:打通16个币种
这待遇简直了!美团外卖进军香港 正疯狂招骑手:月入3万+
消息!手机套餐费太贵 韩国三大运营商被批:是否串通涨价
与剧版强烈反差!《三体》动画豆瓣跌至3.9分:官方已停播
特斯拉最入门车型国内现身?别被骗了:“披着狼皮的羊”而已
关注:Camunda(一)---安装和简单示例
女子在桃李面包中吃出带锈刀片 官方:不存在使用该刀片的生产环节
环球快看:手机寒气仍存 5G巨头中兴被曝优化人员 回应称正常调整
世界观焦点:蔚来ET9要来了?号称“蔚来版迈巴赫” 屏幕开始横过来
掌权八年后上汽大众换帅:贾健旭接棒
大嘴猴50S精梳棉男士四角裤狂促:券后每条不到10元!
WPF学习_day1
K8S-Service的yaml文件详解
全球时讯:【机器视觉】-什么是机器视觉?
当前报道:游戏王dm新马甲_[游戏王DM]羁绊
全球热点!张艺谋监制!北京冬奥拍成电影了:《北京2022》预告片发布
世界视讯!提前!韩国欲2028年推6G网 速度有多快?5G是高铁 6G就是飞机
全球首发5.5G 高通骁龙X75基带不再公布速率:峰值没啥意义
极氪汽车被指销售欺诈!车主集体投诉:退一赔一
世界新动态:ChatGPT火了 中国电信股价大涨50%:底层技术早有布局