



SSD测试工程师需要具备以下基本素养。
这一小节主要介绍进行常见的SSD测试需要了解的基础知识。
这几个单位在SSD测试中比较常见,我们需要简单了解它们之间的转换关系:1个二进制位称为1bit(用作单位时写作b),1个字节称为1Byte(用作单位时写作B),1个字称为1Word,1个双字称为1Dword。
1B=8b
1Word=2B=16b
1Dword=2Word=4B=32b
基础的位移运算,对于SSD测试人员来说也是需要掌握的知识。相关的资料有很多,我们不再赘述。
SSD领域常见的测试工具或者自研开发的测试平台,一般都会提供返回数据Buffer的方式以便定位问题。我们需要了解如何对这些数据Buffer进行解读。至于大、小端的基本知识,这里我们不再赘述。
假定一个LBA被成功写入了数据,并且是以数据模式0x1234ABCD写入的。当读取该LBA数据并查看数据Buffer时,需要首先明确数据Buffer具体是以大端(高位字节排放在内存的低地址端,低位字节排放在内存的高地址端)还是小端(低位字节排放在内存的低地址端,高位字节排放在内存的高地址端)形式返回的。图1-6展示了小端和大端形式的数据。
图1-6 大小端形式的数据
iostat是Linux下的一个常用的命令行工具,它可以显示磁盘IO统计信息,我们可以使用这个命令进行一些性能数据的统计。但是在某些场景下,我们可能会发现iostat和FIO的IOPS存在不匹配的情况,这个主要是由具体IO模型所使用的块大小(BS)和盘片最大数据传输大小(MDTS)不一致引起的。
当FIO执行的IO请求的块大小超过NVMe设备的最大数据传输大小时,FIO并不会上报失败或错误;相反,FIO会根据操作系统和存储驱动程序的行为来处理这种情况。
通常,操作系统的存储驱动程序会自动将大于最大数据传输大小的IO请求分割成多个较小块的传输,这些块的大小不会超过最大数据传输大小的限制。因此,即使FIO的块大小参数设置得很大,这些请求也会被自动分割成符合最大数据传输大小限制的块大小。这一行为,使得FIO可以与不同的存储设备和配置无缝配合工作,即使它们有不同的最大数据传输大小的限制。同时,它也保证了NVMe设备的稳定性和可靠性,防止因单个IO请求过大而导致控制器不稳定。因此,我们测试性能时通常不需要担心最大数据传输大小的限制,除非是有特殊的性能调优需求或者需要对存储系统进行深入的性能分析。当然,如果我们使用FIO做一些命令的功能测试时,则需要留意FIO的这一特性,以免被误导。本书后续章节会对此进行详细介绍。
在iostat命令的日志中,TPS代表“Transfers per second”,即每秒传输的事务处理个数。这是一个衡量磁盘IO负载的指标,显示了每秒对设备或分区执行的IO操作(读取或写入)的平均次数。TPS是高值通常表明磁盘活动很高,可能是因为有大量的IO操作在被执行。这个指标对于理解存储设备的性能和它们如何处理负载是有帮助的。
简单地讲,FIO的IOPS与IO模型的实际块大小匹配,iostat TPS与盘侧的IO操作次数匹配,对于同一个性能度量,虽然IOPS与TPS的数值可能不一致,但是盘侧实际IO带宽是一致的。
下面是我们用的一个NVMe SSD。这块盘逻辑块大小为4KiB,MDTS为5(等价于128KiB)。
当我们将FIO的块大小设置为128KiB时,可以看到FIO和iostat均为23.7k IOPS,因为128KiB的块大小正好是单笔命令传输数据大小的上限。具体实验数据如图1-7所示。
图1-7 FIO与iostat的IOPS示例1
当我们将FIO的块大小设置为256KiB时,可以看到FIO为13.8k IOPS,但是iostat对应的却是27.7k TPS,大约是FIO数值的2倍。我们可以发现,256KiB正好是上限128KiB的2倍,FIO实际切分成两笔命令后才下发。因此,iostat统计到的命令次数就是FIO数值的2倍了。具体实验数据如图1-8所示。
图1-8 FIO与iostat的IOPS示例2
我们需要额外注意的是,在不同的操作系统和驱动环境下,FIO具体的切分方式可能与我们上述的实验并不一致。所以,如果要使用iostat的TPS去反映IOPS,需要特别留意底层驱动的具体切分方式。后文会详细介绍FIO,这里不再展开。
测试人员需要确保在整个测试过程中将所发现的问题都记录下来,无论这是不是一个“真正的问题”,也不论这个问题最终会不会“被解决”。
笔者曾经跟一个项目经理深入探讨过这个话题。他不止一次地跟笔者抱怨,项目上经常会遇到一些“莫名其妙”的漏测问题。笔者建议他先仔细分析一下这些漏测问题,并尝试追溯发生的原因。我们发现有不少漏测问题居然都是“人为”造成的,并不是什么技术性问题导致的。比较典型的人为因素就是,测试过程中测试人员发现了一些蛛丝马迹,跟开发人员对齐完草草了事,并没有对问题进行跟踪。这就直接导致了项目经理完全不能感知到这些潜在的问题,而且这些问题会随着项目的推进逐渐被遗忘,最终变成一个个“暗箭”。而越到项目后期,这些“暗箭”会变得越可怕。
这里有一个实际的例子。
测试人员在测试过程中,发现了命令返回的盘片容量大小有点问题,于是跟开发人员对齐。开发人员反馈“这是一个已知问题”,当前版本不会修正,后续版本他们会修正。于是,测试人员就修改了测试这边相应的配置值,以便后续测试在当前版本下能够继续执行,可怕的“暗箭”就此产生了。后面我们做再多的努力,技术上做再多的突破,也很难暴露这个问题。不幸的是,这个问题很快被后续团队抓住,笔者的朋友结结实实地挨了“板子”,一顿毫无技术意义的“板子”。
作为测试人员,我们一定要守住一个底线——确保所有的发现都“有单可查”。
有些“口号型”研发团队,开会的时候都会不停强调测试的重要性,实际项目执行过程中却搞开发“一言堂”,测试人员却成了开发的副手。
这个现象在国内“小团队”中相对常见一些。会出现这种情况,一个原因是开发人员的技术能力普遍比测试人员高,再一个原因是这些“小团队”会因为各种原因重开发而轻测试。这种做法的危害性是显而易见的,测试团队发挥不出应有的价值,也给不出让人信服的质量评估结论。
在我所经历的几个项目中,在问题对齐时也经常会有测试人员反馈某些脚本修改或者测试设计是开发人员让他做的,但是测试人员自己并不理解其中的缘由,这种情况是极其危险的,很可能给测试团队埋下一个“大炸弹”。
对于一个SSD测试人员,我建议大家首先从用户的视角去看待遇到的问题或者争议,一定不能一味地按照开发的想法去做测试。开发人员的视角跟测试人员的视角,还是存在一定差别的。测试人员需要时刻记住自己是球场上的守门员,而不仅是一个球童。测试团队存在的意义,就在于梳理出专业的测试方法并严格施行,最终输出相应的质量评估结论。
我建议测试团队的管理人员经常提醒测试人员,杜绝此类问题的发生。
SSD测试比较复杂,我们的测试也很难达到百分百的覆盖率,因此就会产生相应的测试漏洞。测试漏洞本身并不难解决,我们只需要在测试迭代过程中进行补齐就可以了。难的是我们要如何发现这些测试漏洞。
在实际项目中,测试团队可以借助研究白盒测试和黑盒测试各自发现的问题来分析对方的测试漏洞,二者相互印证,能够快速提高整体测试覆盖率。简单一点讲,通过分析黑盒测试拦截到的问题,我们可以分析出白盒测试的漏洞;反之亦然。那么,这个做法的实际意义又是什么呢?
以黑盒测试为例,假设我们在黑盒测试过程中发现了一个白盒测试的遗漏问题,我们就可以尝试补充相应的白盒测试。一方面,我们可以在分析的过程中,检查相关模块的测试有无其他漏洞;另一方面,我们可以用补充的白盒测试来精准地验证黑盒测试发现的问题是否成功得到修正。因为,对于一些边缘情况,黑盒测试没有发现问题并不代表真的没有问题。
此外,如果我们能够得到整体测试集对应的固件代码覆盖率,那么问题会变得更加简单明了。目前,市面上已经有不少商业性的软件工具,可以帮助我们统计代码覆盖率。如果团队能够使用相应的工具,就会让我们分析测试漏洞的工作变得非常简单而又明确。对于这些商业软件,这里我们就不做过多介绍了,大家可以自行检索。
在实际项目测试过程中,我们可能会发现,使用同样的测试集在项目迭代过程中拦截的问题越来越少了。但是,在后续测试流程中又能够发现一些被遗漏的问题,这就是我们说的测试的“免疫性”。白盒测试是相对更加容易出现该问题的领域,因为它的验证点更加精准、范围更加明确。
所以,我们的测试需要不断优化,不断更新迭代,以降低“免疫性”。这也是我们不能一味地只关注白盒测试而忽略黑盒测试的一个重要原因。
同样地,在项目进行到一定阶段后,如果发现测试拦截不到新的问题了,我们就需要静下心来,思考一下是否中了测试免疫的陷阱,是否需要对测试进行增强。
对于大多数领域来讲,对应的测试都是一个“无底洞”。换句话来说,只要我们持续不断地投入测试,总会发现一些新的问题。但是获得的收益并不会与测试投入成正比。随着测试投入的加大,收益反而可能会降低。相信大家在实际项目中都会遇到类似的情况:前期的测试投入比较容易发现新问题,单位测试量所收获的问题数量比较高,一段时间后发现新问题的数量呈现逐渐收敛的趋势,单位测试量所拦截的问题数量也会逐渐降低。
SSD本身就是一个比较复杂的整体,其对应的测试的复杂度也会比较高。另外,大多数公司并不会组成庞大的测试团队来应对这一情况。所以,作为SSD测试人员,首先,我们需要明白测试团队不可能有无限的时间来无限制地对SSD进行质量验证。其次,我们需要知道如何来应对这一问题:
● 识别高风险模块并加大测试覆盖面。
● 识别高优先级的测试点。
● 善于利用下游团队的知识,例如多去了解后续客户的实际使用场景。
● 实现测试自动化、测试流程自动化,以提高测试效率。
● 加强测试覆盖分析。
● 白盒、黑盒测试相互结合、相互印证。
我们在实际编写测试脚本时,经常会考虑使用一些随机数,比如随机的逻辑地址、随机大小的IO数据块等。大多数场景下,使用随机数并不会引发什么问题。但是,在某些情况下,是不能随便使用随机数的。这里基本的原则是,使用随机数不会对测试用例的设计产生影响从而导致测试覆盖的缺失。
举个例子,我们计划验证几种特定的IO数据块大小能否被正确处理,那么测试脚本在实现中就不能去随机选择其中的一种或者几种IO数据块大小,哪怕我们可能会使用多次循环、重复执行的方式。
我们在实际开展SSD测试时,可能会遇到开发团队抱怨测试人员在某些模块或者某些场景下的测试压力太大了或者场景太极端了。
遇到这种情况,我们可以分析一下具体测试是否真的是过度测试,比如我们的验证指标是否超出了产品需求的定义或者我们是否测试了产品不支持的功能点,等等。对于上述情况,我们一般可以当作真正的过度测试来处理。但是也会有假的过度测试存在,毕竟开发人员和测试人员看待问题的视角是有区别的。我们曾经在一个实际项目上发现当对SSD进行频繁上下电时,会出现上电超时的现象。起初开发人员认为是测试人员的上下电操作过于频繁,超出了实际使用范围,但是硬件团队最终分析得知,这个问题是电容充放电有问题导致的,其实是一个硬件问题。总而言之,测试团队需要把控好质量标准,一切以产品需求和对应的测试需求为准。