移动应用软件测试技术与实践
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.6 软件缺陷

软件缺陷又被叫做“Bug”,即计算机软件中存在的某种破坏正常运行能力的问题、错误,或者隐藏的功能缺陷,它的存在会导致软件产品在某种程度上不能满足用户的需要。“IEEE 729-1983”对缺陷有一个标准的定义:“从产品内部看,缺陷是软件产品开发或维护过程中存在的错误、毛病等各种问题;从产品外部看,缺陷是系统所需要实现的某种功能的失效或违背。”在软件开发生命周期的后期,修复检测到的软件错误的成本较高。

缺陷的表现形式不仅体现在功能的失效方面,还体现在其他方面,主要类型一是软件没有实现产品规格说明书所要求的功能;二是软件中出现了产品规格说明书指明不应该出现的错误;三是软件实现了产品规格说明书没有提到的功能;四是软件没有实现虽然产品规格说明书没有明确提及但应该实现的目标;五是软件难以理解、不容易使用且运行缓慢,或从测试人员的角度看最终用户会认为不好。

【案例】计算器的开发。

计算器的“产品规格说明书”规定指出可以准确无误地执行加、减、乘、除运算,如果按下加法键没有反应或者计算结果出错,则是第1种类型的缺陷;产品规格说明书还可能规定计算器不会死机,或者停止反应。如果随意敲键盘导致计算器停止接收输入,则是第2种类型的缺陷;如果使用计算器测试发现除了加、减、乘、除之外还可以求平方根,但是产品规格说明书没有提及这一功能,则是第3种类型的缺陷——软件实现了产品规格说明书中未提及的功能;如果发现电池没电会导致计算不正确,而产品规格说明书是假定电池一直都有电,从而发现第4种类型的错误;如果软件测试人员发现某些地方不对,如按键太小、“=”键的布局位置不好、在亮光下看不清显示屏等,无论什么原因都要认定为缺陷,而这正是第5种类型的缺陷。

1.6.1 概述

1.缺陷属性

(1)缺陷标识(Identifier):标记某个缺陷的一组符号,每个缺陷必须有一个唯一的标识。

(2)缺陷类型(Type):根据缺陷的自然属性划分的缺陷种类。

(3)缺陷严重程度(Severity):因缺陷引起的故障对软件产品的影响程度。

(4)缺陷优先级(Priority):缺陷必须被修复的紧急程度。

(5)缺陷状态(Status):缺陷通过一个跟踪修复过程的进展情况。

(6)缺陷起源(Origin):缺陷引起的故障或事件第1次被检测到的阶段。

(7)缺陷来源(Source):引起缺陷的起因。

(8)缺陷根源(Root Cause):产生缺陷的根本因素。

2.缺陷类型

(1)F-Function:影响了重要的特性、用户界面、产品接口、硬件结构接口和全局数据结构。并且设计文档需要正式的变更,如逻辑、指针、循环、递归、功能等缺陷。

(2)A-Assignment:需要修改少量代码,如初始化或控制模块,包括声明、重复命名,范围、限定等缺陷。

(3)I-Interface:与其他组件、模块或设备驱动程序、调用参数、控制块或参数列表相互影响的缺陷。

(4)C-Checking:提示的错误信息,不适当的数据验证等缺陷。

(5)B-Build/package/merge:由于配置库、变化管理或版本控制引起的错误。

(6)D-Documentation:影响发布和维护,包括注释。

(7)G-Algorithm:算法错误。

(8)U-User Interface:屏幕格式、确认用户输入、功能有效性,以及页面排版等方面的缺陷。

(9)P-Performance:不满足系统可测量的属性要求,如执行时间、事务处理速率等。

(10)N-Norms:不符合各种标准的要求,如编码标准、设计符号等。

3.缺陷严重程度

(1)Critical:很严重的错误,不能执行正常工作功能或重要功能,或者危及人身安全。

(2)Major:不太严重地影响系统要求或基本功能的实现,并且没有办法更正(重新安装或重新启动该软件不属于更正办法)。

(3)Minor:小的会影响系统要求或基本功能的问题,且存在合理的更正办法(重新安装或重新启动该软件不属于更正办法)。

(4)Cosmetic:使用户不方便或遇到麻烦,但不影响实现正常功能或重要功能。

(5)Other:其他错误。

