例如:在Web应用程序中执行表单的功能测试时,我们将通过输入不同种类的随机输入值来测试字段。
通常,作为Web应用程序的用户,我们实际上并未在字段中输入随机值。
那么,当生产中出现此类问题的可能性较小时,合并所有可能/可能不会导致错误的测试用例有什么用呢?
注意:上面的示例仅是示例案例;此类问题可能发生在任何种类的功能/模块中。
我问这个问题只是为了知道是否要遵循任何标准做法,或者它完全取决于产品,领域和所有其他因素。
例如:在Web应用程序中执行表单的功能测试时,我们将通过输入不同种类的随机输入值来测试字段。
通常,作为Web应用程序的用户,我们实际上并未在字段中输入随机值。
那么,当生产中出现此类问题的可能性较小时,合并所有可能/可能不会导致错误的测试用例有什么用呢?
注意:上面的示例仅是示例案例;此类问题可能发生在任何种类的功能/模块中。
我问这个问题只是为了知道是否要遵循任何标准做法,或者它完全取决于产品,领域和所有其他因素。
Answers:
您可能不会在Web应用程序的字段中输入随机值,但是肯定有人在那里执行此操作。
有些人是偶然输入的,其他人则是故意破坏应用程序的。在这两种情况下,您都不希望应用程序崩溃或表现出其他有害行为。
对于第一种类型的用户,您不希望这样做,因为这给他们带来了糟糕的体验,并可能使他们拒之门外。
对于第二种类型的用户,他们通常没有光荣的意图,您也不想让他们访问他们不应该访问的信息,或者不允许他们拒绝真正的用户访问您的服务。
测试的标准做法不仅是验证天气情况是否有效,而且还应验证是否探索了异常边缘情况以发现潜在问题,并确信攻击者无法轻松访问您的系统。如果您的应用程序已经因随机输入而崩溃,那么您就不想知道攻击者可以使用特制输入做什么。
您不能假设任何用户不会因意外或故意对软件进行任何“愚蠢”的操作。用户可能会不小心按下错误的按钮,猫会在键盘上走动,系统可能会发生故障,其计算机可能会受到恶意软件的劫持等。
此外,用户本身可能是恶意的,有意寻找破解软件的方法,以期希望他们找到一种利用软件的方法来发挥自己的优势。即使他们发现了无法利用的错误,知道自己缺少QA程序的情况下,发现的任何内容仍可能促使他们探查系统中可以攻击的内容。
就测试而言,防止随机输入是很有用的,但是完全随机选择测试输入(即不考虑任何用例或边缘用例的情况)几乎是无用的。测试的目的是根据雇主/客户/用户的要求和期望来验证您的解决方案;这意味着您需要专注于针对所有边缘情况和边界条件,以及与用户预期工作流程不符的任何“退化”情况。
当然,您可能会运行测试,以发现后来您认为不值得修复的错误。这可能是出于各种原因-该错误相对于其对用户的影响而言可能过于昂贵而无法修复,或者您可能会发现没人使用的功能中的错误,或者该错误可能已经很好地建立在系统中,以至于有些用户将其视为功能。
或者,您可能正在编写某些定制软件,这些用户的“专家”用户非常有限,而花时间修复错误并没有商业利益,因为这些用户能够使用错误软件来完成工作(例如,诊断工具内部IT团队使用的收入不会带来任何收益,因此,如果它偶尔崩溃,那么没人会愿意为修复它而花费时间-他们只会告诉IT团队忍受这些错误。 。
但是,只有知道这些错误,您才能做出这些决定。例如,用户可能输入恶意输入,从而抹去了整个数据库-如果您尚未针对这种情况进行明确的保护和测试,那么您将无法确定这种情况是否会发生。将未发现的错误留在系统中的风险意味着,如果其中一个错误在现实世界中暴露出来并对您的用户产生重大影响,则可能使您面临真正的问题。
因此,虽然是否要修复错误的决定可能需要软件所有者(通常是谁付钱给谁)的一些输入,但是是否要测试错误以及要测试哪种情况的决定是需要解决的工程问题。考虑到估算和项目计划,在时间/金钱/资源的限制下,目标应该是尽可能合理地接近全部覆盖范围。
For example, a user may enter a malicious input which wipes the entire database - if you haven't explicitly protected against and tested for this scenario, then there's no way you can be sure whether or not this can happen.
像这个 XKCD漫画中的小Bobby Tables一样吗?;)
有几个因素需要考虑。为了说明这些观点,我将使用一个字段示例,在该字段中,用户应在为特定任务定义的配额的上下文中输入百分比,以该任务可以使用的磁盘空间为单位。0%表示该任务将无法向磁盘写入任何内容;100%表示任务可以填满所有磁盘空间。中间的值表示它们的含义。
作为开发人员,您可能正在考虑可接受的值为[0、1、2、3,⋯99、100],而其他所有内容都是愚蠢的。让我们看看为什么用户仍然可以输入那些“傻”值。
%^
用户输入的值是56,但Shift在输入时误按了(例如,因为在法语键盘上,您必须按Shift输入数字,并且用户不断在法语键盘和QWERTY之间切换)。
以相同的方式,您可以获得一个数字,该数字在其之前或之后或之间:
56q
在这里,用户可能正在输入数字,然后输入制表符以移至下一个字段。 ⇆ 用户没有按,而是按了邻居键。
空输入可能是最常见的。用户以为该字段是可选的,或者不知道该字段中要放置什么。
56.5
用户认为浮点值是可以接受的。用户错了,应用程序应该礼貌地解释为什么只接受整数值,或者初始要求错了,让用户输入浮点值是有意义的。
none
用户误解了,当被问及任务可能占用的空间时,该应用会期望有一个数字。这可能表明用户界面不佳。例如,询问用户“任务应占用多少磁盘空间?”邀请进行此类输入,而带百分号的字段将收到较少的此类输入,因为“无%”不会很有道理。
150
用户在这种情况下误解了百分比的含义。也许用户想告诉该任务可以占用当前使用空间的150%,所以如果在2 TB的磁盘上使用了100 GB,则该任务可以使用150 GB。同样,更好的用户界面可能会有所帮助。例如,与其在裸露的输入字段上附加百分号,不如将其添加为:
[____] % of disk space (2 TB)
当用户开始输入内容时,它将即时更改文本,使其变为:
[5___] % of disk space (102.4 GB of 2 TB)
大数字或带有浮点数的数字可以不同地表示。例如,一些1234.56可以写这样的:1,234.56
。根据文化的不同,相同编号的文本表示形式也会有所不同。在法国,同样的号码将被写成这样:1 234,56
。看到,一个逗号(不要期待)和一个空格。
始终期望使用特定语言环境的特定格式会或早或晚给您带来麻烦,因为来自不同国家/地区的用户会有不同的书写数字,日期和时间等习惯。
Twenty-four
普通人与计算机的想法不同。“二十四” 是实际数字,与PC会告诉您的内容无关。
尽管(1)大多数系统不能完全处理这种类型的输入,并且(2)几乎每个用户都无法想象输入用全字母写的数字,但这并不意味着这种输入是愚蠢的。艾伦·库珀(Alan Cooper)在《关于面孔3》中指出,不处理此类输入表示计算机无法适应人类,并且理想情况下,该界面应该能够正确处理这些输入。
我唯一要添加到艾伦·库珀(Alan Cooper)的书中的是,在许多情况下,数字是错误地用数字写的。计算机希望用户犯错(并且不会容忍写得正确的用户)的事实令人讨厌。
5𝟨
Unicode保留了自己的惊喜:看起来相同的字符并不相同。不服气吗?复制粘贴"5𝟨" === "56"
到浏览器的开发人员工具,然后按Enter。
这些字符串不相等的原因是Unicode字符𝟨
与该字符不同6
。这将导致生气的客户打电话告诉您的应用程序无法正常工作,提供看起来合法的输入屏幕截图,并且您的应用程序声称该输入无效的情况。
您会问为什么有人要输入看起来像数字的Unicode字符?虽然我不希望用户无意间输入一个字符,但从其他来源复制粘贴可能会导致这种情况,而且我遇到了这样的情况:用户实际上对包含Unicode字符的字符串进行了复制粘贴,而不会出现在屏幕上。
这些是您获得基本数字输入字段的情况。我会让您想象一下,对于更复杂的表单(例如日期或地址),您必须处理什么。
我的回答集中在您所说的“傻”输入上。测试不是要检查幸福的道路。这还与当恶意用户有意输入奇怪的东西并试图破坏它时,检查您的应用程序是否不会中断有关。这意味着当您要求提供百分比时,还必须测试当用户使用包含1,000,000个字符,负数或bobby table的字符串进行响应时会发生什么。
1 234,56
字符串(使用U + 00A0 NO-BREAK SPACE而不是U + 0020 SPACE),这是编入这些数字标记(或使用U + 202F的正确方法)窄边休息空间,peroahps)。在呈现给用户之前,从任何根据语言环境对数字进行格式设置的应用程序中复制值,将非常容易产生该值。
这里有很多很好的答案来描述为什么这很重要,但是关于如何合理地保护应用程序却没有很多建议。“标准做法”是在客户端和服务器上都使用可靠的输入验证。不明智的输入很容易被抵制;您只是拒绝在特定情况下没有意义的任何事情。例如,一个社会保险号仅由破折号和数字组成;您可以放心地拒绝用户在社会保险号字段中输入的任何其他内容。
对您编写的每个应用程序都应进行两种测试,每种测试都有不同的用途。您在自己的应用程序上进行的测试是肯定测试;其目的是证明该程序有效。 测试人员还对您的应用程序执行的测试是负面测试;其目的是证明您的程序不起作用。 你为什么需要这个?因为您不是测试自己的软件的最佳人选。毕竟,您已经写了东西,显然它已经可以了,对吧?
在编写输入验证时,您将采用积极的测试来证明您的验证有效。测试人员将使用随机输入来尝试证明它不起作用。请注意,随机输入的问题空间实际上是无限的。您的目标不是测试所有可能的排列,而是通过拒绝无效输入来限制问题空间。
还要注意,最终用户并不是唯一向程序提供输入的人。您编写的每个类都有自己的API和对有效输入的约束,因此,可靠的验证(即“代码约定”)对您的类也很重要。这样做的目的是对您的软件进行强化,以使意外行为很少或根本不存在。
最后,工作流程很重要。我看到了应用程序崩溃的原因,不是因为用户输入了一些不合逻辑的内容,而是因为它们以意外的顺序在应用程序中执行了操作。您的应用程序应该意识到这种可能性,并且可以优雅地处理意外的工作流,或者要求用户按照您指定的顺序执行操作。
通常,“随机”值不是随机的。您正在尝试捕获极端情况,即“未知未知”。
举例来说,#字符会使您的应用崩溃。您事先不知道这一点,因此不可能为每个可能的输入编写测试用例。但是我们可以写一个测试"¬!"£$%^&*()_+-=[]{};'#:@~,./<>?|\"
,看看它是否损坏
我曾经写过一个程序,并在一个有60名学生的实验室中进行了现场测试。我站在60个计算机屏幕的后面,看到他们正在使用它。他们做的荒唐之举令人毛骨悚然。看着他们的“创造力”,我浑身是汗。他们所做的远远超过任何一个人一生中都能幻想的事情。当然其中之一打破了它。
之后,我遵循一种方法: if "a very specific use case" do, else show error
如果我有几个用例,我会严格定义它们并将其链接起来。
您要描述的是Fuzzing或Fuzz Testing:向系统抛出随机和无效的输入,然后看看会发生什么。您不这样做是因为您希望用户这样做。您这样做是为了暴露您自己的假设和偏见,以强调系统的边缘以查看发生了什么。
由人类编写的正常测试输入将带有假设和偏见。这些偏差可能是某些类别的错误无法通过测试发现的。
例如,如果您的大多数输入都在ASCII安全的Unicode范围内,则不会执行有关代码中字符编码的假设。也许它总是小于特定大小,因此不会命中固定大小的字段或缓冲区。也许有一些特殊的字符以令人惊讶的方式被解释,从而暴露了用户输入正被馈送到shell或用于以不安全的方式构建查询。或者,也许有太多的“快乐之路”测试,而没有足够的尝试来执行错误处理。
模糊测试对输入没有这种先入之见。它将通过“有效”输入的任何可能组合来残酷地锻炼您的系统。Unicode,ASCII,大,小以及很多错误。您的系统应优雅地响应所有这些。它永远不会崩溃。用户应该始终获得有关出了什么问题以及如何解决的明智信息。不是垃圾输入/垃圾输出,而是垃圾输入/错误输出。
尽管可能会因为“没有真正的用户会这样做”而消除由此产生的爆炸,但这却错过了练习的重点。模糊测试是消除您对可能输入的偏见的一种廉价方法。这是一种廉价的方法,可将用户尝试将所有奇怪的事情扔到您的系统上。作为工程师,您的工作是确保系统正常运行。
此外,模糊“输入”不仅仅与用户有关。它可能表示对第三者服务进行API查询的结果,如果它开始发送混乱的结果怎么办?您的系统如何处理?正确的系统应警告管理员组件已损坏。一个不正确的系统将悄悄地拒绝错误的查询,或者更糟糕的是,将其接受为良好的数据。
最后,一些用户是恶意的。如果您不对系统进行模糊测试,则其他人会进行测试。他们将探测系统边缘的常见错误,并尝试将其用作安全漏洞。模糊测试可以在某种程度上模拟这种情况,并且您可以处理在安全漏洞成为问题之前发现的任何可能的安全漏洞。
如果您的目标是创建优质产品,请测试用户将能够实际提交的每种可能的输入类型。否则,您只是在等待某人提交一种您不需要进行测试的输入的那一天。
在我工作的地方当局对新的电子拍卖软件进行的大规模展示中,我的经理断定(承认有一些恶作剧),他认为有必要看看如果他以负值进行拍卖时会发生什么。令我感到真正惊讶的是,拍卖软件允许这种毫无意义的投标,整个拍卖过程都停止了。所展示的拍卖类型绝不应该允许提交负数。
大批组装的采购和财务人员中的一些人因我的经理提出了荒谬的价值而感到恼火。但是其他人,包括我自己,对软件开发人员感到恼火,因为他们没有测试并拒绝这种明显类型的无效输入。我只能想象该软件在偏转其他类型的无效输入(代码注入尝试,数据库表中无法表示的外来字符等)方面必须具有多弱的能力。
由我自己决定,我将退还该软件,并认为它不适合其用途。弱软件产品与强软件产品之间的区别在于其所经受的测试水平。
test every possible type of input that a user will be physically able to submit.
-问题空间本质上是无限的,您通过尝试全部测试来浪费时间。检查负输入是一个单一的分支。这不仅是明智的,而且也是有能力的开发人员所期望的。您不必检查每个负数即可证明这种验证有效。
例如:在Web应用程序中执行表单的功能测试时,我们将通过输入不同种类的随机输入值来测试字段。
是。这是一种测试,但不是功能测试。这就是所谓的压力测试。向系统施加压力以查看它是否可以处理它。
那么,当生产中出现此类问题的可能性较小时,合并所有可能/可能不会导致错误的测试用例有什么用呢?
当您进行压力测试软件时,您试图发现该软件极限的界限。
这些测试本质上是详尽无遗的。在需要发现使用限制,断点,检查所有逻辑分支或查看部分故障如何影响整个系统的地方。
您可以使所有功能测试通过,但仍无法通过压力测试。
我问这个问题只是为了知道是否要遵循任何标准做法,或者它完全取决于产品,领域和所有其他因素。
是的,这是标准做法。
测试软件是关于询问预期行为的问题,当所有测试通过时,这表明软件可以按预期运行。这就是为什么测试为部署更新提供了良好的前提条件的原因。
压力测试没有提供明确的特定通过或失败指标。结果更具参考价值。它告诉您系统可以处理的内容,并根据这些信息做出决策。
您可以定义压力测试的特定目标,必须通过这些目标才能继续进行开发的下一阶段。这些可以包含在质量保证过程中,但是环境的变化会改变压力测试的结果。因此,人们在不同时间运行压力测试,以了解系统如何处理不断变化的条件。
我的意思是,您不能在每次部署新版本的软件时都进行压力测试,并且认为这意味着以后所有事情都将通过压力测试。