精华内容
下载资源
问答
  • 其实,“层叠”的就是样式的覆盖,当一元素被运用上多种样式,并且出现重名的样式属性时,浏览器必须从中选择一属性值,这过程就叫“层叠”。样式覆盖(这种叫法更大众化些)遵循一定的规则,之前我对这...
  •  1、最基本的先保证以正反两大类用例全面覆盖需求(且先不论需求中的主次),其中包括  (1)细化各种数据类型,达到有效和无效数据类型的覆盖  (2)细化各种流程分支(考虑主流程、辅流程、异常处理、出错...
  • 测试用例的设计-提高测试覆盖率 前言 说到测试用例的设计,我想每有过测试经历的测试工程师都会认为很简单,不就是:按需求或概要设计,得到软件功能划分图,然后据此按每功能,采用等价类划分、临界值、因果...

     

    测试用例的设计-提高测试覆盖率

    前言

    说到测试用例的设计,我想每个有过测试经历的测试工程师都会认为很简单,不就是:按需求或概要设计,得到软件功能划分图,然后据此按每个功能,采用等价类划分、临界值、因果图等方法来设计用例就行了。

    但事实上撇开测试数据的设计不谈,仅就测试项来说,我们发现,对同一个项目,有经验的测试人员,在写用例或测试时总会有更多的测试考虑点,从而发现更多的问题;而有些测试人员测试用例的撰写却只有那么三板斧,表面看好象已经把页面所有信息的测试都考虑到了,实际上却还是遗漏了大量测试覆盖点,导致其测试出来的程序总是比较脆弱。

    究其原因,我觉得还是测试用例的撰写水平不到位,更确切地说是测试用例的覆盖度太低。说实话我认为系统测试用例真正做到100%覆盖是很难的。难道说按设计中的功能划分,每个功能都写到了这个用例就覆盖完整了?错,这还远远不够。因为我们知道还有大量的内部处理、转换、业务逻辑、相互影响的关系等都是需求或设计中所不会点明的。而这些一方面需要靠测试人员对项目本身的了解,另一方面要靠测试人员的经验,来一一找到这些隐藏点并予以测试,才能真正地保证我们的测试覆盖度。

    所以本文抛开具体的测试数据设计方法,主要从测试覆盖度的角度来介绍用例设计时,如何才能考虑地更周全,如何才能将隐藏的测试项一一找出,从而使我们的测试更全面更完整。

    想法虽然美好,可是毕竟每个测试的项目都是各不相同,针对不同项目我们的经验也会告诉给我们不同的想法,这些想法通常很感性,很难用严密的逻辑理论来把它升华。因此本文的内容仍是很简陋且不成熟,只是希望能以本文为砖,引起大家的思考,一起来补充完善,以使我们的测试用例设计水平不断提高。


    正文

    一、测试用例的切面设计

    1、功能点切面

    2、特定切面

    3、隐含切面

    1)、后台功能

    2)、完整业务流程的测试

    3)、某种特定情况下的系统运行 

    4)、其它相关系统

    5)、除功能测试外的其它测试类型

    二、详细用例的设计

    1、功能切面表面用例设计

    1)、具体功能测试

    2)、组合操作的测试

    3)、GUI界面的测试

    4)、数据初始化情况测试

    5)、业务需求实现是否正确

    2、功能切面隐含测试项用例设计:

    1)、数据完整性的测试

    2)、后台的特殊处理

    3)、功能业务之间的关联与转换

    4)、从设计实现发掘测试点

    5)、并发操作时的测试

    3、特定切面用例设计

    4、隐含切面用例设计

    1)、无界面的后台功能

    2)、与业务流相关的测试

    3)、其它测试类型

    三、测试数据的设计

    一、测试用例的切面设计

    所谓测试切面设计,其实就是测试用例大项的划分。测试用例划分的经典方法是瀑布模型,也就是从上到下,逐渐细分,大模块包括小模块,小模块包括更小的模块。但仅仅如此是不够的,我们还要从更多的角度切入系统,从不同的角度把系统切分成一块一块的,来进行测试,从而确保测试大项的完整性。

    1、功能点切面

    这是最常见的切面,通常我们认为页面上的一个按钮就是一个功能点。然后我们可以根据功能的复杂程度,按每个功能;或一个功能点分多页;或多个功能点合成一页来进行用例的撰写。

    2、特定切面

    除此以外,还有一种特定切面的划分方法,也是用例撰写时经常会用到的。所谓的特定切面,就是忽略掉表面上的功能点,而关注测试对象的某一个面。比如我们的内部管理系统提供了销售录入导入、注册录入导入等功能,从菜单划分上对应了七八个功能点。但这些功能处理后台有个共同的处理项就是授权记录的生成,这时我们就可以把授权记录生成单独拿出来做一个测试项,而在其它测试项中涉及这一部分的用例就不必再一一撰写。此外象一些界面共通的操作用例单独写成一页,也是一种特定切面。所以如果说将用例按功能点划分是一种纵向划分法,那么特定切面就是从横向的角度分析所得到的切面。在普通功能点划分上再根据实际情况设计特定切面,可以使我们的用例阅读性、理解性、操作性更强。

    3、隐含切面

    这类用例是最容易被忽略的。它往往不是明显的某个功能项,可能是功能项后台的隐含处理,也可能是多个功能项之间的关联处理,甚至可能是在某种特定情形下的处理。这都需要测试人员通过对软件的学习了解,来进行挖掘。

    1)、后台功能

    常见的如一些定时自动启动的服务;以及某种特定情况下自动执行的操作等。它们在界面上往往是不体现的,但许多在需求设计中还是会提到,也有一些比较细小的功能可能会被忽略,就需要测试人员根据对项目的了解程度来进行挖掘。所以说一个熟悉项目的和一个不熟悉的测试人员,写出来的用例就完全是两个层次的。

     

    2)、完整业务流程的测试

    我们都知道测试用例的设计是从点、线、面三个层次去考虑的。完整的一个功能项是线,其中的某个按钮是点,多个相关功能结合成完整业务流就是面。从实际来看这类用例往往被我们忽略。

    事实上目前公司的软件本来都是业务型应用软件,将各种功能从业务流中切割出来单独写用例,肯定也会有涉及到整体流程的情况。若不加以区分,将细节与全局搅在一起,不仅思路混乱,也容易考虑不周。因此在系统测试阶段,建议用例设计要有分有合,针对具体功能的就只围着这个功能转:而在业务流程测试项中,再完全从整体的业务流角度出发去考虑用例,这样不仅不容易产生疏漏,用例阅读与执行也更清楚。

    3)、某种特定情况下的系统运行

    这类用例的设计往往与系统实际业务情况密不可分。比如财务软件,通常需要在月尾一天、月头一天、年尾一天、年头一天,对所有相关功能中的日期处理进行测试;又比如WIN 2000环境开发测试的系统,要测试在98XP2003等操作系统下是否能运行自如;再有如存在大量动态图片视频等的网页,在普通网速下的展现速度等等。总之就是要尽可能从实际应用的角度出发考虑,来进行测试补充。

    4)、其它相关系统

    即指在当前项目中直接使用的其它成果,包括公司自有的系统模块、组件、函数;以及购买或免费得到的一些功能组件。对这些内容需要预先与开发组长等讨论清楚,是否需要测试。若时间紧张或其它原因决定不测的,应在测试计划中说明。若需要测试的,则具体可根据实际情况来设计,可以是通过系统某个功能的测试来涉及,此时就不需要单独划分测试项;若相对比较独立的,也可以通过单独的测试项来对其专门进行测试。

    5)、除功能测试外的其它测试类型

    包括可靠性、安全性、恢复性、配置安装测试等等,这些测试类型都是一个单独的测试项。

    所谓好的开始是成功的一半,保证测试项划分的完整、合理、正确,会直接影响到本次测试的成效。通常建议该阶段工作要花1-2天的时间来考虑,并要在测试过程中随着对软件的深入了解,不断进行调整补充。可千万不要认为把分析设计中的功能模型图搬搬过来就可以了。

    二、详细用例的设计

    划分好了测试项,接着就是针对各个测试项,考虑具体的测试用例了。根据测试项的特点,测试用例的设计角度也有所不同。下面我们就来看看通常的功能点测试用例,该从哪些角度出发来进行设计:

    1、功能切面表面用例设计

    1)、具体功能测试

    根据需求分析设计,按页面提供的各个功能项,采用黑盒测试的各种方法,设计用例。比如页面提供了增、删、改、查功能,那么这四个功能是否正确实现就是我要验证的。这是最简单、最基本,同时也是必须的测试用例,通常我们的编码人员自测也就是做到这个程度。

    2)、组合操作的测试

    这是从上一角度扩展出来的,相对而言也是编码人员不会去测试的,所以需要测试人员多作考虑。

    所谓组合操作测试,也就是选择某几个操作项,按一定的顺序进行操作,验证系统不会出现意外错误。当然要将所有功能项排列组合一遍来测试不仅不必要,也是不可能的。所以具体要将哪些功能项进行结合,要按怎样的步骤来操作,还是需要测试人员根据实际情况来作设计(所以说在IT业人才就是一切呀,呵呵:)。

    一般来说我们会考虑功能项之间的数据是否会存在关联,若有就需要考虑这种组合了。常见的如查询功能,需要将各条件逐一累加进行测试;增完的数据能否改,改完能否删,删完能否再增,这之间能否查询到正确结果;按钮的连续多次点击会否出现异常;有严格前后顺序要求的几个操作,尝试颠倒顺序去操作,系统能否控制等等。

    不仅在某功能内部,扩展到有关联的多个功能项之间,同样有组合操作测试的存在。如申报完了能才反馈;如申报成功或失败后再尝试申报等。当然对于这类用例既可以写到某个功能切面中,也可以单独写到完整业务流程的切面中,这就取决于可能涉及用例的数量了,若关系比较复杂,当然是单独写比较好;若也就是三五个用例数,那就直接在某个功能的用例中补充好了。

     

    3)、GUI界面的测试

    这类测试是测试人员的强项,具体测试项目如限长、非法输入等等,就不必赘述了。要提醒的是在测试时,一定要从实际使用者的操作习惯出发。要知道界面原型所能确定的也只是页面的摆放显示,而实际操作时的控制实现仍是编码人员自行实现的,即使有编码指南,其所及范围也是十分有限。而许多编码人员在用户操作方便性上的考虑往往差强人意。所以测试人员就必须要把好这一关。

    4)、数据初始化情况测试

    不该为空的数据是否有校验;该有默认值的数据默认值是否正确;引用其它功能生成的数据,是否会实时刷新;页面关闭或系统重启后,数据的初始化设置等都是这类用例。

    5)、业务需求实现是否正确

    这类问题往往是由于我们的需求说明欠详细,而编码人员的需求了解程度又较低造成。作为测试人员自然要对需求进行深刻研究,来对软件实现进行把关。这里常见的一些关注点有:

          数据的长度、类型控制是否合理(比如控制纳税人识别号只能为数字,但实际业务中是会有字母出现的);

          业务逻辑控制是否合理(比如某数据项不提供修改,但实际业务中该数据项经常会需要改动);

          提供的实现方式是否合理(比如只在某一页面提供某数据的获取功能,但根据业务划分有些人员不能操作此页面,却必须要能看到该数据);

          所做的数据控制是否合理(比如必须在A功能中新增数据,然后才能在B功能中操作,但实际业务中有可能会出现相反操作);

          所做的数据控制是否完整(如授权的方式有普通按月、有买断、有按数量控制,那么当同一企业尝试同时存在以上几种授权方式时,系统是否能有必要的控制);

          还有其它一些操作细节上的满足(如业务上需要批量操作的数据有否提供批量操作功能、导入失败的结果文件是否能修改后直接再导入等)。

    对于不满足的需求,经开发组长、需求经理等确认不作修改的,就要作为软件的缺限或限制在测试报告中进行说明民。

    2、功能切面隐含测试项用例设计:

    1)、数据完整性的测试

    当某数据被其它功能引用;或当前功能要引用其它来源的数据,就会涉及到数据完整性的测试。最常见的如被引用的数据删除了,或关键字被修改了,引用的数据会否出错;两个途径进入的数据会否冲突或重复;此外还有因为相关的几个功能由不同人员编码,从而导致彼此的控制不一致,如A功能进入的数据在可允许的极端情况下,到B功能中引用会否异常(最常见如用户名录入时允许长度10,但引用到某个单子填写时允许长度是8,此时就会异常了)。

    2)、后台的特殊处理

    是指某功能除了表面所见以外的程序处理。比如订单录入,表面所见的就是订单的保存,但后台还会有重复数据的判断、非法数据的处理、业务逻辑上冲突情况的处理以及其它种种根据需求设计所特有的处理。又比如备份功能,在备份前可能有数据的清空、备份目录的清空、备份目标是否存在的校验、备份文件重复时的处理等等。类似这些在分析设计中就未必会写全了,还是要测试人员多花心思去思考挖掘。

    3)、功能业务之间的关联与转换

    相关联的几个功能之间数据的传递,会否产生影响。比如新增录入的某种特殊字符,要查询时会引起查询SQL语句异常;又如某下载文件名中存在中文等字符,下载时由于编码问题导致乱码的出现;再有报表填写时到小数点后四位,生成报文时会不会被忽略成两位了等等。象这种问题,通常只能是在每个功能设计用例时,尽量保证用例中的数据能涉及到允许范围的各种情况,即充分运用等价类划分+边界值的方法设计出各种稀奇古怪的数据,并需验证这些数据从头流到尾,都还是能保持其正确性,而不仅仅是在当前功能中正确。

    4)、从设计实现发掘测试点

    这个就是我们测试中最难捉的BUG了,它往往是由编码人员自己在编码时创造出来的,连设计人员都不会知道。

    比如内部管理系统中,正常的产品,其类别通常是2位数字;如果是模块,其类别就以产品代码来取代。这时如何来判断该产品是模块呢?最保险的当然是校验其产品类别字段的值能否在产品表中找到;也有比较简单的方法就是直接判断类别代码大于2位还是小于等于2位。此时若能确切知道采用的是哪种实现方法,就可以直接找到其漏洞所在。比如采用后一种方法,当产品类别长度变化时,明显系统会出错。那么即使确认该实现方式不改,测试人员也应将其作为限制写入测试报告,。让大家知道这个产品类别长度是不能随意变化的。

    而让人郁闷的是,类似这样的实现,有太多的编码人员都是随性处理的,它们细而隐蔽,在系统数据正常情况下根本不会被发现;而在漫漫的软件使用道路中,由于需求变更等原因对原有一些设计做维护变化,这种问题就会突然暴发出来让人措不及防。所以要杜绝这类漏洞,除了测试人员要做土拨鼠,不停地对软件各功能的实现细节进行挖掘外,也要多给编码人员灌输完美实现的理念,多用复杂但抗压性高的代码,来替代简单但依赖性强的代码。

    5)、并发操作时的测试

    即两个或多个用户同时操作同一功能时,会否引起数据的混乱。通常在C/S结构下,如果有同时操作的可能,是需要作此测试的;而在B/S结构下由于其特殊性,此问题通常难以解决。除非就是某用户一旦使用过某功能后,在一定时间内锁定不允许再用,但这也会带来实际应用中的不便,所以除非是特别核心的数据,一般我们也不会去做此控制,当然对于可能出现的并发冲突也就作为系统的限制进行遗留了。

    3、特定切面用例设计

    所谓特定切面,其实就是从另一个角度切割出来的用例面,所以具体的用例撰写方式其实与功能切面是一致的。

    4、隐含切面用例设计

    隐含切面分以下几种情况:

    1)、无界面的后台功能

    对这类测试项,需要通过参数设置、代码调用等方式来实现测试,但具体的测试设计其实与普通功能测试并无二致。这里要注意,因为测试时往往前台、后台是分开来分别进行的,而实际运行时两者很可能是交集的,所以测试时要多注意后台功能的执行与前台的一些功能执行会否产生冲突?比如后台有个文件搬运的服务,那有没有可能在前台文件生成过程中,后台执行文件搬运了?若有可能就要注意会否出现问题了。

    2)、与业务流相关的测试

    这类测试用例的设计,就要从完整业务角度来设计数据了。从理论上来讲,应该要将各个功能可能出现的各种数据排列组合到一起,按业务流程逐一进行测试。但实际上我们不可能去做全覆盖。所以设计这类用例时,最好有一张草稿,将所有相关功能按业务流程逐一列示,然后再将每个功能可能出现的特定数据一一标上,最后将图中最可能出现的、最可能出错的、最核心的数据取出来,分别组合成一个个完整的业务数据用例,来进行测试。这样就可以按清晰的思路,找出最实用、最有效的测试数据。

    3)、其它测试类型

    这一类的测试通常都有其特定的方法。如要测可靠性就准备大量数据不停地执行;要测安全性就考虑数据的加密、数据的传输、数据的破坏;恢复性一般从网络、电源方面着手;配置安装则根据系统可支持的配置,搭建相应环境进行功能验证,此处的验证也要掌握技巧,即要多测试那些涉及到:数据库读写、磁盘文件读写、文件上传下载、文件加解密、数据统计、图表展现、打印等方面的功能。

     

    三、测试数据的设计

    每一个测试思路最终都要转化成具体的数据才能来执行。关于测试数据设计的方法也不外乎那几种,就不再赘述了。此处单就一些经常易犯的错误,提出一些注意点,作为用例数据设计时的参考:

    1、尽量避免可能出现歧义测试结果的数据:即你设计的数据必须能唯一正确地反映出你所希望测试的结果。比如一组测试数据,有可能得到结果A或结果B,此时单用此数据来测试预期结果为A的用例,那明显就产生了歧义。

    2、对于不便具体列示的数据,则必须详细描述其各项特性:有时我们在设计用例时为节约时间,不一定要到具体的一个数值,这也是允许的,但前提是你必须要详细描述清楚你要测试的数据特性。比如数据库字段限长20,要测试超长数据时,可以描述为:尝试输入长度为21位的半角英文字符;尝试输入长度为19位的半角英文字符,然后切换到中文全角再输入一位全角字符等。千万不能写成:尝试输入超长字符,因为这只能是测试方案,作为方案是可以这样写,但到用例阶段,必须要是具体的、明确的、可操作的。

    3、测试数据的设计必须有明确目的性:即测试数据是从测试方案衍生而来的。如上例测试方案是测超长字符输入控制,所以测试数据就要根据具体字段长度来录入超长数据,如果一味录入长15位、长16位的数据那就没意义了。好的测试数据是可以同时针对多个测试方案的,此时可以在用例边注明一下该数据的测试目的,因为随着时间推移,对着具体的数据你也许会忘了它到底是测什么的,而这对你最后总结测试,查验测试覆盖率是非常不利的,所以随时记下你的思路想法吧,好记性不如烂笔头。

    4、测试数据可省略描述:测试数据描述以能让人看懂为准则。所以写用例时当碰到连续几个用例,仅某几个关键数据值改动,其余均是一样的情况下,不必每个用例都要重复描述所有数据,可以在第一个用例描述完整之后,其余用例中仅列示不同的数据,并标明其余数据同上第X个用例,即可。这样测试时仍能复原测试数据,且该用例的测试目的一眼就明,增加了用例的清晰性。

    至些,我根据测试用例设计的顺序,从测试数据的切面设计(即测试项划分),到详细测试用例设计,再到测试数据设计三个层面,逐一介绍了如何来提高测试用例的覆盖度。因为具体项目中的具体情况太多,以上叙述的内容也只能是管窥蠡测。至于其中的疏漏错误之处应也难免,只希望各位阅后能打开思路,从自己多年的测试经验中多总结、提炼出一些想法思路,进一步补充完善这个文档,使大家的测试用例设计能力都能进一步提升。

    转载于:https://www.cnblogs.com/nichoc/p/6824751.html

    展开全文
  • 测试用例的设计-提高测试覆盖率 前言 说到测试用例的设计,我想每有过测试经历的测试工程师都会认为很简单,不就是:按需求或概要设计,得到软件功能划分图,然后据此按每功能,采用等价类划分、临界值、因果...

    原文:https://www.cnblogs.com/nichoc/p/6824751.html

    测试用例的设计-提高测试覆盖率

    前言

    说到测试用例的设计,我想每个有过测试经历的测试工程师都会认为很简单,不就是:按需求或概要设计,得到软件功能划分图,然后据此按每个功能,采用等价类划分、临界值、因果图等方法来设计用例就行了。

    但事实上撇开测试数据的设计不谈,仅就测试项来说,我们发现,对同一个项目,有经验的测试人员,在写用例或测试时总会有更多的测试考虑点,从而发现更多的问题;而有些测试人员测试用例的撰写却只有那么三板斧,表面看好象已经把页面所有信息的测试都考虑到了,实际上却还是遗漏了大量测试覆盖点,导致其测试出来的程序总是比较脆弱。

    究其原因,我觉得还是测试用例的撰写水平不到位,更确切地说是测试用例的覆盖度太低。说实话我认为系统测试用例真正做到100%覆盖是很难的。难道说按设计中的功能划分,每个功能都写到了这个用例就覆盖完整了?错,这还远远不够。因为我们知道还有大量的内部处理、转换、业务逻辑、相互影响的关系等都是需求或设计中所不会点明的。而这些一方面需要靠测试人员对项目本身的了解,另一方面要靠测试人员的经验,来一一找到这些隐藏点并予以测试,才能真正地保证我们的测试覆盖度。

    所以本文抛开具体的测试数据设计方法,主要从测试覆盖度的角度来介绍用例设计时,如何才能考虑地更周全,如何才能将隐藏的测试项一一找出,从而使我们的测试更全面更完整。

    想法虽然美好,可是毕竟每个测试的项目都是各不相同,针对不同项目我们的经验也会告诉给我们不同的想法,这些想法通常很感性,很难用严密的逻辑理论来把它升华。因此本文的内容仍是很简陋且不成熟,只是希望能以本文为砖,引起大家的思考,一起来补充完善,以使我们的测试用例设计水平不断提高。

     

    正文

    一、测试用例的切面设计

    1、功能点切面

    2、特定切面

    3、隐含切面

    (1)、后台功能

    (2)、完整业务流程的测试

    (3)、某种特定情况下的系统运行 

    (4)、其它相关系统

    (5)、除功能测试外的其它测试类型

    二、详细用例的设计

    1、功能切面表面用例设计

    (1)、具体功能测试

    (2)、组合操作的测试

    (3)、GUI界面的测试

    (4)、数据初始化情况测试

    (5)、业务需求实现是否正确

    2、功能切面隐含测试项用例设计:

    (1)、数据完整性的测试

    (2)、后台的特殊处理

    (3)、功能业务之间的关联与转换

    (4)、从设计实现发掘测试点

    (5)、并发操作时的测试

    3、特定切面用例设计

    4、隐含切面用例设计

    (1)、无界面的后台功能

    (2)、与业务流相关的测试

    (3)、其它测试类型

    三、测试数据的设计

    一、测试用例的切面设计

    所谓测试切面设计,其实就是测试用例大项的划分。测试用例划分的经典方法是瀑布模型,也就是从上到下,逐渐细分,大模块包括小模块,小模块包括更小的模块。但仅仅如此是不够的,我们还要从更多的角度切入系统,从不同的角度把系统切分成一块一块的,来进行测试,从而确保测试大项的完整性。

    1、功能点切面

    这是最常见的切面,通常我们认为页面上的一个按钮就是一个功能点。然后我们可以根据功能的复杂程度,按每个功能;或一个功能点分多页;或多个功能点合成一页来进行用例的撰写。

    2、特定切面

    除此以外,还有一种特定切面的划分方法,也是用例撰写时经常会用到的。所谓的特定切面,就是忽略掉表面上的功能点,而关注测试对象的某一个面。比如我们的内部管理系统提供了销售录入导入、注册录入导入等功能,从菜单划分上对应了七八个功能点。但这些功能处理后台有个共同的处理项就是授权记录的生成,这时我们就可以把“授权记录生成”单独拿出来做一个测试项,而在其它测试项中涉及这一部分的用例就不必再一一撰写。此外象一些界面共通的操作用例单独写成一页,也是一种特定切面。所以如果说将用例按功能点划分是一种纵向划分法,那么特定切面就是从横向的角度分析所得到的切面。在普通功能点划分上再根据实际情况设计特定切面,可以使我们的用例阅读性、理解性、操作性更强。

    3、隐含切面

    这类用例是最容易被忽略的。它往往不是明显的某个功能项,可能是功能项后台的隐含处理,也可能是多个功能项之间的关联处理,甚至可能是在某种特定情形下的处理。这都需要测试人员通过对软件的学习了解,来进行挖掘。

    1)、后台功能

    常见的如一些定时自动启动的服务;以及某种特定情况下自动执行的操作等。它们在界面上往往是不体现的,但许多在需求设计中还是会提到,也有一些比较细小的功能可能会被忽略,就需要测试人员根据对项目的了解程度来进行挖掘。所以说一个熟悉项目的和一个不熟悉的测试人员,写出来的用例就完全是两个层次的。

     

    2)、完整业务流程的测试

    我们都知道测试用例的设计是从点、线、面三个层次去考虑的。完整的一个功能项是线,其中的某个按钮是点,多个相关功能结合成完整业务流就是面。从实际来看这类用例往往被我们忽略。

    事实上目前公司的软件本来都是业务型应用软件,将各种功能从业务流中切割出来单独写用例,肯定也会有涉及到整体流程的情况。若不加以区分,将细节与全局搅在一起,不仅思路混乱,也容易考虑不周。因此在系统测试阶段,建议用例设计要有分有合,针对具体功能的就只围着这个功能转:而在业务流程测试项中,再完全从整体的业务流角度出发去考虑用例,这样不仅不容易产生疏漏,用例阅读与执行也更清楚。

    3)、某种特定情况下的系统运行

    这类用例的设计往往与系统实际业务情况密不可分。比如财务软件,通常需要在月尾一天、月头一天、年尾一天、年头一天,对所有相关功能中的日期处理进行测试;又比如WIN 2000环境开发测试的系统,要测试在98、XP、2003等操作系统下是否能运行自如;再有如存在大量动态图片视频等的网页,在普通网速下的展现速度等等。总之就是要尽可能从实际应用的角度出发考虑,来进行测试补充。

    4)、其它相关系统

    即指在当前项目中直接使用的其它成果,包括公司自有的系统模块、组件、函数;以及购买或免费得到的一些功能组件。对这些内容需要预先与开发组长等讨论清楚,是否需要测试。若时间紧张或其它原因决定不测的,应在测试计划中说明。若需要测试的,则具体可根据实际情况来设计,可以是通过系统某个功能的测试来涉及,此时就不需要单独划分测试项;若相对比较独立的,也可以通过单独的测试项来对其专门进行测试。

    5)、除功能测试外的其它测试类型

    包括可靠性、安全性、恢复性、配置安装测试等等,这些测试类型都是一个单独的测试项。

    所谓好的开始是成功的一半,保证测试项划分的完整、合理、正确,会直接影响到本次测试的成效。通常建议该阶段工作要花1-2天的时间来考虑,并要在测试过程中随着对软件的深入了解,不断进行调整补充。可千万不要认为把分析设计中的功能模型图搬搬过来就可以了。

    二、详细用例的设计

    划分好了测试项,接着就是针对各个测试项,考虑具体的测试用例了。根据测试项的特点,测试用例的设计角度也有所不同。下面我们就来看看通常的功能点测试用例,该从哪些角度出发来进行设计:

    1、功能切面表面用例设计

    1)、具体功能测试

    根据需求分析设计,按页面提供的各个功能项,采用黑盒测试的各种方法,设计用例。比如页面提供了增、删、改、查功能,那么这四个功能是否正确实现就是我要验证的。这是最简单、最基本,同时也是必须的测试用例,通常我们的编码人员自测也就是做到这个程度。

    2)、组合操作的测试

    这是从上一角度扩展出来的,相对而言也是编码人员不会去测试的,所以需要测试人员多作考虑。

    所谓组合操作测试,也就是选择某几个操作项,按一定的顺序进行操作,验证系统不会出现意外错误。当然要将所有功能项排列组合一遍来测试不仅不必要,也是不可能的。所以具体要将哪些功能项进行结合,要按怎样的步骤来操作,还是需要测试人员根据实际情况来作设计(所以说在IT业人才就是一切呀,呵呵:)。

    一般来说我们会考虑功能项之间的数据是否会存在关联,若有就需要考虑这种组合了。常见的如查询功能,需要将各条件逐一累加进行测试;增完的数据能否改,改完能否删,删完能否再增,这之间能否查询到正确结果;按钮的连续多次点击会否出现异常;有严格前后顺序要求的几个操作,尝试颠倒顺序去操作,系统能否控制等等。

    不仅在某功能内部,扩展到有关联的多个功能项之间,同样有组合操作测试的存在。如申报完了能才反馈;如申报成功或失败后再尝试申报等。当然对于这类用例既可以写到某个功能切面中,也可以单独写到完整业务流程的切面中,这就取决于可能涉及用例的数量了,若关系比较复杂,当然是单独写比较好;若也就是三五个用例数,那就直接在某个功能的用例中补充好了。

     

    3)、GUI界面的测试

    这类测试是测试人员的强项,具体测试项目如限长、非法输入等等,就不必赘述了。要提醒的是在测试时,一定要从实际使用者的操作习惯出发。要知道界面原型所能确定的也只是页面的摆放显示,而实际操作时的控制实现仍是编码人员自行实现的,即使有编码指南,其所及范围也是十分有限。而许多编码人员在用户操作方便性上的考虑往往差强人意。所以测试人员就必须要把好这一关。

    4)、数据初始化情况测试

    不该为空的数据是否有校验;该有默认值的数据默认值是否正确;引用其它功能生成的数据,是否会实时刷新;页面关闭或系统重启后,数据的初始化设置等都是这类用例。

    5)、业务需求实现是否正确

    这类问题往往是由于我们的需求说明欠详细,而编码人员的需求了解程度又较低造成。作为测试人员自然要对需求进行深刻研究,来对软件实现进行把关。这里常见的一些关注点有:

    u      数据的长度、类型控制是否合理(比如控制纳税人识别号只能为数字,但实际业务中是会有字母出现的);

    u      业务逻辑控制是否合理(比如某数据项不提供修改,但实际业务中该数据项经常会需要改动);

    u      提供的实现方式是否合理(比如只在某一页面提供某数据的获取功能,但根据业务划分有些人员不能操作此页面,却必须要能看到该数据);

    u      所做的数据控制是否合理(比如必须在A功能中新增数据,然后才能在B功能中操作,但实际业务中有可能会出现相反操作);

    u      所做的数据控制是否完整(如授权的方式有普通按月、有买断、有按数量控制,那么当同一企业尝试同时存在以上几种授权方式时,系统是否能有必要的控制);

    u      还有其它一些操作细节上的满足(如业务上需要批量操作的数据有否提供批量操作功能、导入失败的结果文件是否能修改后直接再导入等)。

    对于不满足的需求,经开发组长、需求经理等确认不作修改的,就要作为软件的缺限或限制在测试报告中进行说明民。

    2、功能切面隐含测试项用例设计:

    1)、数据完整性的测试

    当某数据被其它功能引用;或当前功能要引用其它来源的数据,就会涉及到数据完整性的测试。最常见的如被引用的数据删除了,或关键字被修改了,引用的数据会否出错;两个途径进入的数据会否冲突或重复;此外还有因为相关的几个功能由不同人员编码,从而导致彼此的控制不一致,如A功能进入的数据在可允许的极端情况下,到B功能中引用会否异常(最常见如用户名录入时允许长度10,但引用到某个单子填写时允许长度是8,此时就会异常了)。

    2)、后台的特殊处理

    是指某功能除了表面所见以外的程序处理。比如订单录入,表面所见的就是订单的保存,但后台还会有重复数据的判断、非法数据的处理、业务逻辑上冲突情况的处理以及其它种种根据需求设计所特有的处理。又比如备份功能,在备份前可能有数据的清空、备份目录的清空、备份目标是否存在的校验、备份文件重复时的处理等等。类似这些在分析设计中就未必会写全了,还是要测试人员多花心思去思考挖掘。

    3)、功能业务之间的关联与转换

    相关联的几个功能之间数据的传递,会否产生影响。比如新增录入的某种特殊字符,要查询时会引起查询SQL语句异常;又如某下载文件名中存在中文等字符,下载时由于编码问题导致乱码的出现;再有报表填写时到小数点后四位,生成报文时会不会被忽略成两位了等等。象这种问题,通常只能是在每个功能设计用例时,尽量保证用例中的数据能涉及到允许范围的各种情况,即充分运用等价类划分+边界值的方法设计出各种“稀奇古怪”的数据,并需验证这些数据从头流到尾,都还是能保持其正确性,而不仅仅是在当前功能中正确。

    4)、从设计实现发掘测试点

    这个就是我们测试中最难捉的BUG了,它往往是由编码人员自己在编码时创造出来的,连设计人员都不会知道。

    比如内部管理系统中,正常的产品,其类别通常是2位数字;如果是模块,其类别就以产品代码来取代。这时如何来判断该产品是模块呢?最保险的当然是校验其产品类别字段的值能否在产品表中找到;也有比较简单的方法就是直接判断类别代码大于2位还是小于等于2位。此时若能确切知道采用的是哪种实现方法,就可以直接找到其漏洞所在。比如采用后一种方法,当产品类别长度变化时,明显系统会出错。那么即使确认该实现方式不改,测试人员也应将其作为限制写入测试报告,。让大家知道这个产品类别长度是不能随意变化的。

    而让人郁闷的是,类似这样的实现,有太多的编码人员都是随性处理的,它们细而隐蔽,在系统数据正常情况下根本不会被发现;而在漫漫的软件使用道路中,由于需求变更等原因对原有一些设计做维护变化,这种问题就会突然暴发出来让人措不及防。所以要杜绝这类漏洞,除了测试人员要做土拨鼠,不停地对软件各功能的实现细节进行挖掘外,也要多给编码人员灌输完美实现的理念,多用复杂但抗压性高的代码,来替代简单但依赖性强的代码。

    5)、并发操作时的测试

    即两个或多个用户同时操作同一功能时,会否引起数据的混乱。通常在C/S结构下,如果有同时操作的可能,是需要作此测试的;而在B/S结构下由于其特殊性,此问题通常难以解决。除非就是某用户一旦使用过某功能后,在一定时间内锁定不允许再用,但这也会带来实际应用中的不便,所以除非是特别核心的数据,一般我们也不会去做此控制,当然对于可能出现的并发冲突也就作为系统的限制进行遗留了。

    3、特定切面用例设计

    所谓特定切面,其实就是从另一个角度切割出来的用例面,所以具体的用例撰写方式其实与功能切面是一致的。

    4、隐含切面用例设计

    隐含切面分以下几种情况:

    1)、无界面的后台功能

    对这类测试项,需要通过参数设置、代码调用等方式来实现测试,但具体的测试设计其实与普通功能测试并无二致。这里要注意,因为测试时往往前台、后台是分开来分别进行的,而实际运行时两者很可能是交集的,所以测试时要多注意后台功能的执行与前台的一些功能执行会否产生冲突?比如后台有个文件搬运的服务,那有没有可能在前台文件生成过程中,后台执行文件搬运了?若有可能就要注意会否出现问题了。

    2)、与业务流相关的测试

    这类测试用例的设计,就要从完整业务角度来设计数据了。从理论上来讲,应该要将各个功能可能出现的各种数据排列组合到一起,按业务流程逐一进行测试。但实际上我们不可能去做全覆盖。所以设计这类用例时,最好有一张草稿,将所有相关功能按业务流程逐一列示,然后再将每个功能可能出现的特定数据一一标上,最后将图中最可能出现的、最可能出错的、最核心的数据取出来,分别组合成一个个完整的业务数据用例,来进行测试。这样就可以按清晰的思路,找出最实用、最有效的测试数据。

    3)、其它测试类型

    这一类的测试通常都有其特定的方法。如要测可靠性就准备大量数据不停地执行;要测安全性就考虑数据的加密、数据的传输、数据的破坏;恢复性一般从网络、电源方面着手;配置安装则根据系统可支持的配置,搭建相应环境进行功能验证,此处的验证也要掌握技巧,即要多测试那些涉及到:数据库读写、磁盘文件读写、文件上传下载、文件加解密、数据统计、图表展现、打印等方面的功能。

     

    三、测试数据的设计

    每一个测试思路最终都要转化成具体的数据才能来执行。关于测试数据设计的方法也不外乎那几种,就不再赘述了。此处单就一些经常易犯的错误,提出一些注意点,作为用例数据设计时的参考:

    1、尽量避免可能出现歧义测试结果的数据:即你设计的数据必须能唯一正确地反映出你所希望测试的结果。比如一组测试数据,有可能得到结果A或结果B,此时单用此数据来测试预期结果为A的用例,那明显就产生了歧义。

    2、对于不便具体列示的数据,则必须详细描述其各项特性:有时我们在设计用例时为节约时间,不一定要到具体的一个数值,这也是允许的,但前提是你必须要详细描述清楚你要测试的数据特性。比如数据库字段限长20,要测试超长数据时,可以描述为:尝试输入长度为21位的半角英文字符;尝试输入长度为19位的半角英文字符,然后切换到中文全角再输入一位全角字符等。千万不能写成:尝试输入超长字符,因为这只能是测试方案,作为方案是可以这样写,但到用例阶段,必须要是具体的、明确的、可操作的。

    3、测试数据的设计必须有明确目的性:即测试数据是从测试方案衍生而来的。如上例测试方案是测超长字符输入控制,所以测试数据就要根据具体字段长度来录入超长数据,如果一味录入长15位、长16位的数据那就没意义了。好的测试数据是可以同时针对多个测试方案的,此时可以在用例边注明一下该数据的测试目的,因为随着时间推移,对着具体的数据你也许会忘了它到底是测什么的,而这对你最后总结测试,查验测试覆盖率是非常不利的,所以随时记下你的思路想法吧,好记性不如烂笔头。

    4、测试数据可省略描述:测试数据描述以能让人看懂为准则。所以写用例时当碰到连续几个用例,仅某几个关键数据值改动,其余均是一样的情况下,不必每个用例都要重复描述所有数据,可以在第一个用例描述完整之后,其余用例中仅列示不同的数据,并标明其余数据同上第X个用例,即可。这样测试时仍能复原测试数据,且该用例的测试目的一眼就明,增加了用例的清晰性。

    至些,我根据测试用例设计的顺序,从测试数据的切面设计(即测试项划分),到详细测试用例设计,再到测试数据设计三个层面,逐一介绍了如何来提高测试用例的覆盖度。因为具体项目中的具体情况太多,以上叙述的内容也只能是管窥蠡测。至于其中的疏漏错误之处应也难免,只希望各位阅后能打开思路,从自己多年的测试经验中多总结、提炼出一些想法思路,进一步补充完善这个文档,使大家的测试用例设计能力都能进一步提升。

    展开全文
  • 数据库面试考题一览(全面覆盖

    万次阅读 2020-04-01 22:56:13
    属性可以为作为一超键,多属性组合在一起也可以作为一超键。超键包含候选键和主键。 候选键:是最小超键,即没有冗余元素的超键。 主键:数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的...

    一、基本概念


     

    1.主键、外键、超键、候选键

    超键:在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以为作为一个超键,多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。

    候选键:是最小超键,即没有冗余元素的超键。

    主键:数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合。一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null)。

    外键:在一个表中存在的另一个表的主键称此表的外键。

    2.为什么用自增列作为主键

    如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引、

    如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引、

    如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。

    数据记录本身被存于主索引(一颗B+Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)

    如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页

    如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

    3.触发器的作用?

    触发器是一种特殊的存储过程,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。

    4.什么是存储过程?用什么来调用?

    存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。

    调用:

    1)可以用一个命令对象来调用存储过程。

    2)可以供外部程序调用,比如:java程序。

    5.存储过程的优缺点?

    优点:

    1)存储过程是预编译过的,执行效率高。

    2)存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯。

    3)安全性高,执行存储过程需要有一定权限的用户。

    4)存储过程可以重复使用,可减少数据库开发人员的工作量。

    缺点:移植性差

    6.存储过程与函数的区别

    7.什么叫视图?游标是什么?

    视图:

    是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的修改会影响基本表。它使得我们获取数据更容易,相比多表查询。

    游标:

    是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行,从结果集的当前行检索一行或多行。可以对结果集当前行做修改。一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要。

    8.视图的优缺点

    优点:

    1对数据库的访问,因为视图可以有选择性的选取数据库里的一部分。

    2)用户通过简单的查询可以从复杂查询中得到结果。

    3)维护数据的独立性,试图可从多个表检索数据。

    4)对于相同的数据可产生不同的视图。

    缺点:

    性能:查询视图时,必须把视图的查询转化成对基本表的查询,如果这个视图是由一个复杂的多表查询所定义,那么,那么就无法更改数据

    9.drop、truncate、 delete区别

    最基本:

    • drop直接删掉表。

    • truncate删除表中数据,再插入时自增长id又从1开始。

    • delete删除表中数据,可以加where字句。

    (1) DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。TRUNCATE TABLE 则一次性地从表中删除所有的数据并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。

    (2) 表和索引所占空间。当表被TRUNCATE 后,这个表和索引所占用的空间会恢复到初始大小,而DELETE操作不会减少表或索引所占用的空间。drop语句将表所占用的空间全释放掉。

    (3) 一般而言,drop > truncate > delete

    (4) 应用范围。TRUNCATE 只能对TABLE;DELETE可以是table和view

    (5) TRUNCATE 和DELETE只删除数据,而DROP则删除整个表(结构和数据)。

    (6) truncate与不带where的delete :只删除数据,而不删除表的结构(定义)drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger)索引(index);依赖于该表的存储过程/函数将被保留,但其状态会变为:invalid。

    (7) delete语句为DML(data maintain Language),这个操作会被放到 rollback segment中,事务提交后才生效。如果有相应的 tigger,执行的时候将被触发。

    (8) truncate、drop是DLL(data define language),操作立即生效,原数据不放到 rollback segment中,不能回滚。

    (9) 在没有备份情况下,谨慎使用 drop 与 truncate。要删除部分数据行采用delete且注意结合where来约束影响范围。回滚段要足够大。要删除表用drop;若想保留表而将表中数据删除,如果于事务无关,用truncate即可实现。如果和事务有关,或老师想触发trigger,还是用delete。

    (10) Truncate table 表名 速度快,而且效率高,因为:?truncate table 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。

    (11) TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。

    (12) 对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。

    10.什么是临时表,临时表什么时候删除?

    临时表可以手动删除:
    DROP TEMPORARY TABLE IF EXISTS temp_tb;

    临时表只在当前连接可见,当关闭连接时,MySQL会自动删除表并释放所有空间。因此在不同的连接中可以创建同名的临时表,并且操作属于本连接的临时表。
    创建临时表的语法与创建表语法类似,不同之处是增加关键字TEMPORARY,

    如:

    CREATE TEMPORARY TABLE tmp_table (

    NAME VARCHAR (10) NOT NULL,

    time date NOT NULL
    );

    select * from tmp_table;

    11.非关系型数据库和关系型数据库区别,优势比较?

    非关系型数据库的优势:

    • 性能:NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。

    • 可扩展性:同样也是因为基于键值对,数据之间没有耦合性,所以非常容易水平扩展。

    关系型数据库的优势:

    • 复杂查询:可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。

    • 事务支持:使得对于安全性能很高的数据访问要求得以实现。

    其他:

    1.对于这两类数据库,对方的优势就是自己的弱势,反之亦然。

    2.NOSQL数据库慢慢开始具备SQL数据库的一些复杂查询功能,比如MongoDB。

    3.对于事务的支持也可以用一些系统级的原子操作来实现例如乐观锁之类的方法来曲线救国,比如Redis set nx。

    12.数据库范式,根据某个场景设计数据表?

    第一范式:(确保每列保持原子性)所有字段值都是不可分解的原子值。

    第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。
    第一范式的合理遵循需要根据系统的实际需求来定。比如某些数据库系统中需要用到“地址”这个属性,本来直接将“地址”属性设计成一个数据库表的字段就行。但是如果系统经常会访问“地址”属性中的“城市”部分,那么就非要将“地址”这个属性重新拆分为省份、城市、详细地址等多个部分进行存储,这样在对地址中某一部分操作的时候将非常方便。这样设计才算满足了数据库的第一范式,如下表所示。
    上表所示的用户信息遵循了第一范式的要求,这样在对用户使用城市进行分类的时候就非常方便,也提高了数据库的性能。

    第二范式:(确保表中的每列都和主键相关)在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。

    第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
    比如要设计一个订单信息表,因为订单中可能会有多种商品,所以要将订单编号和商品编号作为数据库表的联合主键。

    第三范式:(确保每列都和主键列直接相关,而不是间接相关) 数据表中的每一列数据都和主键直接相关,而不能间接相关。

    第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
    比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。

    BCNF:符合3NF,并且,主属性不依赖于主属性。

    若关系模式属于第二范式,且每个属性都不传递依赖于键码,则R属于BC范式。
    通常BC范式的条件有多种等价的表述:每个非平凡依赖的左边必须包含键码;每个决定因素必须包含键码。
    BC范式既检查非主属性,又检查主属性。当只检查非主属性时,就成了第三范式。满足BC范式的关系都必然满足第三范式。
    还可以这么说:若一个关系达到了第三范式,并且它只有一个候选码,或者它的每个候选码都是单属性,则该关系自然达到BC范式。
    一般,一个数据库设计符合3NF或BCNF就可以了。

    第四范式:要求把同一表内的多对多关系删除。

    第五范式:从最终结构重新建立原始结构。

    13.什么是 内连接、外连接、交叉连接、笛卡尔积等?

    内连接: 只连接匹配的行

    左外连接: 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行

    右外连接: 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行

    例如1:
    SELECT a.,b. FROM luntan LEFT JOIN usertable as b ON a.username=b.username

    例如2:
    SELECT a.,b. FROM city as a FULL OUTER JOIN user as b ON a.username=b.username

    全外连接: 包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。

    交叉连接: 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配

    例如:
    SELECT type,pub_name FROM titles CROSS JOIN publishers ORDER BY type

    注意:

    很多公司都只是考察是否知道其概念,但是也有很多公司需要不仅仅知道概念,还需要动手写sql,一般都是简单的连接查询,具体关于连接查询的sql练习,参见以下链接:

    牛客网数据库SQL实战

    leetcode中文网站数据库练习

    我的另一篇文章,常用sql练习50题

    14.varchar和char的使用场景?

    1.char的长度是不可变的,而varchar的长度是可变的。

    定义一个char[10]和varchar[10]。
    如果存进去的是‘csdn’,那么char所占的长度依然为10,除了字符‘csdn’外,后面跟六个空格,varchar就立马把长度变为4了,取数据的时候,char类型的要用trim()去掉多余的空格,而varchar是不需要的。

    2.char的存取数度还是要比varchar要快得多,因为其长度固定,方便程序的存储与查找。
    char也为此付出的是空间的代价,因为其长度固定,所以难免会有多余的空格占位符占据空间,可谓是以空间换取时间效率。
    varchar是以空间效率为首位。

    3.char的存储方式是:对英文字符(ASCII)占用1个字节,对一个汉字占用两个字节。
    varchar的存储方式是:对每个英文字符占用2个字节,汉字也占用2个字节。

    4.两者的存储数据都非unicode的字符数据。

    15.SQL语言分类

    SQL语言共分为四大类:

    • 数据查询语言DQL

    • 数据操纵语言DML

    • 数据定义语言DDL

    • 数据控制语言DCL。

    1. 数据查询语言DQL

    数据查询语言DQL基本结构是由SELECT子句,FROM子句,WHERE子句组成的查询块:

    SELECT
    FROM
    WHERE

    2 .数据操纵语言DML

    数据操纵语言DML主要有三种形式:

    1) 插入:INSERT

    2) 更新:UPDATE

    3) 删除:DELETE

    3. 数据定义语言DDL

    数据定义语言DDL用来创建数据库中的各种对象-----表、视图、索引、同义词、聚簇等如:
    CREATE TABLE/VIEW/INDEX/SYN/CLUSTER

    表 视图 索引 同义词 簇

    DDL操作是隐性提交的!不能rollback

    4. 数据控制语言DCL

    数据控制语言DCL用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等。如:

    1) GRANT:授权。

    2) ROLLBACK [WORK] TO [SAVEPOINT]:回退到某一点。回滚---ROLLBACK;回滚命令使数据库状态回到上次最后提交的状态。其格式为:
    SQL>ROLLBACK;

    3) COMMIT [WORK]:提交。

    在数据库的插入、删除和修改操作时,只有当事务在提交到数据
    库时才算完成。在事务提交前,只有操作数据库的这个人才能有权看
    到所做的事情,别人只有在最后提交完成后才可以看到。
    提交数据有三种类型:显式提交、隐式提交及自动提交。下面分
    别说明这三种类型。

    (1) 显式提交
    用COMMIT命令直接完成的提交为显式提交。其格式为:
    SQL>COMMIT;

    (2) 隐式提交
    用SQL命令间接完成的提交为隐式提交。这些命令是:
    ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,
    EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。

    (3) 自动提交
    若把AUTOCOMMIT设置为ON,则在插入、修改、删除语句执行后,
    系统将自动进行提交,这就是自动提交。其格式为:
    SQL>SET AUTOCOMMIT ON;

    参考文章:
    https://www.cnblogs.com/study-s/p/5287529.html

    16.like %和-的区别

    通配符的分类:

    %百分号通配符:表示任何字符出现任意次数(可以是0次).

    _下划线通配符:表示只能匹配单个字符,不能多也不能少,就是一个字符.

    like操作符: LIKE作用是指示mysql后面的搜索模式是利用通配符而不是直接相等匹配进行比较.

    注意: 如果在使用like操作符时,后面的没有使用通用匹配符效果是和=一致的,SELECT * FROM products WHERE products.prod_name like '1000';
    只能匹配的结果为1000,而不能匹配像JetPack 1000这样的结果.

    • %通配符使用: 匹配以"yves"开头的记录:(包括记录"yves") SELECT FROM products WHERE products.prod_name like 'yves%';
      匹配包含"yves"的记录(包括记录"yves") SELECT
       FROM products WHERE products.prod_name like '%yves%';
      匹配以"yves"结尾的记录(包括记录"yves",不包括记录"yves ",也就是yves后面有空格的记录,这里需要注意) SELECT * FROM products WHERE products.prod_name like '%yves';

    • 通配符使用: SELECT FROM products WHERE products.prod_name like '_yves'; 匹配结果为: 像"yyves"这样记录.
      SELECT
       FROM products WHERE products.prod*name like 'yves
      *'; 匹配结果为: 像"yvesHe"这样的记录.(一个下划线只能匹配一个字符,不能多也不能少)

    注意事项:

    • 注意大小写,在使用模糊匹配时,也就是匹配文本时,mysql是可能区分大小的,也可能是不区分大小写的,这个结果是取决于用户对MySQL的配置方式.如果是区分大小写,那么像YvesHe这样记录是不能被"yves__"这样的匹配条件匹配的.

    • 注意尾部空格,"%yves"是不能匹配"heyves "这样的记录的.

    • 注意NULL,%通配符可以匹配任意字符,但是不能匹配NULL,也就是说SELECT * FROM products WHERE products.prod_name like '%;是匹配不到products.prod_name为NULL的的记录.

    技巧与建议:

    正如所见, MySQL的通配符很有用。但这种功能是有代价的:通配符搜索的处理一般要比前面讨论的其他搜索所花时间更长。这里给出一些使用通配符要记住的技巧。

    • 不要过度使用通配符。如果其他操作符能达到相同的目的,应该 使用其他操作符。

    • 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用 在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起 来是最慢的。

    • 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数.

    参考博文:https://blog.csdn.net/u011479200/article/details/78513632

    17.count(*)、count(1)、count(column)的区别

    • count(*)对行的数目进行计算,包含NULL

    • count(column)对特定的列的值具有的行数进行计算,不包含NULL值。

    • count()还有一种使用方式,count(1)这个用法和count(*)的结果是一样的。

    性能问题:

    1.任何情况下SELECT COUNT(*) FROM tablename是最优选择;

    2.尽量减少SELECT COUNT(*) FROM tablename WHERE COL = ‘value’ 这种查询;

    3.杜绝SELECT COUNT(COL) FROM tablename WHERE COL2 = ‘value’ 的出现。

    • 如果表没有主键,那么count(1)比count(*)快。

    • 如果有主键,那么count(主键,联合主键)比count(*)快。

    • 如果表只有一个字段,count(*)最快。

    count(1)跟count(主键)一样,只扫描主键。count(*)跟count(非主键)一样,扫描整个表。明显前者更快一些。

    18.最左前缀原则

    多列索引:

    ALTER TABLE people ADD INDEX lname_fname_age (lame,fname,age);

    为了提高搜索效率,我们需要考虑运用多列索引,由于索引文件以B-Tree格式保存,所以我们不用扫描任何记录,即可得到最终结果。

    注:在mysql中执行查询时,只能使用一个索引,如果我们在lname,fname,age上分别建索引,执行查询时,只能使用一个索引,mysql会选择一个最严格(获得结果集记录数最少)的索引。

    最左前缀原则:顾名思义,就是最左优先,上例中我们创建了lname_fname_age多列索引,相当于创建了(lname)单列索引,(lname,fname)组合索引以及(lname,fname,age)组合索引。

    二、索引


     

    1.什么是索引?

    何为索引:

    数据库索引,是数据库管理系统中一个排序的数据结构,索引的实现通常使用B树及其变种B+树。

    在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

    2.索引的作用?它的优点缺点是什么?

    索引作用:

    协助快速查询、更新数据库表中数据。

    为表设置索引要付出代价的:

    • 一是增加了数据库的存储空间

    • 二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。

      3.索引的优缺点?

    创建索引可以大大提高系统的性能(优点):

    1.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

    2.可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

    3.可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

    4.在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

    5.通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

    增加索引也有许多不利的方面(缺点):

    1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

    2.索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

    3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

    4.哪些列适合建立索引、哪些不适合建索引?

    索引是建立在数据库表中的某些列的上面。在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引。

    一般来说,应该在这些列上创建索引:

    (1)在经常需要搜索的列上,可以加快搜索的速度;

    (2)在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;

    (3)在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;

    (4)在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;

    (5)在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;

    (6)在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

    对于有些列不应该创建索引:

    (1)对于那些在查询中很少使用或者参考的列不应该创建索引。

    这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

    (2)对于那些只有很少数据值的列也不应该增加索引。

    这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。

    (3)对于那些定义为text, image和bit数据类型的列不应该增加索引。

    这是因为,这些列的数据量要么相当大,要么取值很少。

    (4)当修改性能远远大于检索性能时,不应该创建索引。

    这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

    5.什么样的字段适合建索引

    唯一、不为空、经常被查询的字段

    6.MySQL B+Tree索引和Hash索引的区别?

    Hash索引和B+树索引的特点:

    • Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位;

    • B+树索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问;

    为什么不都用Hash索引而使用B+树索引?

    1. Hash索引仅仅能满足"=","IN"和""查询,不能使用范围查询,因为经过相应的Hash算法处理之后的Hash值的大小关系,并不能保证和Hash运算前完全一样;

    1. Hash索引无法被用来避免数据的排序操作,因为Hash值的大小关系并不一定和Hash运算前的键值完全一样;

    1. Hash索引不能利用部分索引键查询,对于组合索引,Hash索引在计算Hash值的时候是组合索引键合并后再一起计算Hash值,而不是单独计算Hash值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash索引也无法被利用;

    1. Hash索引在任何时候都不能避免表扫描,由于不同索引键存在相同Hash值,所以即使取满足某个Hash键值的数据的记录条数,也无法从Hash索引中直接完成查询,还是要回表查询数据;

    1. Hash索引遇到大量Hash值相等的情况后性能并不一定就会比B+树索引高。

    补充:

    1.MySQL中,只有HEAP/MEMORY引擎才显示支持Hash索引。

    2.常用的InnoDB引擎中默认使用的是B+树索引,它会实时监控表上索引的使用情况,如果认为建立哈希索引可以提高查询效率,则自动在内存中的“自适应哈希索引缓冲区”建立哈希索引(在InnoDB中默认开启自适应哈希索引),通过观察搜索模式,MySQL会利用index key的前缀建立哈希索引,如果一个表几乎大部分都在缓冲池中,那么建立一个哈希索引能够加快等值查询。
    B+树索引和哈希索引的明显区别是:

    3.如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;

    4.如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;
    同理,哈希索引没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);

    5.哈希索引也不支持多列联合索引的最左匹配规则;

    6.B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。

    7.在大多数场景下,都会有范围查询、排序、分组等查询特征,用B+树索引就可以了。

    7.B树和B+树的区别

    1. B树,每个节点都存储key和data,所有节点组成这棵树,并且叶子节点指针为nul,叶子结点不包含任何关键字信息

    2. B+树,所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接,所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字。(而B 树的非终节点也包含需要查找的有效信息)

    8.为什么说B+比B树更适合实际应用中操作系统的文件索引和数据库索引?

    1.B+的磁盘读写代价更低

    B+的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。

    2.B+tree的查询效率更加稳定

    由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

    9.聚集索引和非聚集索引区别?

    聚合索引(clustered index):

    聚集索引表记录的排列顺序和索引的排列顺序一致,所以查询效率快,只要找到第一个索引值记录,其余就连续性的记录在物理也一样连续存放。聚集索引对应的缺点就是修改慢,因为为了保证表中记录的物理和索引顺序一致,在记录插入的时候,会对数据页重新排序。
    聚集索引类似于新华字典中用拼音去查找汉字,拼音检索表于书记顺序都是按照a~z排列的,就像相同的逻辑顺序于物理顺序一样,当你需要查找a,ai两个读音的字,或是想一次寻找多个傻(sha)的同音字时,也许向后翻几页,或紧接着下一行就得到结果了。

    非聚合索引(nonclustered index):

    非聚集索引指定了表中记录的逻辑顺序,但是记录的物理和索引不一定一致,两种索引都采用B+树结构,非聚集索引的叶子层并不和实际数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针方式。非聚集索引层次多,不会造成数据重排。
    非聚集索引类似在新华字典上通过偏旁部首来查询汉字,检索表也许是按照横、竖、撇来排列的,但是由于正文中是a~z的拼音顺序,所以就类似于逻辑地址于物理地址的不对应。同时适用的情况就在于分组,大数目的不同值,频繁更新的列中,这些情况即不适合聚集索引。

    根本区别:

    聚集索引和非聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致。

    三、事务


     

    1.什么是事务?

    事务是对数据库中一系列操作进行统一的回滚或者提交的操作,主要用来保证数据的完整性和一致性。

    2.事务四大特性(ACID)原子性、一致性、隔离性、持久性?

    原子性(Atomicity):
    原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

    一致性(Consistency):
    事务开始前和结束后,数据库的完整性约束没有被破坏。比如A向B转账,不可能A扣了钱,B却没收到。

    隔离性(Isolation):
    隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

    持久性(Durability):
    持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

    3.事务的并发?事务隔离级别,每个级别会引发什么问题,MySQL默认是哪个级别?

    从理论上来说, 事务应该彼此完全隔离, 以避免并发事务所导致的问题,然而, 那样会对性能产生极大的影响, 因为事务必须按顺序运行, 在实际开发中, 为了提升性能, 事务会以较低的隔离级别运行, 事务的隔离级别可以通过隔离事务属性指定。
    事务的并发问题

    1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

    2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果因此本事务先后两次读到的数据结果会不一致。

    3、幻读:幻读解决了不重复读,保证了同一个事务里,查询的结果都是事务开始时的状态(一致性)。

    例如:事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作 这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有跟没有修改一样,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
    小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。

    事务的隔离级别

    读未提交:另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据脏读

    不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果因此本事务先后两次读到的数据结果会不一致。

    可重复读:在同一个事务里,SELECT的结果是事务开始时时间点的状态,因此,同样的SELECT操作读到的结果会是一致的。但是,会有幻读现象

    串行化:最高的隔离级别,在这个隔离级别下,不会产生任何异常。并发的事务,就像事务是在一个个按照顺序执行一样

    特别注意:

    MySQL默认的事务隔离级别为repeatable-read

    MySQL 支持 4 中事务隔离级别.

    事务的隔离级别要得到底层数据库引擎的支持, 而不是应用程序或者框架的支持.

    Oracle 支持的 2 种事务隔离级别:READ_COMMITED , SERIALIZABLE

    SQL规范所规定的标准,不同的数据库具体的实现可能会有些差异

    MySQL中默认事务隔离级别是“可重复读”时并不会锁住读取到的行

    事务隔离级别:未提交读时,写数据只会锁住相应的行。

    事务隔离级别为:可重复读时,写数据会锁住整张表。

    事务隔离级别为:串行化时,读写数据都会锁住整张表。

    隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,鱼和熊掌不可兼得啊。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

    4.事务传播行为

    1.PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。

    2.PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。

    3.PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

    4.PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。

    5.PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

    6.PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

    7.PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

    5.嵌套事务

    什么是嵌套事务?

    嵌套是子事务套在父事务中执行,子事务是父事务的一部分,在进入子事务之前,父事务建立一个回滚点,叫save point,然后执行子事务,这个子事务的执行也算是父事务的一部分,然后子事务执行结束,父事务继续执行。重点就在于那个save point。看几个问题就明了了:

    如果子事务回滚,会发生什么?

    父事务会回滚到进入子事务前建立的save point,然后尝试其他的事务或者其他的业务逻辑,父事务之前的操作不会受到影响,更不会自动回滚。

    如果父事务回滚,会发生什么?

    父事务回滚,子事务也会跟着回滚!为什么呢,因为父事务结束之前,子事务是不会提交的,我们说子事务是父事务的一部分,正是这个道理。那么:

    事务的提交,是什么情况?

    是父事务先提交,然后子事务提交,还是子事务先提交,父事务再提交?答案是第二种情况,还是那句话,子事务是父事务的一部分,由父事务统一提交。

    参考文章:https://blog.csdn.net/liangxw1/article/details/51197560

    四、存储引擎

    1.MySQL常见的三种存储引擎(InnoDB、MyISAM、MEMORY)的区别?

    两种存储引擎的大致区别表现在:

    1.InnoDB支持事务,MyISAM不支持, 这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而MyISAM就不可以了。

    2.MyISAM适合查询以及插入为主的应用。

    3.InnoDB适合频繁修改以及涉及到安全性较高的应用。

    4.InnoDB支持外键,MyISAM不支持。

    5.从MySQL5.5.5以后,InnoDB是默认引擎。

    6.InnoDB不支持FULLTEXT类型的索引。

    7.InnoDB中不保存表的行数,如select count() from table时,InnoDB需要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含where条件时MyISAM也需要扫描整个表。

    8.对于自增长的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段一起建立联合索引。

    9.DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的 删除,效率非常慢。MyISAM则会重建表。

    10.InnoDB支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like '%lee%'。

    2.MySQL存储引擎MyISAM与InnoDB如何选择

    MySQL有多种存储引擎,每种存储引擎有各自的优缺点,可以择优选择使用:MyISAM、InnoDB、MERGE、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE、FEDERATED、ARCHIVE、CSV、BLACKHOLE。

    虽然MySQL里的存储引擎不只是MyISAM与InnoDB这两个,但常用的就是两个。
    关于MySQL数据库提供的两种存储引擎,MyISAM与InnoDB选择使用:

    • 1.INNODB会支持一些关系数据库的高级功能,如事务功能和行级锁,MyISAM不支持。

    • 2.MyISAM的性能更优,占用的存储空间少,所以,选择何种存储引擎,视具体应用而定。

    如果你的应用程序一定要使用事务,毫无疑问你要选择INNODB引擎。但要注意,INNODB的行级锁是有条件的。在where条件没有使用主键时,照样会锁全表。比如DELETE FROM mytable这样的删除语句。

    如果你的应用程序对查询性能要求较高,就要使用MyISAM了。MyISAM索引和数据是分开的,而且其索引是压缩的,可以更好地利用内存。所以它的查询性能明显优于INNODB。压缩后的索引也能节约一些磁盘空间。MyISAM拥有全文索引的功能,这可以极大地优化LIKE查询的效率。

    有人说MyISAM只能用于小型应用,其实这只是一种偏见。如果数据量比较大,这是需要通过升级架构来解决,比如分表分库,而不是单纯地依赖存储引擎。

    现在一般都是选用innodb了,主要是MyISAM的全表锁,读写串行问题,并发效率锁表,效率低,MyISAM对于读写密集型应用一般是不会去选用的。
    MEMORY存储引擎

    MEMORY是MySQL中一类特殊的存储引擎。它使用存储在内存中的内容来创建表,而且数据全部放在内存中。这些特性与前面的两个很不同。
    每个基于MEMORY存储引擎的表实际对应一个磁盘文件。该文件的文件名与表名相同,类型为frm类型。该文件中只存储表的结构。而其数据文件,都是存储在内存中,这样有利于数据的快速处理,提高整个表的效率。值得注意的是,服务器需要有足够的内存来维持MEMORY存储引擎的表的使用。如果不需要了,可以释放内存,甚至删除不需要的表。

    MEMORY默认使用哈希索引。速度比使用B型树索引快。当然如果你想用B型树索引,可以在创建索引时指定。

    注意,MEMORY用到的很少,因为它是把数据存到内存中,如果内存出现异常就会影响数据。如果重启或者关机,所有数据都会消失。因此,基于MEMORY的表的生命周期很短,一般是一次性的。

    3.MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别,各自的适用场景?

    事务处理上方面

    • MyISAM:强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持。

    • InnoDB:提供事务支持事务,外部键等高级数据库功能。具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。

    锁级别

    • MyISAM:只支持表级锁,用户在操作MyISAM表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。

    • InnoDB:支持事务和行级锁,是innodb的最大特色。行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。

    关于存储引擎MyISAM和InnoDB的其他参考资料如下:

    MySQL存储引擎中的MyISAM和InnoDB区别详解

    MySQL存储引擎之MyISAM和Innodb总结性梳理

    五、优化


     

    1.查询语句不同元素(where、jion、limit、group by、having等等)执行先后顺序?

    • 1.查询中用到的关键词主要包含六个,并且他们的顺序依次为 select--from--where--group by--having--order by

    其中select和from是必须的,其他关键词是可选的,这六个关键词的执行顺序 与sql语句的书写顺序并不是一样的,而是按照下面的顺序来执行

    from:需要从哪个数据表检索数据

    where:过滤表中数据的条件

    group by:如何将上面过滤出的数据分组

    having:对上面已经分组的数据进行过滤的条件

    select:查看结果集中的哪个列,或列的计算结果

    order by :按照什么样的顺序来查看返回的数据

    • 2.from后面的表关联,是自右向左解析 而where条件的解析顺序是自下而上的。

    也就是说,在写SQL语句的时候,尽量把数据量小的表放在最右边来进行关联(用小表去匹配大表),而把能筛选出小量数据的条件放在where语句的最左边 (用小表去匹配大表)

    其他参考资源:
    http://www.cnblogs.com/huminxxl/p/3149097.html

    2.使用explain优化sql和索引?

    对于复杂、效率低的sql语句,我们通常是使用explain sql 来分析sql语句,这个语句可以打印出,语句的执行。这样方便我们分析,进行优化

    table:显示这一行的数据是关于哪张表的

    type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、index和ALL

    all:full table scan ;MySQL将遍历全表以找到匹配的行;

    index: index scan; index 和 all的区别在于index类型只遍历索引;

    range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值的行,常见与between ,等查询;

    ref:非唯一性索引扫描,返回匹配某个单独值的所有行,常见于使用非唯一索引即唯一索引的非唯一前缀进行查找;

    eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配,常用于主键或者唯一索引扫描;

    const,system:当MySQL对某查询某部分进行优化,并转为一个常量时,使用这些访问类型。如果将主键置于where列表中,MySQL就能将该查询转化为一个常量。

    possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句

    key: 实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MySQL会选择优化不足的索引。这种情况下,可以在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MySQL忽略索引

    key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好

    ref:显示索引的哪一列被使用了,如果可能的话,是一个常数

    rows:MySQL认为必须检查的用来返回请求数据的行数

    Extra:关于MySQL如何解析查询的额外信息。将在表4.3中讨论,但这里可以看到的坏的例子是Using temporary和Using filesort,意思MySQL根本不能使用索引,结果是检索会很慢。

    3.MySQL慢查询怎么解决?

    • slow_query_log 慢查询开启状态。

    • slow_query_log_file 慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录)。

    • long_query_time 查询超过多少秒才记录。

    六、数据库锁


     

    1.mysql都有什么锁,死锁判定原理和具体场景,死锁怎么解决?

    MySQL有三种锁的级别:页级、表级、行级。

    • 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

    • 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

    • 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
      什么情况下会造成死锁?

    什么是死锁?

    死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等竺的进程称为死锁进程。

    表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB。

    死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。

    那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。

    死锁的解决办法?

    1.查出的线程杀死 kill
    SELECT trx_MySQL_thread_id FROM information_schema.INNODB_TRX;

    2.设置锁的超时时间
    Innodb 行锁的等待时间,单位秒。可在会话级别设置,RDS 实例该参数的默认值为 50(秒)。

    生产环境不推荐使用过大的 innodb_lock_wait_timeout参数值
    该参数支持在会话级别修改,方便应用在会话级别单独设置某些特殊操作的行锁等待超时时间,如下:
    set innodb_lock_wait_timeout=1000; —设置当前会话 Innodb 行锁等待超时时间,单位秒。

    3.指定获取锁的顺序

    2.有哪些锁(乐观锁悲观锁),select 时怎么加排它锁?

    悲观锁(Pessimistic Lock):

    悲观锁特点:先获取锁,再进行业务操作。

    即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。通常所说的“一锁二查三更新”即指的是使用悲观锁。通常来讲在数据库上的悲观锁需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。当数据库执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。

    补充:
    不同的数据库对select for update的实现和支持都是有所区别的,

    • oracle支持select for update no wait,表示如果拿不到锁立刻报错,而不是等待,MySQL就没有no wait这个选项。

    • MySQL还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。因此如果在MySQL中用悲观锁务必要确定走了索引,而不是全表扫描。

    乐观锁(Optimistic Lock):

    1.乐观锁,也叫乐观并发控制,它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,那么当前正在提交的事务会进行回滚。

    2.**乐观锁的特点先进行业务操作,不到万不得已不去拿锁。**即“乐观”的认为拿锁多半是会成功的,因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。
    乐观锁在数据库上的实现完全是逻辑的,不需要数据库提供特殊的支持。

    3.一般的做法是在需要锁的数据上增加一个版本号,或者时间戳

    实现方式举例如下:

    乐观锁(给表加一个版本号字段) 这个并不是乐观锁的定义,给表加版本号,是数据库实现乐观锁的一种方式

    1. SELECT data AS old_data, version AS old_version FROM …;

    2. 根据获取的数据进行业务操作,得到new_data和new_version

    3. UPDATE SET data = new_data, version = new_version WHERE version = old_version

    if (updated row > 0) {

    // 乐观锁获取成功,操作完成

    } else {

    // 乐观锁获取失败,回滚并重试

    }

    注意:

    • 乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大,因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能

    • 乐观锁还适用于一些比较特殊的场景,例如在业务操作过程中无法和数据库保持连接等悲观锁无法适用的地方。

    总结:
    悲观锁和乐观锁是数据库用来保证数据并发安全防止更新丢失的两种方法,例子在select ... for update前加个事务就可以防止更新丢失。悲观锁和乐观锁大部分场景下差异不大,一些独特场景下有一些差别,一般我们可以从如下几个方面来判断。

    • 响应速度: 如果需要非常高的响应速度,建议采用乐观锁方案,成功就执行,不成功就失败,不需要等待其他并发去释放锁。'

    • 冲突频率: 如果冲突频率非常高,建议采用悲观锁,保证成功率,如果冲突频率大,乐观锁会需要多次重试才能成功,代价比较大。

    • 重试代价: 如果重试代价大,建议采用悲观锁。

    七、其他


     

    1.数据库的主从复制

    主从复制的几种方式:

    同步复制:

    所谓的同步复制,意思是master的变化,必须等待slave-1,slave-2,...,slave-n完成后才能返回。这样,显然不可取,也不是MySQL复制的默认设置。比如,在WEB前端页面上,用户增加了条记录,需要等待很长时间。

    异步复制:

    如同AJAX请求一样。master只需要完成自己的数据库操作即可。至于slaves是否收到二进制日志,是否完成操作,不用关心,MySQL的默认设置。

    半同步复制:

    master只保证slaves中的一个操作成功,就返回,其他slave不管。这个功能,是由google为MySQL引入的。

    2.数据库主从复制分析的 7 个问题?

    问题1:master的写操作,slaves被动的进行一样的操作,保持数据一致性,那么slave是否可以主动的进行写操作?

    假设slave可以主动的进行写操作,slave又无法通知master,这样就导致了master和slave数据不一致了。因此slave不应该进行写操作,至少是slave上涉及到复制的数据库不可以写。实际上,这里已经揭示了读写分离的概念。

    问题2:主从复制中,可以有N个slave,可是这些slave又不能进行写操作,要他们干嘛?

    实现数据备份:
    类似于高可用的功能,一旦master挂了,可以让slave顶上去,同时slave提升为master。

    异地容灾:比如master在北京,地震挂了,那么在上海的slave还可以继续。
    主要用于实现scale out,分担负载,可以将读的任务分散到slaves上。
    【很可能的情况是,一个系统的读操作远远多于写操作,因此写操作发向master,读操作发向slaves进行操作】

    问题3:主从复制中有master,slave1,slave2,...等等这么多MySQL数据库,那比如一个JAVA WEB应用到底应该连接哪个数据库?

    我们在应用程序中可以这样,insert/delete/update这些更新数据库的操作,用connection(for master)进行操作,

    select用connection(for slaves)进行操作。那我们的应用程序还要完成怎么从slaves选择一个来执行select,例如使用简单的轮循算法。

    这样的话,相当于应用程序完成了SQL语句的路由,而且与MySQL的主从复制架构非常关联,一旦master挂了,某些slave挂了,那么应用程序就要修改了。能不能让应用程序与MySQL的主从复制架构没有什么太多关系呢?
    找一个组件,application program只需要与它打交道,用它来完成MySQL的代理,实现SQL语句的路由。
    MySQL proxy并不负责,怎么从众多的slaves挑一个?可以交给另一个组件(比如haproxy)来完成。

    这就是所谓的MySQL READ WRITE SPLITE,MySQL的读写分离。

    问题4:如果MySQL proxy , direct , master他们中的某些挂了怎么办?

    总统一般都会弄个副总统,以防不测。同样的,可以给这些关键的节点来个备份。

    问题5:当master的二进制日志每产生一个事件,都需要发往slave,如果我们有N个slave,那是发N次,还是只发一次?如果只发一次,发给了slave-1,那slave-2,slave-3,...它们怎么办?

    显 然,应该发N次。实际上,在MySQL master内部,维护N个线程,每一个线程负责将二进制日志文件发往对应的slave。master既要负责写操作,还的维护N个线程,负担会很重。可以这样,slave-1是master的从,slave-1又是slave-2,slave-3,...的主,同时slave-1不再负责select。slave-1将master的复制线程的负担,转移到自己的身上。这就是所谓的多级复制的概念。

    问题6:当一个select发往MySQL proxy,可能这次由slave-2响应,下次由slave-3响应,这样的话,就无法利用查询缓存了。

    应该找一个共享式的缓存,比如memcache来解决。将slave-2,slave-3,...这些查询的结果都缓存至mamcache中。

    问题7:随着应用的日益增长,读操作很多,我们可以扩展slave,但是如果master满足不了写操作了,怎么办呢?

    scale on ?更好的服务器?没有最好的,只有更好的,太贵了。。。
    scale out ? 主从复制架构已经满足不了。
    可以分库【垂直拆分】,分表【水平拆分】。

    3.mysql 高并发环境解决方案?

    MySQL 高并发环境解决方案: 分库 分表 分布式 增加二级缓存。。。。。

    需求分析:互联网单位 每天大量数据读取,写入,并发性高。

    现有解决方式:水平分库分表,由单点分布到多点数据库中,从而降低单点数据库压力。

    集群方案:解决DB宕机带来的单点DB不能访问问题。

    读写分离策略:极大限度提高了应用中Read数据的速度和并发量。无法解决高写入压力。

    4.数据库崩溃时事务的恢复机制(REDO日志和UNDO日志)?

    转载:MySQL REDO日志和UNDO日志

    Undo Log:

    Undo Log是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用了Undo Log来实现多版本并发控制(简称:MVCC)。

    事务的原子性(Atomicity)事务中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作。如果在执行的过程中发生了错误,要回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过。
    原理Undo Log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为UndoLog)。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。

    之所以能同时保证原子性和持久化,是因为以下特点:

    更新数据前记录Undo log。
    为了保证持久性,必须将数据在事务提交前写到磁盘。只要事务成功提交,数据必然已经持久化。
    Undo log必须先于数据持久化到磁盘。如果在G,H之间系统崩溃,undo log是完整的, 可以用来回滚事务。
    如果在A-F之间系统崩溃,因为数据没有持久化到磁盘。所以磁盘上的数据还是保持在事务开始前的状态。

    缺陷:每个事务提交前将数据和Undo Log写入磁盘,这样会导致大量的磁盘IO,因此性能很低。
    如果能够将数据缓存一段时间,就能减少IO提高性能。但是这样就会丧失事务的持久性。因此引入了另外一种机制来实现持久化,即Redo Log。

    Redo Log:

    原理和Undo Log相反,Redo Log记录的是新数据的备份。在事务提交前,只要将Redo Log持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是Redo Log已经持久化。系统可以根据Redo Log的内容,将所有数据恢复到最新的状态。

    八、整理时参考的资料


    java团长数据库整理

    20个数据库常见面试题讲解 - 鹏磊 - 开源中国"

    34个数据库常见面试题讲解

    漫谈数据库索引知识库博客园

    Mysql| 使用通配符进行模糊查询(like,%,_)

    MySQL存储引擎中的MyISAM和InnoDB区别详解

    MySQL存储引擎之MyISAM和Innodb总结性梳理

    https://blog.csdn.net/liangxw1/article/details/51197560

    展开全文
  • 代码覆盖

    千次阅读 2018-02-11 13:06:47
    用途:测试覆盖率评价的是测试代码的质量,并不是产品代码的质量代码覆盖率是一种白盒测试,因为测试覆盖率是评价产品代码类内部的指标,而不是评价系统接口或规约。测试覆盖率尤其用于评价测试代码是否已经覆盖了...

    用途

    测试覆盖率评价的是测试代码的质量,并不是产品代码的质量

    代码覆盖率是一种白盒测试,因为测试覆盖率是评价产品代码类内部的指标,而不是评价系统接口或规约。测试覆盖率尤其用于评价测试代码是否已经覆盖了产品代码所有的路径。

    分类

    类的覆盖率:类覆盖描熟了项目中多少类已被测试套件访问。  
    方法覆盖率:方法覆盖率是被访问的方法的百分比。 
    语句覆盖率:语句覆盖率追踪单条源代码语句的调用。 
    语句块覆盖率:语句快覆盖率将语句块作为基本的覆盖律单元。 
    分支覆盖率:分支覆盖率也被称为判断覆盖率。指标计算哪些代码分支被执行。

    代码的覆盖深度:从覆盖源程序语句的详尽程度分析,逻辑覆盖标准包括以下不同的覆盖
    标准:语句覆盖、判定覆盖、条件覆盖、条件判定组合覆盖、多条件覆盖和修正判定条件覆
    盖。 参考:
    http://bbs.51testing.com/thread-74208-1-1.html

    ·语句覆盖为了暴露程序中的错误,程序中的每条语句至少应该执行一次。因此语句覆
    盖(Statement Coverage)的含义是:选择足够多的测试数据,使被测程序中每条语句至少执
    行一次。语句覆盖是很弱的逻辑覆盖。

    ·判定覆盖 比语句覆盖稍强的覆盖标准是判定覆盖(Decision Coverage)。判定覆盖的
    含义是:设计足够的测试用例,使得程序中的每个判定至少都获得一次真值假值
    或者说使得程序中的每一个取分支和取分支至少经历一次,因此判定覆盖又称为
    分支覆盖。
    ·条件覆盖在设计程序中,一个判定语句是由多个条件组合而成的复合判定。为了更彻
    底地实现逻辑覆盖,可以采用条件覆盖(Condition Coverage)的标准。条件覆盖的含义是:
    构造一组测试用例,使得每一判定语句中每个逻辑条件的可能值至少满足一次。
    ·多条件覆盖多条件覆盖也称条件组合覆盖,它的含义是:设计足够的测试用例,使得
    每个判定中条件的各种可能组合都至少出现一次。显然满足多条件覆盖的测试用例是一定满足
    判定覆盖、条件覆盖和条件判定组合覆盖的。
    ·修正条件判定覆盖修正条件判定覆盖是由欧美的航空/航天制造厂商和使用单位联合制
    定的航空运输和装备系统软件认证标准,目前在国外的国防、航空航天领域应用广泛。这
    个覆盖度量需要足够的测试用例来确定各个条件能够影响到包含的判定的结果。它要求满足两
    个条件:首先,每一个程序模块的入口和出口点都要考虑至少要被调用一次,每个程序的判定
    到所有可能的结果值要至少转换一次;其次,程序的判定被分解为通过逻辑操作符(andor)连接的布尔条件,每个条件对于判定的结果值是独立的。

    覆盖率工具 

    Clover(商用)、EMMACobertura  JaCoCo

    特点/工具

    Cobertura

    Emma

    jacoco

    http://rensanning.iteye.com/blog/2002371
    http://blog.csdn.net/smile0102/article/details/48688763

    集成

    一个与Junit集成的代码覆盖率测量工具

    可以与AntMaven集成,也可以通过命令行调用

    可以统计几种覆盖率:classmethodblock, line。支持版本迭代的覆盖率统计

    免费且开源的Java代码覆盖率测试工具,100%Java编写,不依赖与任何第三方库

    Java Code Coverage)是开源的Java代码覆盖率测试library
    可以集成到ANTMavenbuild工具中。它采用标准的JVM Tool Interface。把JaCoCo agent 加入到JVM后启动,加载到JVM中的class具体被执行了哪些代码行将会被记录下来,JaCoCo搜集这些执行信息直到JVM结束后生成静态报告。

    开源

    免费、开源的

    免费、开源的

    免费、开源的

    报告形式

    可以生成HTMLXML格式的报告

    可以按照不同的标准对HTML结果进行排序

    提供了多种格式的报告,包括纯文本,HTMLXML,所有的报告都可以进行详细设置以获得定制报告

     

    覆盖率统计

    为每个类、包以及整个项目计算所覆盖的代码行与代码分支的百分比例

    支持对类,方法,代码行和基本的分支语句的覆盖率测试

    使用EMMA时,不需要获得源代码就可进行覆盖率测试,此外,EMMA还支持对整个jar文件测试。

     

     

     

     

     

     

     

     

     

    注释:

    Java测试覆盖率工具上,还有一个更加简单的工具:EclEmma(推荐,EclEmma是一个基于EMMAJava代码覆盖工具) ,它可以很方便的与Eclipse集成,然后可以直接run,显示出代码覆盖率,其地址是:http://www.eclemma.org/

     

    错误认识

    为覆盖率而设计是错误得的,有一点:有覆盖率统计,好过没有 

    功能测试代码覆盖率统计工具-EMMA

    原理:

    原理:
    http://qa.blog.163.com/blog/static/190147002201111151057365/
    http://www.tuicool.com/articles/3YJRfuU

    局限: 

     仅仅支持JDK7,如果JDK8,需要选择如jacoco等工具。
    脚本的编写:
    http://tianya23.blog.51cto.com/1081650/364094

    EMMA 所使用的字节码插装不仅保证 EMMA 不会给源代码带来脏代码,还确保 EMMA 摆脱了源代码的束缚,这一特点使 EMMA 应用于功能测试成为了可能。

    大多数功能测试中,测试人员一般不能直接得到被测源代码,源代码也不是测试人员关心的重点。在具体的测试过程中,功能测试人员一般以一个有意义的功能模块作为测试关心的重点,而能够反映一定功能含义的类和方法的覆盖率在功能测试中更有价值。因此,在功能测试中,类覆盖率和方法覆盖率是测试人员关心的重点,行和块覆盖率则作为测试的参考。

    测试覆盖率报告中包含了两个方面的内容,测试覆盖的部分和未被测试覆盖的部分。尽管百分之百的测试覆盖率不能代表被测对象完全没有问题,但是测试覆盖的部分以及覆盖比率可以增加测试者对测试工作的信心,指导测试执行以及测试的方向。另一方面,当测试用例执行出现异常时,针对每个测试用例的测试报告还可以提供可疑代码的范围,为代码纠错提供帮助。

    测试覆盖率报告中未覆盖的部分也同样有价值:

    · 表明测试可能不完整,有些功能、代码没有被测试覆盖到。

    · 为测试用例的设计提供指导建议。在覆盖率报告的指导下,测试人员有目的地与开发人员进行讨论,确定未覆盖部分是测试的空白还是不需要测试的部分。

    · 帮助开发人员发现无用代码,为修改,完善代码提供依据。

    在使用 EMMA 获得测试覆盖率过程中,类、方法等覆盖的百分比报告,可以方便测试人员更好的评估测试。测试人员通过对照覆盖率报告与测试用例设计文档,需求文档可以迅速找到测试的不足。通过与开发人员进行讨论,可以更好的评估测试力度,并指导进一步的测试。因此在功能测试中引入覆盖率信息,能够完善测试结果报告,确保测试质量和力度,保证测试按质、按量地完成。

     

    EMMA 使用

    EMMA基本是四步曲:插桩(instr),运行,收集(ctl),报告(report

    版本0http://www.ibm.com/developerworks/cn/opensource/os-cn-emma/

    插装被测组件

    EMMA 通过对被测组件进行插装来跟踪被测组件的执行过程。测试人员应首先和开发人员讨论,确定哪一部分包含了符合插装要求的文件( Java 文件),哪一部分需要考虑覆盖率信息,然后选择合适的方式进行插装。

    · 插装准备

    在执行插装操作之前,首先应该扩展 Java 虚拟机,即将 emma.jar 放到被测组件运行使用的JRE 目录下面作为 JRE 的扩展,以便 EMMA 能够被调用。 emma.jar 包含了 EMMA 核心功能模块的实现和 EMMA 运行时所需的类文件,这些文件是使用 EMMA 所必需的。

    由于示例被测组件运行在 Websphere Portal Server 中,并使用默认的 JRE 运行,因此将emma.jar 放到 “/opt/WebSphere/PortalServer/java/jre/lib/ext” 下面。在实际的测试中,将该路径进行相应的替换。

    · 插装

    EMMA 中提供了 “instr” 命令完成插装操作。插装操作可以面向 JAR 包、 WAR 包、 WAR 包、类文件和目录,选择合适的命令进行插装可以使插装过程变得简便。

    清单 1. 对类文件插装命令

    /opt/WebSphere/PortalServer/java/jre/bin/java emma instr -m overwrite -ip

    /opt/WebSphere/PortalServer/installedApps/NumberQuizWEB_10yggsru.ear/NumberQuizWEB.war/WEB

    -INF/classes -Dmetadata.out.file=/root/emma/Number_coverage.em

    · 合并元数据

    完成插装操作以后,在指定的路径下会产生一些名为 “*coverage.em” 的文件,这些文件保存了插装的元信息,这些信息主要是记录插装过程中的插装点在被测代码中的位置。如果在插装过程中,指定这些文件到同一文件的话, EMMA 默认将元数据进行合并。如果测试人员未指定路径,或者希望得到独立的元文件,这些文件将分别产生在默认或指定的目录下。测试人员还可以通过使用 “merge” 命令手动将这些元文件进行合并,保证生成的覆盖率报表的全面性。注意:合并操作不支持逆向操作。

    清单 5. 合并元数据命令

    /opt/WebSphere/PortalServer/java/jre/bin/java emma merge

    -input <path1>/coverage1.em,<path2>/coverage.em -out <path>/coverage2.em

     

    完成上面的操作以后,就已经完成了收集覆盖率信息的准备工作。接下来测试人员可以进行正常的测试工作,在运行测试的过程中, EMMA 将跟踪并记录执行轨迹,得到覆盖率信息。

    运行测试用例,得到覆盖率报告

    完成插装工作以后,测试人员可以按照测试计划运行测试用例。 EMMA 将在测试执行的过程中记录代码执行信息并将结果记录在内存中。每次当 JVM 停止时,内存中记录的执行信息将被清除并被保存到 “*.ec” 的文件中。但是在实际测试的过程中, JVM 的停止很难控制,因此测试人员可以定时手动将内存中执行信息写出。在这种情况下,内存中的记录被输出,但是内存中的内容不被清除。

    从本地收集覆盖率信息

    /opt/WebSphere/PortalServer/java/jre/bin/java -cp emma.jar emma ctl -connect

    auscsdpfvtvm15.bto.ibm.com:47653 -command coverage.get,/root/emma/Number_coverage.ec

     

    EMMA: processing control command sequence

    EMMA: executing [coverage.get (/root/emma/Number_coverage.ec,true,true)]

    EMMA: coverage.get: local copy of coverage data merged into

              [/root/emma/Number_coverage.ec] {in 39 ms}

    EMMA: coverage.get: command completed in 79 ms

    EMMA: control command sequence complete

    这样收集到的信息被保存在 “coverage.ec” 中, “coverage.ec” 是二进制格式的文件,因此很难被用来查看覆盖率结果。

    生成覆盖率报告

    /opt/WebSphere/PortalServer/java/jre/bin/java -cp emma.jar emma report -r html -in

     /root/emma/Number_coverage.em,/root/emma/Number_coverage.ec -

    Dreport.html.out.file=/root/emma/Number_coverage.html -Dreport.metrics=class:80

    (,method:75)

    在生成覆盖率报告的过程中,测试人员可以根据测试要求通过 “Dreport.metrics” 参数设定满意的覆盖率标准。在示例命令中设定了类覆盖率的满意度为80%

    测试报告可以以 HTML ,文本和 XML 三种格式输出。

    合并覆盖率结果

    完成所用的测试用例后,测试覆盖信息可以被合并在一起,得到整个测试的覆盖报告。覆盖率结果文件通过 “merge” 命令合并 “*.ec” 文件实现的。

    另外,由于 EMMA 中测试覆盖率是通过与 “*.em” 文件关联获得代码信息的,因此当代码发生变化时,已经运行过的测试不必完全重复,只需将得到的 “*.ec” 文件合并(新得到的 “*.ec” 文件放在后面),然后关联最新的 “*.em” 文件即可得到代码变化后的覆盖率信息,这方便了 EMMA 支持版本变化的测试。在生成新的测试报告的时候,需要注意 “*.ec” 的时间一定要晚于 “*.em” 文件。

    清单 9. 合并覆盖率结果命令

    /opt/WebSphere/PortalServer/java/jre/bin/java emma merge

    –input coverage1.ec,coverage2.ec,coverage3.ec –output coverage.ec

    如果在生成测试报告的时候,如果出现 “com.vladium.emma.EMMARuntimeException: [CLASS_STAMP_MISMATCH] runtime version of class in the coverage data is not consistent with the version of this class in the metadata, possibly because stale metadata is being used for report generation” 错误,说明在生成新的 “*.em” 前后代码曾经被修改过,并且被修改的代码所在的类文件在新的测试中没有被覆盖到,这就需要重新执行这部分测试,保证修改过的部分被重新执行。

     

    展开全文
  • Testing coverage(测试覆盖),测试系统覆盖被测试系统的程度,一项给定测试或一组测试对某个给定系统或构件的所有指定测试用例进行处理所达到的程度。 逻辑覆盖方法有以下6种: 语句覆盖 判定覆盖(即...
  • 其中的覆盖项是作为测试基础的一入口或属性,比如语句、分支、条件等。 结构覆盖率包括语句覆盖率、分支覆盖率、循环覆盖率、路径覆盖率等。 测试覆盖中需要遵循的两条准则:ESTCA准则、LCSAJ准则。
  • LTE弱覆盖问题分析与优化

    千次阅读 2021-01-27 06:53:01
    《LTE弱覆盖问题分析与优化》由会员分享,可在线阅读,更多相关《LTE弱覆盖问题分析与优化(5页珍藏版)》请在装配图网上搜索。1、LTE弱覆盖问题分析与优化摘要本文结合现网实际工作情况介绍了LTE弱覆盖的发现手段,...
  • 关于覆盖率,网络上最常见的两词应该是“测试覆盖率”(Test Coverage)和”代码覆盖率“(Code Coverage)。今天就来探探这两东西。 在测试里面,一般会将测试覆盖率分为两部分,即”需求覆盖率“和”代码...
  • 白盒测试作为测试人员常用的一种测试方法,越来越受到测试工程师的重视。白盒测试并不是简单的按照代码设计用例...本文介绍六种白盒子测试方法:语句覆盖、判定覆盖、条件覆盖、判定条件覆盖、条件组合覆盖、路径覆盖
  • 因此,EMC包括两方面的要求:一方面是设备在正常运行过程中对所在环境产生的电磁干扰不能超过一定的限值;另一方面是器具对所在环境中存在的电磁干扰具有一定程度的抗扰度,即电磁敏感性。 电磁干扰源种类 ...
  • 白盒测试的六种覆盖方法

    千次阅读 2020-08-27 12:29:19
    白盒测试的六种覆盖方法白盒测试的概述白盒的测试用例需要做到白盒测试的实施步骤白盒测试的优缺点六种覆盖方法1、语句覆盖2、判定覆盖3、条件覆盖4、判定/条件覆盖5、组合覆盖6、路径覆盖总结 白盒测试作为测试人员...
  • ...   摘要: 白盒测试作为测试人员常用的一种...逻辑测试不是片面的测试正确的结果或是测试错误的结果,而是尽可能全面覆盖每一逻辑路径。   转载于:https://www.cnblogs.com/MR-Guo/p/3449385.html
  • 功能覆盖

    2021-04-02 09:23:09
    如果你的功能覆盖率很高但是代码覆盖率很低,这说明你列的测试点可能不够全面,有遗漏的功能没有加入到你的测试计划中,你的测试没有很好的执行设计的所有代码,这是应该回到设计规范上,更新验证计划,然后增加更过...
  • SV之覆盖

    万次阅读 多人点赞 2019-05-22 21:01:29
    Coverage 覆盖率 Functional Coverage 功能覆盖率 Cross Coverage 交叉覆盖 Coverage Options 覆盖率选项 Coverage methods 覆盖率方法 Coverage system task 覆盖率系统任务 Coverage 覆盖覆盖率用来衡量...
  • 怎么保证测试用例的覆盖

    千次阅读 2019-10-07 05:01:13
    但实际上我们不可能去做全覆盖。所以设计这类用例时,最好有一张草稿,将所有相关功能按业务流程逐一列示,然后再将每功能可能出现的特定数据一一标上,最后将图中最可能出现的、最可能出错的、最核心的数据取出来...
  • 1 什么是Massive MIMOMassive MIMO(大规模天线技术,亦称为Large Scale MIMO)是第代移动通信(5G)中提高系统容量和频谱利用率的关键技术。它最早由美国贝尔实验室研究人员提出,研究发现,当小区的基站天线数目...
  • C++语言的单元测试与代码覆盖

    千次阅读 2018-11-20 11:32:44
    测试是软件开发过程中一必须的环节,测试确保软件的质量符合预期。 对于工程师自己来说,单元测试也是一种提升自信心的方式。 直接交付没有经过测试的代码是不太好的,因为这很可能会浪费整个团队的时间,在一些...
  • 本文主要是介绍什么是代码覆盖度,引入代码覆盖度的好处,代码覆盖度的度量方法以及对应的测试用例设计方法 1. 什么是代码覆盖度代码覆盖率分析实际上一种度量方式,间接度量质量的方法的过程,是在保证测试质量的...
  • 浅谈:怎么提高测试用例覆盖

    千次阅读 2020-05-13 15:28:29
    看了很多文章,在测试过程中,我们如何可以使我们的用例更加完善呢,以前上学的时候就说几大的方面,设计测试用例的时候要从功能性,兼容性,易用性,可靠性,性能,安全方面去设计用例 但是在实际的测试过程中,...
  • 【测试用例】如何提高测试覆盖

    千次阅读 2018-06-14 10:54:53
     说到测试用例的设计,我想每有过测试经历的测试工程师都会认为很简单,不就是:按需求或概要设计,得到软件功能划分图,然后据此按每功能,采用等价类划分、临界值、因果图等方法来设计用例就行了。...
  • 逻辑测试不是片面的测试正确的结果或是测试错误的结果,而是尽可能全面覆盖每一逻辑路径。   转载二:http://www.cnblogs.com/yinluhui0229/articles/2051482.html   判定覆盖 与 条件覆盖 的区别 ...
  • SV -- Coverage 覆盖

    千次阅读 2020-04-29 13:18:49
    SV – Coverage 覆盖率 本文内容来自: http://www.asic-world.com/systemverilog/coverage.html https://verificationguide.com/systemverilog/systemverilog-array-manipulation-methods/ ...
  • Android全面屏适配指南

    千次阅读 2019-05-06 13:57:25
    何为全面全面屏是手机业界对于超高屏占比...现在业内所说的全面屏手机是真实屏占比可以达到80%以上,拥有超窄边框设计的手机。 全面屏手机屏幕的宽高比例比较特殊,不再是以前的16:9。比如三星的Galaxy S8屏幕...
  • 1.什么是动态频谱共享DSS? 2. 动态频谱共享DSS与静态射频共享的比较 3. 如何部署动态频谱共享? 4动态频谱共享的好处? 5.动态频谱共享的技术实现

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 55,659
精华内容 22,263
关键字:

五个全面覆盖指的是