4.同行评审错误严重程度

(1)Major:主要且较大的缺陷。

(2)Minor:次要且小的缺陷。

5.缺陷优先级

(1)Resolve Immediately:缺陷必须被立即解决。

(2)Normal Queue:缺陷需要正常排队等待修复或列入软件发布清单。

(3)Not Urgent:缺陷可以在方便时被解决。

6.缺陷状态

(1)Submitted:已提交的缺陷。

(2)Open:确认“提交的缺陷”并等待处理。

(3)Rejected:拒绝“已提交的缺陷”,不需要修复或不是缺陷。

(4)Resolved:缺陷被修复。

(5)Closed:确认被修复的缺陷,将其关闭。

7.缺陷起源

(1)Requirement:在需求阶段发现的缺陷。

(2)Architecture:在构架阶段发现的缺陷。

(3)Design:在设计阶段发现的缺陷。

(4)Code:在编码阶段发现的缺陷。

(5)Test:在测试阶段发现的缺陷。

8.缺陷来源

(1)Requirement:由于需求问题引起的缺陷。

(2)Architecture:由于构架问题引起的缺陷。

(3)Design:由于设计问题引起的缺陷。

(4)Code:由于编码问题引起的缺陷。

(5)Test:由于测试问题引起的缺陷。

(6)Integration:由于集成问题引起的缺陷。

9.缺陷级别

一旦发现软件缺陷,就要设法找到产生这个缺陷的原因,并且分析对产品质量的影响,然后确定软件缺陷的严重性和处理这个缺陷的优先级。各种缺陷所造成的后果不同,有的仅仅是不方便,有的可能是灾难性的。一般问题越严重,其处理优先级就越高,可以概括为以下4种级别。

(1)微小的(Minor):一些小问题,如有个别错别字、文字排版不整齐等。对功能几乎没有影响,软件产品仍可使用。

(2)一般的(Major):不太严重的错误,如次要功能模块丧失、提示信息不够准确、用户界面差和操作时间长等。

(3)严重的(Critical):很严重的错误,指功能模块或特性没有实现,以及主要功能部分丧失,或次要功能全部丧失,或致命的错误声明。

(4)致命的(Fatal):致命的错误,造成系统崩溃、死机,或数据丢失、主要功能完全丧失等。

除了严重性之外,还存在反映软件缺陷处于一种什么样的状态,以便于及时跟踪和管理,下面是不同的缺陷状态。

(1)激活状态(Open):问题没有解决,测试人员新报告的缺陷或者验证后缺陷仍旧存在。

(2)已修正状态(Fixed):开发人员针对缺陷修正软件后已解决问题或通过单元测试。

(3)关闭状态(Close):测试人员经过验证后确认缺陷不存在之后的状态。

以上是3种基本的状态,还有一些需要相应的状态描述,如“保留”和“不一致”状态等。

1.6.2 产生原因

在软件开发的过程中,软件缺陷的产生是不可避免的。从软件本身、团队工作和技术问题等角度分析,可以了解造成软件缺陷的主要因素。

软件缺陷的产生主要是由软件产品的特点和开发过程决定的。

1.软件本身的原因

(1)需求不清晰,导致设计目标偏离客户的需求,从而引发功能或产品特征上的缺陷。

(2)系统结构非常复杂,而又无法设计成一个很好的层次结构或组件结构,从而导致意想不到的问题或系统维护及扩充上的困难。即使设计良好的面向对象的系统,由于对象、类太多,所以很难完成对各种对象、类相互作用的组合测试而导致隐藏一些参数传递、方法调用、对象状态变化等方面的问题。

(3)对程序逻辑路径或数据范围的边界考虑不够周全,漏掉某些边界条件造成容量或边界错误。

(4)对一些实时应用要进行精心设计和技术处理,保证精确的时间同步,否则容易引发时间上的不一致性带来的问题。

(5)没有考虑系统崩溃后的自我恢复或数据的异地备份、灾难性恢复等问题,从而存在系统安全性及可靠性的隐患。

(6)系统运行环境复杂。用户使用的计算机环境千变万化,包括用户的各种操作方式或各种不同的输入数据容易引发一些特定用户环境下的问题。在系统实际应用中数据量很大,从而会引发强度或负载问题。

(7)由于通信端口多、存取和加密手段的矛盾性等,所以会造成系统的安全性或适用性等问题。

