1.1.单元测试是什么
写代码免不了要做测试,测试有很多种,对于java来说,最初级的就是写个main函数运行一下看看结果,高级的可以用各种高大上的复杂的测试系统。每种测试都有它的关注点,比如测试功能是不是正确,或者运行状态稳不稳定,或者能承受多少负载压力,等等。
那么所谓的单元测试是什么?这里直接引用维基百科上的词条说明:
单元测试(又称为模块测试, Unit Testing)是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。
所以,我眼中的“合格的”单元测试需要满足几个条件:
- 测试的是一个代码单元内部的逻辑,而不是各模块之间的交互。
- 无依赖,不需要实际运行环境就可以测试代码。
- 运行效率高,可以随时执行。
1.2.单元测试的定位
了解了单元测试是什么之后,第二个问题就是:单元测试是用来做什么的?
很多人第一反应是“看看程序有没有问题”,或者“确保没有bug”。单元测试确实可以测试程序有没有问题,但是,从我个人编程的经验来看,大部分情况下只是使用单元测试来“看看程序有没有问题”的话,效率反而不如把程序运行起来直接查看结果。原因有两个:
- 单元测试要写额外的代码,而不写单元测试,直接运行程序也可以测试程序有没有问题。
- 即使通过了单元测试,程序在实际运行的时候仍然有可能出问题。
但是,很多时候直接启动程序测试会比较慢,所以一些同学为了解决这个问题,采用了一个折中的办法:只加载要测试的模块和它所有的依赖模块,比如在测试时只加载这个模块相关的spring的配置文件。这时所谓的单元测试实际上是用xUnit框架运行的集成测试,并没有体现“单元”的概念。
而关于“纯粹的单元测试”在介绍语言或者框架的书里很少被提起,反而是介绍重构或者敏捷开发的书里经常会看到各种各样的关于单元测试的介绍。
在这里我总结了一下几个比较常见的单元测试的几个典型场景:
- 开发前写单元测试,通过测试描述需求,由测试驱动开发。
- 在开发过程中及时得到反馈,提前发现问题。
- 应用于自动化构建或持续集成流程,对每次代码修改做回归测试。
- 作为重构的基础,验证重构是否可靠。
还有最重要的一点:编写单元测试的难易程度能够直接反应出代码的设计水平,能写出单元测试和写不出单元测试之间体现了编程能力上的巨大的鸿沟。无论是什么样的程序员,坚持编写一段时间的单元测试之后,都会明显感受到代码设计能力的巨大提升。
3.Spock是什么
3.1.简介
这里引用官方的介绍:
Spock is a testing and specification framework for Java and Groovy applications. What makes it stand out from the crowd is its beautiful and highly expressive specification language. Thanks to its JUnit runner, Spock is compatible with most IDEs, build tools, and continuous integration servers. Spock is inspired from JUnit, jMock, RSpec, Groovy, Scala, Vulcans, and other fascinating life forms.
简单地说,spock是一个测试框架,它的核心特性有以下几个:
- 可以应用于java或groovy应用的单元测试框架。
- 测试代码使用基于groovy语言扩展而成的规范说明语言(specification language)。
- 通过junit runner调用测试,兼容绝大部分junit的运行场景(ide,构建工具,持续集成等)。
- 框架的设计思路参考了JUnit,jMock,RSpec,Groovy,Scala,Vulcans……
要理解spock的几个特性,还要理解几个关键名词:
3.1.1.groovy
引用维基百科上的介绍:
Groovy是Java平台上设计的面向对象编程语言。这门动态语言拥有类似Python、Ruby和Smalltalk中的一些特性,可以作为Java平台的脚本语言使用。
Groovy的语法与Java非常相似,以至于多数的Java代码也是正确的Groovy代码。Groovy代码动态的被编译器转换成Java字节码。由于其运行在JVM上的特性,Groovy可以使用其他Java语言编写的库。
groovy是一门比较轻量,学习门槛也比较低的语言。对于只用过java语言的程序员来说,groovy是一个很不错的开拓视野的机会。如果你没有接触过groovy,那么可以参考这两条:
- 可以用纯java的语法写groovy。
- 参考这篇快速入门。
我个人比较喜欢groovy语言,在一些小项目中经常使用它。引用一下R大在知乎的回复:
Groovy比较讨好来自Java的程序员的一点是:用它写代码可以渐进的从接近Java的风格进化为接近Ruby的风格。使用接近Java风格写Groovy时,代码几乎跟Java一样,容易上手;而学习过程中可以逐渐用上各种类似Ruby的方便功能。
3.1.2.specification language
如果接触过不同语言类型的开源项目的话,就会发现有些项目中找不到测试目录(test),取而代之的是一个叫“spec”的目录,比如用ruby写的项目gitlab。这里的spec实际是specification的缩写,它的背后是一种近些年来开始流行起来的编程思想:BDD(Behavior-driven development)。
关于BDD,同样是引用维基百科上的介绍:
BDD:行为驱动开发是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作。BDD最初是由Dan North在2003年命名,它包括验收测试和客户测试驱动等的极限编程的实践,作为对测试驱动开发的回应。
BDD的做法包括:
- 确立不同利益相关者要实现的远景目标
- 使用特性注入方法绘制出达到这些目标所需要的特性
- 通过由外及内的软件开发方法,把涉及到的利益相关者融入到实现的过程中
- 使用例子来描述应用程序的行为或代码的每个单元
- 通过自动运行这些例子,提供快速反馈,进行回归测试
- 使用“应当(should)”来描述软件的行为,以帮助阐明代码的职责,以及回答对该软件的功能性的质疑
- 使用“确保(ensure)”来描述软件的职责,以把代码本身的效用与其他单元(element)代码带来的边际效用中区分出来。
- 使用mock作为还未编写的相关代码模块的替身
BDD背后的编程思想超出了这篇文章的范围,这里就不再展开。上文说的specification language实际上是BDD其中一部分思想的实现手段:通过某种规范说明语言去描述程序“应该”做什么,再通过一个测试框架读取这些描述、并验证应用程序是否符合预期。
3.1.3.单元测试的运行场景
测试只有被执行之后才会有价值,这里就涉及一个“什么时候执行单元测试”的问题。
1.被接触最多的就是在IDE中执行单元测试,java程序员比较幸运,主流的java IDE都可以很好的集成了单元测试功能,单元测试代码自动生成、测试覆盖率检查等功能也都成了IDE的标配。这些功能都能让程序员在编写代码的时候直接可以运行单元测试得到反馈。
2.其次,主流的构建工具(如maven、gradle)中也都实现了运行单元测试的功能,在生成二进制包之前可以对代码进行回归测试,这些构建工具都可以通过命令行调用,这是自动化构建的前提。
3.在此之上,依托于构建工具提供的自动化特性,在持续集成、持续部署的过程中可以执行自动化构建,在自动化构建的过程中通过构建工具执行单元测试,这是持续集成的流程中的重要步骤。
3.2.Spock与现有框架的对比
3.2.1.已有的java单元测试框架
就像刚才说的,有很多已有的单元测试框架,稍微老一点的如JMockit、EasyMock,新一点的类似Mockito和PowerMock。我之前一直在用testng+Mockito作为主要的单元测试框架,用它写过大概上万行单元测试,它的写法相对来说比较易读,功能也能满足大多数场景。
但在使用mockito的过程中也总是有一些不是很方便的地方,比如代码的可读性总还是差那么一点,比如像这样:
虽然能读懂,但是对于它所做的事情全来说感觉说了很多废话,单元测试代码总是里充斥着各种when(),anyXXX(),return()之类啰嗦的关键词,加上java本身就是一个啰嗦的强类型的语言,这让写单测和读单测成为了一种体力活。
其次是单测数据,大部分测试都要提供数据,比如“当输入a的时候应该返回b”,如果只有一组数据那么没什么问题,但是当需要测试很多边界条件,需要多组数据的时候就会比较纠结。
用jUnit或者testng的dataprovider可以实现这个需求,但是无论是通过xml定义还是通过函数返回数据,都非常不方便。
最后,因为这些框架都只是一些独立的函数,没有告诉你“应该怎么写单测”,所以不同的人最终写出来的单测也是五花八门:
- 有不用assert而是用system.out.println的
- 有单测一个函数写了好几百行的
- 有直接把单测当成main函数写的
最终,团队要接受“虽然确实写了单测,然而这并没有什么卵用”的结果。
3.2.2.为什么使用spock
还是刚才的例子,如果用spock写的话:
这段代码实际是3个测试:当getUserInfo返回的用户状态分别为ENABLED、INIT和CLOSED时,验证各自isUserEnabled函数的返回是否符合期待。
我对于spock框架最直接的感受:
- spock框架使用标签分隔单元测试中不同的代码,更加规范,也符合实际写单元测试的思路
- 代码写起来更简洁、优雅、易于理解
- 由于使用groovy语言,所以也可以享受到脚本语言带来的便利
- 底层基于jUnit,不需要额外的运行框架
- 已经发布了1.0版本,基本没有比较严重的bug
3.2.3.为什么不用spock
用了一段时间的spock后,我也总结了几个不用spock的理由:
- 框架相对比较新,IDE的支持(尤其是eclipse)不如其它成熟的框架
- groovy语言本身的compiler更新比较快,偶尔有坑(版本不兼容等)
- 需要了解groovy语言
- 与其它java的测试框架风格相差比较大,需要适应
当然,这些理由比起spock提供的易于开发和维护的单元测试代码来说,都是可以忽略的。
4.使用Spock
写到这里,还是要聚焦一下这篇文章要讨论的问题:如何用spock框架编写单元测试,在此之前再强调一下:
- 单元测试不一定非要使用spock,但是其它框架写出的单元测试代码远没有用spock框架优雅。
- spock框架并不只能写单元测试,它也可以写集成测试,甚至性能测试,但是后两者spock相对于其它框架来说没有什么优势。
4.1.关于开发环境
在使用spock框架时,我比较推荐的ide是IDEA,推荐的构建工具是gradle。
就算不使用spock框架,IDEA的顺手程度也比eclipse好太多,对新技术的响应速度快,也没有那么多莫名其妙的严重bug,社区版免费但主要功能都有,没有什么理由不试用一下。
而gradle相对于maven来说配置简化了很多,可定制的功能也更强,与其迷失在maven复杂的xml和一层套一层的依赖关系中,我宁愿把时间做一些更有意思的事情。
由于IDE基本可以自由选择,但构建工具大部分是由团队决定的,而maven现在还是处于构建工具的领导地位,所以这篇文章里的步骤都是基于IDEA+maven,当前的IDEA已经支持spock,不需要做什么特殊配置。
- 如果你的团队应用了gradle,spock官网中对于gradle如何配置说的比较完整,可以直接参考官网。
- 如果你执迷不悟非要使用eclipse,我在eclipse下也跑通了整个流程。需要安装最新的groovy-eclipse插件和附加包(安装时选择groovy2.4版以上的compiler),地址:https://github.com/groovy/groovy-eclipse/wiki
4.2.hello spock
前面做了那么多铺垫,终于到了真正编写一个hello world的时候。
到这里,我假设你是一位java开发者,并且已经了解基本的IDE及构建工具的使用。
1.创建一个空白项目:hello_spock,选择maven工程。
2.在pom.xml中增加依赖:
3.由于spock是基于groovy语言的,所以需要创建groovy的测试源码目录:首先在test目录下创建名为groovy的目录,之后将它设为测试源码目录。
4.创建一个简单的类:
创建测试类,可以手工创建,也可以使用IDEA的辅助创建:
5.编写测试代码,这里我们验证一下sum返回的结果是否正确:
6.运行一下测试:
7.至此,一个最简单的spock测试就写完了。
4.3.Spock中的概念
4.3.1.Specification
在Spock中,待测系统(system under test; SUT) 的行为是由规格(specification) 所定义的。在使用Spock框架编写测试时,测试类需要继承自Specification类。
4.3.2.Fields
Specification类中可以定义字段,这些字段在运行每个测试方法前会被重新初始化,跟放在setup()里是一个效果。
4.3.3.Fixture Methods
预先定义的几个固定的函数,与junit或testng中类似,不多解释了
4.3.4.Feature methods
这是Spock规格(Specification)的核心,其描述了SUT应具备的各项行为。每个Specification都会包含一组相关的Feature methods,如要测试1+1是否等于2,可以编写一个函数:
4.3.5.blocks
每个feature method又被划分为不同的block,不同的block处于测试执行的不同阶段,在测试运行时,各个block按照不同的顺序和规则被执行,如下图:
下面分别解释一下各个block的用途。
4.3.6.Setup Blocks
setup也可以写成given,在这个block中会放置与这个测试函数相关的初始化程序,如:
一般会在这个block中定义局部变量,定义mock函数等。
4.3.7.When and Then Blocks
when与then需要搭配使用,在when中执行待测试的函数,在then中判断是否符合预期,如:
4.3.7.1.断言
条件类似junit中的assert,就像上面的例子,在then或expect中会默认assert所有返回值是boolean型的顶级语句。如果要在其它地方增加断言,需要显式增加assert关键字,如:
4.3.7.2.异常断言
如果要验证有没有抛出异常,可以用thrown(),如下:
要获取抛出的异常对象,可以用以下语法:
如果要验证没有抛出某种异常,可以用notThrown():
4.3.8.Expect Blocks
expect可以看做精简版的when+then,如:
可以简化为:
函数退出前做一些清理工作,如关闭资源等。
4.3.10.Where Blocks
做测试时最复杂的事情之一就是准备测试数据,尤其是要测试边界条件、测试异常分支等,这些都需要在测试之前规划好数据。但是传统的测试框架很难轻松的制造数据,要么依赖反复调用,要么用xml或者data provider函数之类难以理解和阅读的方式。比如说:
而在spock中,通过where block可以让这类需求实现起来变得非常优雅:
上述例子实际会跑三次测试,相当于在for循环中执行三次测试,a/b/c的值分别为3/5/5,7/0/7和0/0/0。如果在方法前声明@Unroll,则会当成三个方法运行。
更进一步,可以为标记@Unroll的方法声明动态的spec名:
运行时,名称会被替换为实际的参数值。
除此之外,where block还有两种数据定义的方法,并且可以结合使用,如:
4.4.Interaction Based Testing
对于测试来说,除了能够对输入-输出进行验证之外,还希望能验证模块与其他模块之间的交互是否正确,比如“是否正确调用了某个某个对象中的函数”;或者期望被调用的模块有某个返回值,等等。
各类mock框架让这类验证变得可行,而spock除了支持这类验证,并且做的更加优雅。如果你还不清楚mock是什么,最好先去简单了解一下,网上的资料非常多,这里就不展开了。
4.4.1.mock
在spock中创建一个mock对象非常简单:
而创建了mock对象之后就可以对它的交互做验证了:
上面的例子里验证了:在publisher调用send时,两个subscriber都应该被调用一次receive(“hello”)。
示例中,表达式中的次数、对象、函数和参数部分都可以灵活定义:
得益于groovy脚本语言的特性,在定义交互的时候不需要对每个参数指定类型,如果用过java下的其它mock框架应该会被这个特性深深的吸引住。
4.4.2.Stubbing
对mock对象定义函数的返回值可以用如下方法:
符号代表函数的返回值,执行上面的代码后,再调用subscriber.receice方法将返回ok。如果要每次调用返回不同结果,可以使用:
如果要做额外的操作,如抛出异常,可以使用:
而如果要每次调用都有不同的结果,可以把多次的返回连接起来:
4.5.mock and stubbing
如果既要判断某个mock对象的交互,又希望它返回值的话,可以结合mock和stub,可以这样:
注意,spock不支持两次分别设定调用和返回值,如果把上例写成这样是错的:
此时spock会对subscriber执行两次设定:
- 第一次设定receive(“message1″)只能调用一次,返回值为默认值(null)。
- 第二次设定receive(“message1″)会返回ok,不限制次数。
4.6.其它类型的mock对象
spock也支持spy,stub之类的mock对象,但是并不推荐使用。因为使用“正规的”bdd思路写出的代码不需要用这些方法来测试,官方的解释是:
Think twice before using this feature. It might be better to change the design of the code under specification
具体的使用方法如果有兴趣可以参考官方文档。
4.7.更多
至此,读者应该对Spock的主要功能和使用方法应该有个粗略的认识。如果希望实际使用spock,推荐读一下官方的文档,写的比较清晰,并且其中引用的一些文档也都值得一读:
http://spockframework.github.io/spock/docs/1.0/index.html
另外一个值得一看的是spock-example工程:
https://github.com/spockframework/spock-example
5.结语
需要再强调一下:现实中的场景绝对会比文章中的例子复杂(比如要mock一个private函数,或者全局变量,或者静态函数,等等),但是此时更好的思路并不是压榨框架的功能,而应该是去思考代码的设计是否出了问题。
还是强调这个观点:单元测试的难度和代码设计的好坏息息相关,单元测试测的三分是代码,七分是设计。如果你觉得自己处于编码能力上升的瓶颈期,那么可以尝试一下为以前写的类编写“纯粹的”单元测试,在这个过程中,spock可以让你从重复的编码、繁重的维护工作中解脱出来,让编写测试回归为一件有幸福感和成就感的事情。
参考 http://blog.jobbole.com/89874/
相关推荐
Spock 框架是基于 Groovy 语言的测试框架,专为 Java 和 Groovy 应用程序设计,提供了一种简洁、强大的方式来进行行为驱动开发(BDD)和单元测试。这个“spockframework_presentation”压缩包可能包含一个项目演示或...
Spock 是一个基于 Groovy 的 BDD(行为驱动开发)测试框架,它提供了简洁的语法和强大的功能,使得编写单元测试和集成测试变得更为容易。在本模板中,你可以了解到如何在 Gradle 项目中集成 Spock,并有效地进行测试...
在IT行业中,测试是软件开发过程中的重要环节,它确保代码的质量和系统的...通过学习这个项目,开发者可以掌握如何在Kotlin项目中有效地利用Spock进行单元测试和集成测试,提高代码质量,确保项目的稳定性和可靠性。
JESD79-2F DDR2 JESD79-3F DDR3 JESD79-4D DDR4 JESD79-5C DDR5 JESD209-2F LPDDR2 JESD209-3C LPDDR3 JESD209-4E LPDDR4 JESD209-4-1A LPDDR4X JESD209-5C LPDDR5(X)
COMSOL二维光子晶体角态研究:单胞与超胞能带计算及边界态与角态特性分析,COMSOL二维光子晶体角态研究:单胞与超胞能带计算及边界态与角态特性分析,comsol二维光子晶体角态。 单胞能带,超胞能带,边界态以及角态计算。 ,comsol;二维光子晶体;角态;单胞能带;超胞能带;边界态计算,基于Comsol的二维光子晶体角态及能带边界计算研究
六自由度机械臂抓取动作仿真与代码解析:抓取动画、关节参数变化及轨迹图解详解,六自由度机械臂抓取动作仿真指南:掌握两套代码实现动画与轨迹图模拟学习攻略,六自由度机械臂抓取动作仿真-8 两套关于抓取动作的代码,包括抓取动画、关节角、角速度、角加速度的变化仿真、以及抓取轨迹图 简单易懂好上手~ ,六自由度机械臂;抓取动作仿真;抓取动画;关节角变化;角速度角加速度;抓取轨迹图;两套代码;简单易懂好上手,六自由度机械臂抓取动作仿真演示:代码与轨迹图解
ITC网络广播工具软件
Multisim四位密码锁电路仿真设计:设定、开锁与声光报警功能演示资料包,Multisim四位密码锁电路仿真设计:设定、输入、开锁与报警功能详解,附源文件、原理说明书与演示视频,multisim四位密码锁电路仿真设计 功能: 1.通过拨码开关1进行初始密码设定。 2.通过拨码开关2输入密码,实现开锁判断。 3.如果密码正确,LED绿灯亮,表示开锁。 4.如果密码不正确,LED红灯亮,蜂鸣器鸣叫,声光报警。 资料包含:仿真源文件+原理说明书+演示视频 ,四位密码锁电路、Multisim仿真设计、初始密码设定;拨码开关输入;开锁判断;LED灯显示;声光报警;仿真源文件;原理说明书;演示视频,Multisim四位密码锁电路仿真设计:初始密码设置与智能解锁功能的声光报警展示
俗话说,摸鱼摸的好,上班没烦恼,毕竟谁能拒绝带薪拉屎呢(手动狗头) 这是一个云开发职场打工人专属上班摸鱼划水微信小程序源码,没有后台 直接导入微信开发者工具即可运行,UI简约大气漂亮,只需登录微信公众平台配置完合法域名即可轻松上线。 用户进入摸鱼小程序,可以自由设置薪资,上班时间、下班时间、发薪日、 月工作天数以提醒自己摸鱼,全民打酱油,让自己成为摸鱼冠军,《商鞅摸鱼哲学》 摸鱼不是自我放纵,而是个人实力的积蓄,我们的小目标是晚睡晚起 小程序中的今日待办会提醒用户带薪拉屎和闲逛,下方展示的是距离休息日的天数,距离下一次发工资的天数和节日的天数。
【毕业设计】基于Java的开发的一个集合校园二手交易、拼车、失物招领等功能的app_pgj
个人记录:PICkit3离线烧录流程 使用软件:MPLAB X IDE v5.30 记录时间:20250215
基于Matlab代码的电力系统状态估计与实验仿真研究:扩展卡尔曼滤波和无迹卡尔曼滤波在电力系统动态状态估计中的应用及效果分析,Matlab仿真实验研究:基于扩展卡尔曼滤波器与无迹卡尔曼滤波器对电力系统状态估计的影响及验证,状态估计 电力系统状态估计 Matlab代码 实验仿真研究 电力系统由于测量值和传输误差,还有测量噪声的影响,会对状态估计产生影响。 因此,需要对嘈杂的测量进行滤波,以获得准确的电力系统运行动态。 本文使用扩展卡尔曼滤波器(EKF)和无迹卡尔曼滤波器(UKF)来估计电力系统的动态状态。 扩展卡尔曼滤波EKF、无迹卡尔曼滤波UKF 利用扩展的无迹卡尔曼滤波器估计了动力系统的动态状态。 对WECC 3机9总线系统和新英格兰10机39总线系统进行了案例研究。 结果表明EKF和UKF都能准确地估计电力系统的动态状态。 ,核心关键词:状态估计; 电力系统状态估计; Matlab代码; 实验仿真; 测量值误差; 测量噪声; 扩展卡尔曼滤波器(EKF); 无迹卡尔曼滤波器(UKF); 动力系统; 动态状态估计; WECC 3机9总线系统; 新英格兰10机39总线系统。,Matlab
springboot在线考试--
台达DVP EH3与MS300 PLC&变频器通讯程序的全面解决方案,台达DVP EH3与MS300通讯程序:稳定可靠的频率控制与启停管理系统,台达DVP EH3与台达MS300通讯程序(TDEH-9) 可直接用于实际的程序,程序带注释,并附送触摸屏程序,有接线方式和设置,通讯地址说明等。 程序采用轮询,可靠稳定 器件:台达DVP EH3系列PLC,台达MS300系列变频器,昆仑通态7022Ni 功能:实现频率设定,启停控制,实际频率读取,加减速时间设定。 资料:带注释程序,触摸屏程序,接线和设置说明,后续有技术咨询。 ,核心关键词:台达DVP EH3; 台达MS300; 通讯程序(TDEH-9); 轮询; 稳定; 频率设定; 启停控制; 实际频率读取; 加减速时间设定; 触摸屏程序; 接线方式; 设置说明; 技术咨询。,台达PLC与变频器通讯程序(带注释、触摸屏控制)
项目资源包含:可运行源码+sql文件 适用人群:学习不同技术领域的小白或进阶学习者;可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。项目具有较高的学习借鉴价值,也可拿来修改、二次开发。 个人账户管理:支持用户注册、登录与个人信息编辑;提供密码找回及账号安全保护措施。 声纹采集:利用麦克风设备录制用户的声纹样本;支持多种录音格式和质量调整,确保采集到清晰、准确的声纹数据。 声纹模板库管理:建立和维护一个安全的声纹模板库;支持声纹模板的添加、删除、更新和查询操作。 声纹比对与识别:运用深度学习算法对输入的声纹数据进行特征提取和匹配;实现快速、准确的声纹身份验证。 多场景应用支持:适用于多种场景,如门禁系统、移动支付、远程登录等;可根据实际需求定制开发相应的应用场景。 实时监控与报警:实时监控系统运行状态,包括声纹识别成功率、处理速度等指标;当出现异常情况时,及时发出报警信息。 数据分析与报告生成:收集并分析声纹识别过程中的数据,如识别准确率、处理时间等;根据用户需求输出包含详细图表说明的专业级文档供下载打印保存。 社区互动交流:设立论坛版块鼓励用户分享心得体会讨论热点话题;定期邀请行业专家举办线上讲座传授实用技巧知识。 音乐筛选与推荐:集成音乐平台API,根据用户的浏览习惯和情绪状态推荐背景音乐,增强用户体验。 数据可视化:提供交互式的数据可视化面板,使非技术用户也能轻松理解复杂的数据集,从而做出更明智的决策。
三相与多相开绕组永磁同步电机仿真模型的先进控制策略探讨与实现,三相与多相开绕组永磁同步电机的Simulink仿真模型与先进控制策略研究,开绕组电机,开绕组永磁同步电机仿真模型、simulink仿真 共直流母线、独立直流母线,两相容错,三相容错控制,零序电流抑制,控制策略很多 三相开绕组永磁同步电机,六相开绕组永磁同步电机 五相开绕组永磁同步电机,五相开绕组电机 ,开绕组电机; 永磁同步电机仿真模型; simulink仿真; 共直流母线; 独立直流母线; 两相容错; 三相容错控制; 零序电流抑制; 控制策略; 六相开绕组永磁同步电机; 五相开绕组永磁同步电机,开绕组电机仿真研究:共直流母线与独立直流母线的容错控制策略
【毕业设计】基于Java的开发的网上汽车租赁管理系统_pgj
csv 模块是 Python 的标准库,无需额外安装。 运行结果如下图: ['姓名', '年龄', '城市'] ['张三', '25', '北京'] ['李四', '30', '上海'] ['王五', '22', '广州']
【毕业设计】基于Java+Springboot+Vue的宠物领养系统_pgj
让前端开发者学习“机器学习”!