大型测试指南






2.60/5 (2投票s)
关于软件测试的简要概述
引言
根据我的经验,对于许多人来说,在软件测试方面,他们的头脑中存在很大的混乱,有时甚至对于程序员和项目经理也是如此。这就是我决定写一篇博文的原因,它将大致概述软件测试的不同方式。
当我开始职业生涯时,我为一家小型初创公司工作。在那里,软件测试意味着有人启动软件,进行一些随机点击,并检查是否发生了奇怪的事情。后来,我转到汽车行业。在这个领域,测试非常严格。但我所学到的是,软件本身决定了正确的测试过程。这取决于:你的软件对安全性有多关键,谁会使用它,它有多复杂等等。
有几种测试方式,这些方法可以是自动化或手动,功能性或非功能性,黑盒、灰盒或白盒,并且可以在几个不同的级别(单元测试、组件测试等)进行。对于每个项目,你需要找到最适合的测试方式。当然,你使用的测试方法越多,软件中保留bug的可能性就越低(而且这个可能性永远不会达到零),另一方面,测试需要时间,所以也需要成本。这就是为什么你需要找到最适合你项目的方式。现在我将尝试向你介绍不同的测试方式。
功能性测试和非功能性测试
功能性测试
测试可以是功能性或非功能性的。功能性测试通常是针对功能性需求进行的。在这里,你基本上是检查你的软件功能是否与所要求的行为相同。你还需要始终关注边缘情况。
非功能性测试
非功能性测试是针对非功能性软件需求进行的,它可以针对软件的稳定性,它可以测试软件是否在每个要求的环境(操作系统、网页浏览器、不同的硬件等)下运行。安全测试也属于此类别,它检查你的软件是否足够安全,这在基于网络的应用程序中尤其重要。负载测试也属于此,它测试你的软件在大量请求情况下的反应。在这里,你还可以测试软件在最关键场景下的运行时间(性能分析)或内存消耗。它也可以是可用性测试,你与目标用户一起测试你的软件是否足够用户友好。
自动化测试和手动测试
自动化测试
自动化测试通常是所谓的“代码化”测试。它们只需实现一次,之后可以随时运行。典型的例子是使用一些测试框架(GTest、JUnit等)对代码进行单元测试。其他自动化测试可以通过一些测试框架(如Selenium)或脚本语言(Python在这个领域也很受欢迎)来实现。这里的共同点是你向你的程序或程序的一部分提供一些输入,然后让你的程序运行,最后将结果与所谓的预期结果进行比较。自动化测试应该是确定性的。这意味着对于相同的代码片段,它们应该总是通过或总是失败。自动化测试的最大优势是,你可以在每次更改代码库后运行此类测试,并检查更改是否破坏了你已经正常工作的功能。因此,你可以将它们集成到持续集成系统,该系统在每次新提交后运行一次你的测试。
自动化测试也可以与你的代码并行实现,因此你无需等待软件完成后再进行测试开发。
手动测试
手动测试是可以手动完成的测试。因此,你手动启动程序,执行一些预定义的步骤并检查其行为。对于你不想频繁测试的功能或难以以自动化方式测试的功能,进行此类测试是好的。这里重要的是:手动测试也需要基于测试计划进行,该计划描述了具有精确测试步骤和预期行为的不同测试场景。
基于代码知识的测试类别
黑盒测试
在黑盒测试中,你对代码一无所知。你就像一个普通用户,尝试软件的不同功能,而不考虑其实现细节。对于黑盒测试,最好有一个对软件实现细节真正了解的测试人员(因此他没有参与其开发)。黑盒测试通常是针对软件需求进行的,这些需求也需要良好文档化才能定义好的测试用例。在黑盒测试中,你还需要像用户一样思考。黑盒测试可以是自动化测试,也可以是手动测试。
白盒测试
在白盒测试中,你可以访问整个代码库,并在测试用例定义中也考虑它。例如,你知道函数的精确参数,并且你知道在负参数值的情况下,函数必须抛出异常,那么你应该定义这样一个测试用例。最典型的白盒测试是单元测试,但你也可以在不同的级别进行白盒测试。它既可以是自动化测试,也可以是手动测试。因此,如果你作为代码的开发人员使用调试器尝试你的代码在特定输入下的行为,那也算作白盒测试。白盒测试中一个重要的计数器叫做代码覆盖率:它表示当你运行所有测试时,你的代码中有多少百分比的行真正运行。
灰盒测试
在灰盒测试中,你对代码的了解有限。例如,你知道有哪些组件,使用了哪些接口,接口的参数是什么,但你不知道组件是如何实现的。
测试级别
测试有不同的级别,从测试一小段代码到测试整个系统。每个级别都有其自身的优缺点。通常,较低级别测试的优点是它们运行速度更快,并且可以更精确地显示错误的根本原因。另一方面,有些错误只能通过较高级别测试来检测,因为它们是由不同软件组件的错误协作引起的。但在较高级别测试中,很难判断失败的测试用例中错误的根本原因是什么,并且通常它们运行时间更长。
单元测试
单元测试是最低级别的测试。单元测试测试一个单元。一个单元应该足够小,大多数情况下,它是一个函数或一个类。在单元测试中,你确实在测试这一小段代码。为了避免受其他单元的影响,其他单元可以被模拟。这意味着你正在用一些虚假/虚拟行为替换代码片段。为此,有几个模拟框架,如Mockito或GMock。为了能够进行模拟,你需要有一个清晰且模块化的代码架构。一种使模拟变得容易的常见方法叫做依赖注入。
一个好的单元测试应该是小的、快速的、独立的,并且测试一小段代码。通常,单元测试是自动化的,但也可以是手动的。
另一个重要的方法叫做基于测试的开发,你基本上与代码并行实现单元测试用例。
单元测试通常由代码开发人员完成。从长远来看,它有助于发现回归。
一个好的单元测试在失败时能显示错误的准确位置,这样就不需要长时间调试来修复你的代码。
组件测试
组件测试是关于测试代码的一个组件。如果你的代码足够模块化,并且被组织成具有清晰接口的组件,你也可以单独测试这些接口。这是灰盒测试的一个很好的候选。所以你知道要使用哪些接口(例如,在库的情况下),并且你知道你期望这些接口提供什么,但你不知道它们的具体实现。
集成测试
集成测试用于测试多个组件如何协同工作。集成测试还可以检测由组件不正确协作/连接引起的错误。
系统测试
系统测试是针对整个系统的,因此你的软件在其目标硬件上以其目标环境运行。这些测试通常在软件发布之前作为最终测试进行。这些应该在每个软件发布时进行。这通常是黑盒测试,可以是手动或自动的。这个级别的测试通常由独立的测试团队完成。
谁应该测试?
关于谁应该进行测试的问题,有几种不同的观点。在经典的测试方法中,通常的规则是测试人员和开发人员应该是两个人。因此,如果开发人员思维方式错误或对功能理解错误,测试人员仍然可以找到错误。我认为这在较高级别的测试中以及通常在黑盒测试中是一个好方法。
在现代测试方法(如基于测试的开发)中,测试人员和开发人员通常是同一个人。这与敏捷方法很好地契合,在敏捷方法中,所有团队成员都应该能够承担任何类型的任务(测试、开发、设计等)。这种方法使测试稍微快一些,但根据我的经验,它也不是那么有效。
我认为最安全的方法是两种方法的结合:开发人员实现单元测试,由独立团队使用黑盒测试在更高级别进行测试。但对于所有开发来说,都需要考虑是否值得花费这么多时间进行测试。对于汽车开发或飞机软件开发等安全关键系统,当然有意义。但对于网页或游戏移动应用程序,可能就不那么重要了。
项目生命周期中的测试
在像瀑布模型或V模型这样的经典开发方法中,测试显然是在实现之后进行的。但自动化测试的开发也可以与开发并行进行。在遵循这种经典方法的地方,软件也以循环方式完成。这意味着有定期的软件发布,并且每个发布的软件都应该进行测试。因此,当开发团队正在开发发布N+1时,测试团队正在测试发布N并为发布N+1准备自动化测试。
在像SCRUM或看板这样的敏捷开发方法中,通常遵循测试驱动开发。这意味着单元测试和实现是并行进行的。重要的是,在敏捷开发中,你也可以做一些更高级别的测试。你可以将其作为一个单独的用户故事来实施此类测试。或者也可以有一个单独的测试团队,他们也例如基于 scrum 工作,并且他们总是在几个冲刺后测试开发团队的结果。
无论是经典方法还是敏捷方法,我认为将自动化测试集成到 CI 系统中都非常重要,这样它就能定期检查软件是否正常工作。当然,在这种情况下,测试也需要根据新实现的需求定期更新。由于运行所有测试可能需要很长时间,因此最好为不同级别的测试单独设置 CI。例如,在任何新提交时运行所有单元测试,每晚运行所有组件和集成测试,并在每次软件发布时运行所有测试。
摘要
我在写作过程中才意识到这是一个非常复杂的话题,所以我认为我无法详细介绍所有内容,但我希望我能为您提供一个好的概述。由于测试在不同的公司采用不同的方法和方式进行,我几乎可以肯定经验丰富的测试人员会不同意我的一些观点。这很可能发生,老实说,我也不是测试人员。我希望我的文章能对您有所帮助。