(8)新技术的采用可能涉及技术或系统兼容的问题,事先没有考虑周全。

2.团队工作的原因

(1)系统需求分析时对客户的需求理解不清楚,或者和用户的沟通存在一些困难。

(2)不同阶段的开发人员相互理解不一致,如软件设计人员对需求分析的理解有偏差,以及编程人员对系统设计规格说明书中的某些内容重视不够或存在误解。

(3)对于设计或编程上的一些假定或依赖性,相关人员没有充分沟通。

(4)项目组成员技术水平参差不齐或新员工较多,或培训不够等原因也容易引发问题。

3.技术原因

(1)算法错误:在给定条件下未能给出正确或准确的结果。

(2)语法错误:编译性语言程序编译器可以发现这类问题,但是解释性语言程序只能在测试运行时发现。

(3)计算和精度问题:计算的结果没有满足所需要的精度。

(4)系统结构、算法问题:系统结构不合理、算法选择不科学,造成系统性能低下。

(5)接口参数问题:接口参数传递不匹配导致模块集成出现问题。

4.项目管理的原因

(1)缺乏质量文化,不重视质量计划,对质量、资源、任务、成本等的平衡性把握不好,从而容易挤掉需求分析、评审、测试等时间,导致遗留的缺陷会比较多。

(2)系统分析时对客户的需求不是十分清楚,或者和用户的沟通存在一些困难。

(3)开发周期短,需求分析、设计、编程、测试等各项工作不能完全按照定义的流程来进行。工作不够充分,结果也就不完整、不准确,错误较多。周期短还给各类开发人员造成太大的压力,引发一些人为的错误。

(4)开发流程不够完善,存在太多的随机性。缺乏严谨的内审或评审机制,容易产生问题。

(5)文档不完善,风险估计不足等。

1.6.3 软件缺陷的分类

从软件测试观点出发,软件缺陷有以下6大类(共25种)。

1.功能缺陷

(1)需求规格说明书缺陷:需求规格说明书可能不完全,有二义性或自身矛盾;另外,在设计过程中可能修改功能。如果不能紧跟这种变化并及时修改需求规格说明书,则产生该类缺陷。

(2)功能缺陷:软件实现的功能与用户要求的不一致,通常是由于需求规格说明书中包含错误的功能、多余的功能或遗漏的功能所致,在发现和改正这些缺陷的过程中又可能引入新的缺陷。

(3)测试缺陷:软件测试的设计与实施发生错误,特别是系统级的功能测试不仅要求复杂的测试环境和数据库支持,还需要编写测试脚本,因此软件测试自身也可能发生错误;另外,如果测试人员对系统缺乏了解或对需求规格说明书做了错误的解释,也会发生许多错误。

(4)测试标准引发的缺陷:对软件测试的标准要选择适当,若测试标准过于复杂,则导致测试过程出错的可能很大。

2.系统缺陷

(1)外部接口缺陷:外部接口是指系统与终端、打印机、通信线路等外部环境通信的手段,所有外部接口之间、人与机器之间的通信都使用形式或非形式的专门协议。如果协议有错或太复杂,难以理解,致使在使用中出错;此外,还包括对输入/输出格式的错误理解,对输入数据不合理的容错等。

(2)内部接口缺陷:内部接口是指程序内部子系统或模块之间的联系,所引发的缺陷与外部接口相同,只是与程序内实现的细节有关。例如,设计协议错、输入/输出格式错、数据保护不可靠、子程序访问出错等。

(3)硬件结构缺陷:不能正确理解硬件如何工作,如忽视或错误地理解分页机构、地址生成、通道容量、I/O指令、中断处理、设备初始化和启动等而导致的出错。

(4)操作系统缺陷:不了解操作系统的工作机制而导致出错,当然操作系统本身也有缺陷,但是一般用户很难发现这种缺陷。

(5)软件结构缺陷:由于软件结构不合理而产生的缺陷,这种缺陷通常与系统的负载有关,而且往往在系统满载时才出现。例如,错误地设置局部参数或全局参数、错误地假定寄存器与存储器单元已初始化、错误地假定被调用子程序常驻内存或非常驻内存等。

(6)控制与顺序缺陷:例如,忽视了时间因素而破坏了事件的顺序、等待一个不可能发生的条件、漏掉先决条件、规定错误的优先级或程序状态、漏掉处理步骤,以及存在错误或多余的处理步骤等。

