我正在阅读Osherove的《单元测试的艺术》,尽管他还没有涉及性能测试,但仍有两个想法浮现在我脑海中:
- 通常性能测试不能是单元测试,因为性能测试通常需要长时间运行。
- 通常性能测试不能是单元测试,因为性能问题往往在集成或系统级别上表现出来(或者至少需要单元测试的逻辑重现集成环境的性能,这将太复杂而无法成为单元测试)。
特别是针对上述第一个原因,我怀疑性能测试是否由单元测试框架(如NUnit)处理是没有意义的。
我的问题是:我的发现/倾向是否与社区的想法相符?
我正在阅读Osherove的《单元测试的艺术》,尽管他还没有涉及性能测试,但仍有两个想法浮现在我脑海中:
特别是针对上述第一个原因,我怀疑性能测试是否由单元测试框架(如NUnit)处理是没有意义的。
我的问题是:我的发现/倾向是否与社区的想法相符?
我同意你的发现和学习成果。真正的单元测试只测试系统的一部分,而忽略、模拟或伪造其他部分的必要性。集成测试(或回归测试)测试大多数或所有单位之间的协作,这才是真正的性能衡量标准。
在某些情况下,您可以使用单元测试来确保操作在一定时间内完成。如果您想向操作添加更多功能,但不想牺牲性能,您可以使用单元测试来断言。当然,这些单元测试是依赖于机器的,但您可以将一些额外的变量或配置加入方程中。
性能测试很可能由单元测试组成。
例如,一个单元测试可以将多个不同的参数传递给一个方法,并验证该方法返回预期的输出。性能测试可以执行该单元测试1000次(或者您认为有意义的其他值),同时记录从CPU和内存计数器到每个测试所需时间的所有内容。
单元测试应该在很短的时间内执行,因为您只测试一个非常具体的单元/系统。比如,如果您要测试的系统是ClassA:IClassA,则进行模拟/存根并仅测试ClassA的行为,而不应测试除ClassA之外的其他行为,例如ClassA是否使用ClassB。您应该注入ClassB的模拟而不是具体实现以实现此目的。
就性能测试而言,仍然有必要使用像NUnit / MBUnit / MavenThought这样的测试框架,只需将这些测试保存在单独的程序集中,并且不要将其作为单元测试的一部分调用。
因此,如果您使用Rake来调用测试,则其中一些任务可能如下所示:
Rake Test:All #Run all unit tests
Rake Test:Acceptance #Run all acceptance tests
Rake Test:Performance #Run all performance tests
Rake Test:Integration #Run all integration tests
在您的持续集成中,成功构建后总是会调用Test:All进行测试,而Test:Performance则每天在凌晨12点调用。
一切都取决于你所谓的性能测试。当微调特定代码时,我通常使用非常类似于单元测试的东西(我应该称其为单元性能测试吗?)。这基本上就是我在这个question中所做的事情(尽管在那里并不真正关心使用单元测试框架)。但我也会在BOOST单元测试框架中优化我的C++生产代码。
实际上,在不同级别和不同目的下有许多种性能测试(重载压力测试、分析、微调)。你在问题中提到的性能测试似乎是在功能测试级别进行的。对于这个级别,你可能不会使用单元测试框架。
单元测试和性能测试之间存在明显的差异。首先,单元测试是针对应用程序的功能要求进行的测试。例如,你希望确保点击“主页”选项卡时网页会导航到主页。而性能测试则是一种非功能性测试。在这里,你关注的是应用程序在特定用户负载和一定时间内的稳定性和响应能力。
我记得多年前,微软倡导程序员使用Visual Studio Net Application Center Test (ACT) 对他们的单个asp进行性能测试。有一个完整的方法论用于对单个asp执行事务成本分析(TCA)。(现在可能还在使用中)。
即使使用Web driver,也可以使用这种方法来测试这些asps,并使用可选的模拟对象来隔离要测试的代码(例如模拟数据库访问,如果尚未开发)。
只要您有一个驱动程序,以及可选的模拟对象框架来处理任何尚未编写的依赖项,就可以使用任何单元测试遵循此方法。这种方法也变得流行起来,如SOAPUI\LOADUI。
另外,我建议将可以针对给定数据库设计进行测试(优化)的单个SQL语句隔离出来。这(DB)SQL单元性能测试可以在SDLC早期进行,它会发现查询优化机会。
就成本和价值而言:我发现在SDLC早期使用适当的模拟对象进行早期单元性能测试将识别出内存泄漏、过度CPU使用和磁盘IO,但我会为高风险项目选择测试代码。