(7)资源管理缺陷:由于错误地使用资源而产生的缺陷,如使用未经获准的资源、使用后未释放资源、资源死锁,以及把资源链接到错误的队列中等。

3.加工缺陷

(1)算法与操作缺陷:在算术运算、函数求值和一般操作过程中发生的缺陷,如数据类型转换错、除法溢出、错误地使用关系运算符,以及错误地使用整数与浮点数做比较等。

(2)初始化缺陷:例如,忘记初始化工作区、忘记初始化寄存器和数据区、错误地为循环控制变量赋初值,以及用错误的格式、数据或类类型进行初始化等。

(3)控制和次序缺陷:与系统级同名缺陷相比,它属于局部缺陷。例如,遗漏路径、不可达到的代码、不符合语法的循环嵌套、循环返回和终止的条件不正确,以及漏掉处理步骤或处理步骤有错等。

(4)静态逻辑缺陷:例如,错误地使用switch语句、在表达式中使用错误的否定(如用“>”代替“<”的否定)、对情况不适当地分解与组合,以及混淆“或”与“异或”等。

4.数据缺陷

(1)动态数据缺陷:动态数据是在程序执行过程中暂时存在的数据,它的生存期非常短。各种不同类型的动态数据在执行期间将共享一个共同的存储区域,若软件启动时对这个区域未初始化,则导致数据出错。

(2)静态数据缺陷:静态数据在内容和格式上都是固定的,它们直接或间接地出现在程序或数据库中。有编译程序或其他专门对它们做预处理,但预处理也会出错。

(3)数据内容、结构和属性缺陷:数据内容是指存储于存储单元或数据结构中的位串、字符串或数字,其缺陷是由于内容被破坏或被错误地解释而造成的;数据结构是指数据元素的大小和组织形式,在同一存储区域中可以定义不同的数据结构,其缺陷包括结构说明错误及数据结构误用的错误;数据属性是指数据内容的含义或语义,其缺陷包括对错误地解释数据属性,如把整数作为实数,以及允许不同类型的数据混合运算而导致的缺陷等。

5.代码缺陷

代码缺陷包括数据说明错、数据使用错、计算错、比较错、控制流错、界面错、输入/输出错,以及其他错误。

6.需求规格说明书缺陷

需求规格说明书是软件缺陷出现最多的地方,其原因如下。

(1)用户一般是非软件开发专业人员,软件开发人员和用户的沟通存在较大困难,对要开发产品的功能理解不一致。

(2)由于在开发初期软件产品还没有设计和编程,只能完全靠想象描述系统的实现结果,所以有些需求特性不够完整、清晰。

(3)用户的需求总是不断变化,如果这些变化没有在需求规格说明书中得到正确的描述,则容易引起前后文、上下文的矛盾。

(4)不够重视需求规格说明书,在其编写上投入的人力及时间不足。

(5)没有在整个开发队伍中进行充分沟通,有时只有设计师或项目经理得到比较多的信息。

(6)排在编写需求规格说明书之后的阶段是设计,编程排在第3个阶段。在许多人的印象中软件测试主要是找软件代码中的错误,这是一个认识的误区。

1.6.4 软件缺陷处理跟踪

软件缺陷的处理跟踪是测试工作的一个重要部分,测试的目的是为了尽早发现软件中的缺陷,而对软件缺陷进行跟踪管理的目的是确保每个被发现的缺陷都能够及时得到处理。软件测试过程简单说就是围绕缺陷进行的,对缺陷的处理跟踪一般而言需要达到以下目标。

(1)确保每个被发现的缺陷都能够被解决,“解决”的意思不一定是被修正,也可能是其他处理方式(例如,延迟到下一个版本中修正或者由于技术原因不能被修正)。总之,对每个被发现的缺陷的处理方式必须能够在开发组织中达到一致。

(2)收集缺陷数据并根据缺陷趋势曲线识别测试处于测试过程中的哪个阶段。

(3)决定测试过程是否结束,通过缺陷趋势曲线来确定测试过程是否结束是常用并且较为有效的一种方式。

(4)收集缺陷数据并进行分析,作为组织过程改进的财富。

1.6.5 软件缺陷生命周期

生命周期的概念是一个物种从诞生到消亡经历的不同的生命阶段,软件缺陷的生命周期指从其被发现、报告到被修复、验证直至最后关闭的完整过程。在整个软件缺陷的生命周期中,通常是以改变软件缺陷的状态来体现不同的生命阶段。因此对于一个软件测试人员来讲,需要关注软件缺陷在生命周期中的状态变化来跟踪项目进度和软件质量,如图1-6所示。

图1-6 软件缺陷的生命周期

其步骤说明如下。

(1)发现—打开:测试人员找到软件缺陷并将其提交给开发人员。

(2)打开—修复:开发人员再现并修复缺陷,然后提交给测试人员验证。

(3)修复—关闭:测试人员验证修复过的软件,关闭已不存在的缺陷。

在实际工作中,软件缺陷的生命周期不可能像如上述那么简单,需要考虑其他多种情况。一个复杂软件缺陷生命周期的例子如图1-7所示。

图1-7 复杂软件缺陷生命周期的例子

综上所述,软件缺陷在生命周期中会经历数次审阅和状态变化。最终测试人员消除它,结束其生命周期。软件缺陷生命周期中的不同阶段是测试人员、开发人员和管理人员一起参与、协同测试并解决的过程,它一旦被发现即进入测试人员、开发人员、管理人员的严密监控之中,直至其生命周期终结。这样既可保证在较短的时间内高效率地关闭所有的缺陷,缩短软件测试的进程,提高软件质量,也可减少开发、测试和维护的成本。

1.6.6 软件缺陷处理

1.软件缺陷处理技巧

管理人员、测试人员和开发人员需要掌握在软件缺陷生命周期的不同阶段处理软件缺陷的技巧,从而尽快处理它,缩短其生命周期。以下列出处理软件缺陷的基本技巧。

(1)审阅:当测试人员在缺陷跟踪数据库中输入一个新的缺陷时,应该提交它,以便在其能够起作用之前进行审阅。这种审阅可以由测试管理员、项目管理员或其他人员来进行,主要审阅缺陷报告的质量水平。

(2)拒绝:如果审阅者决定需要对一份缺陷报告进行重大修改,如添加更多的信息或者改变缺陷的严重等级,则应该和测试人员一起讨论。由测试人员纠正缺陷报告,然后再次提交。

(3)肯定:如果测试人员已经完整地描述了缺陷的特征并将其分离,那么审阅者应肯定这个报告。

(4)分配:当开发组得到完整描述特征并分离的缺陷时,测试人员会将报告分配给适当的开发人员。如果不知道具体开发人员,则应分配给项目开发组长,由其分配给相应的开发人员。

(5)测试:一旦开发人员修复一个缺陷,则将进入测试阶段。缺陷的修复需要得到测试人员的验证,并且还要进行回归测试,以检查这个缺陷的修复是否会引入新的问题。

(6)重新打开:如果这个修复没有通过确认测试,那么测试人员将重新打开这个缺陷的报告并加注释说明,否则会引发打开与修复多个来回,造成测试人员和开发人员之间不必要的矛盾。

(7)关闭:如果修复通过验证测试,那么测试人员将关闭这个缺陷,只有测试人员有关闭缺陷的权限。

(8)暂缓:如果每个人都同意将确实存在的缺陷移到以后处理,则应该指定下一个版本号或修改的日期。一旦新的版本开始开发时,这些暂缓的缺陷应该重新被打开。

测试人员、开发人员和管理人员必须紧密合作并且掌握软件缺陷的处理技巧,在项目的不同阶段及时审查、处理和跟踪每个软件缺陷,方可加速软件缺陷状态的变换;同时提高软件的质量,促进项目的发展。

2.软件缺陷跟踪系统

到目前为止,讲述的一切运用到实践中还需要软件缺陷跟踪系统,以便描述报告所发现的缺陷、处理软件缺陷属性,以及跟踪软件缺陷的整个生命周期和生成软件缺陷跟踪图表等。建立一套软件缺陷跟踪系统会让我们受益无穷,概括起来有如下7个方面。

(1)软件缺陷跟踪系统应建立软件缺陷跟踪数据库,它不仅有利于软件缺陷的清楚描述,并且提供统一的标准化报告,使所有人的理解一致。

(2)缺陷跟踪数据库允许自动连续地进行软件缺陷编号,并且提供大量供分析和统计的选项,这是手工方法无法实现的。

(3)基于缺陷跟踪数据库可快速生成满足各种查询条件、必要的缺陷报表及曲线图等,开发小组乃至公司的每一个人都可以随时掌握软件产品质量的整体状况或测试及开发的进度。

(4)缺陷跟踪数据库提供了软件缺陷属性并允许开发小组根据对项目的相对和绝对重要性来修复缺陷。

(5)可以在软件缺陷的生命周期中管理缺陷,从最初的报告到最后的解决,确保每一个缺陷不会被忽略;同时,它还可以使注意力保持在那些必须尽快修复的重要缺陷上。

(6)当缺陷在其生命周期中变化时,开发人员、测试人员及管理人员将熟悉新的软件缺陷信息。一个设计良好的软件缺陷跟踪系统可以获取历史记录,并在检查缺陷的状态时参考历史记录。

(7)在软件缺陷跟踪数据库中关闭的每一份缺陷报告都应该记录下来,当产品送出时每一份未关闭的缺陷报告都提供了预先警告的有效技术支持,并且证明测试人员找到特殊情况下突然出现的事件中的软件缺陷。

3.软件缺陷报告

任何一个缺陷跟踪系统的核心都是“软件缺陷报告”,一份软件缺陷报告的详细信息如表1-1所示。

表1-1 一份软件缺陷报告的详细信息

4.软件缺陷的详细描述

软件缺陷的详细描述由3个部分组成,即操作/重现步骤、期望结果、实际结果,说明如下。

(1)操作/重现步骤:提供了如何重复当前缺陷的准确描述,应简明而完备、清晰而准确。这些信息对开发人员是关键的,视为修复缺陷的向导,开发人员有时抱怨糟糕的缺陷报告往往集中在这里。

(2)期望结果:与测试用例标准或需求规格说明书等一致,达到软件预期的功能。测试人员站在用户的角度描述,它提供了验证缺陷的依据。

(3)实际结果:即测试人员收集的结果和信息,以确认缺陷确实是一个问题,并标识那些影响缺陷表现的要素。

5.缺陷报告的案例

一份优秀的缺陷报告记录最少的重复步骤,不仅包括期望结果、实际结果和必要的附件,还提供必要的数据、测试环境或条件,以及简单的分析。

【案例】优秀的缺陷报告。

重现步骤如下。

(1)打开一个编辑文字的软件并且创建一个新的文档(可以录入文字)。

(2)在这个文件中随意录入一两行文字。

(3)选中一两行文字,通过选择Font菜单,然后选择Arial字体格式。

(4)一两行文字变成了无意义的乱字符。

期望结果为当用户选择已录入的文字并改变文字格式的时候,文本应该显示正确的文字格式而不会出现乱字符。

实际结果为字体格式的问题,如果在改变文字格式为Arial之前保存文件,则缺陷不会出现。缺陷仅仅发生在Windows系统并且改变文字格式为其他字体格式时,文字显示正常。

而一份含糊而不完整的缺陷报告缺少重建步骤,并且没有期望结果、实际结果和必要的图片。

【案例】含糊而不完整的缺陷报告。

重现步骤如下。

● 打开一个编辑文本的软件。

● 录入一些文字。

● 选择Arial字体格式。

● 文字变成了乱字符。

期望结果无。

实际结果无。

一份随意的缺陷报告(无关的重建步骤,以及对开发人员理解这个错误毫无帮助的结果信息)如下。

【案例】散漫的缺陷报告。

重现步骤如下。

● 在Window系统中打开一个编辑文本的软件并且编辑已有文件。

● 文件字体显示正常。

● 添加的图片显示正常。

● 创建了一个新的文档。

● 录入大量的文字。

● 选择几行文本,并且通过选择Font菜单选择Aria1格式改变了文本的字体而出现乱字符。

● 有3次重现了这个缺陷。

● 在Linux操作系统中运行这些步骤没有任何问题。

● 在Mac操作系统中运行这些步骤没有任何问题。

期望结果为当用户选择已录入的文本并改变文本格式的时候,文本应该显示正确的文字格式不会出现乱字符。

实际结果为,试着选择少量不同的字体格式,但是只有Arial字体格式有软件缺陷。不论如何,它可能会出现在没有测试的其他字体格式中。