知识卡片
测试是系统架构最外圈的组件,脆弱测试问题会让系统变死板
内容
从架构角度看,无论是小型TDD测试还是大型的FitNesse/Cucumber/SpecFlow测试,所有测试对架构而言都是一样的:测试组件天然充满了各种针对被测代码的具体细节,因此始终向内依赖被测部分的代码——这让测试组件可以被视为系统架构里最外圈的程序,没有任何其他组件反过来依赖它。测试组件通常是独立部署的(哪怕系统本身不要求独立部署,测试代码往往也部署在测试环境而非生产环境),是系统里最独立的组件——系统正常运行不需要用到它,用户也不依赖它,它存在的意义是支持开发过程而非运行过程,但依然是系统不可或缺的一部分,甚至在许多方面反映了系统其他组件该遵循的设计模型。正因为测试独立、不进生产环境,开发者常常在系统设计里忽视它的重要性——这是个严重错误,没被纳入系统设计考量的测试往往非常脆弱,脆弱性会让系统变得死板难改。核心症结在于耦合:如果测试代码和系统强耦合,系统一变测试就得跟着变,哪怕只是某个组件的小改动,也可能连累成百上千个测试出问题——这被称为脆弱的测试问题(fragile tests problem)。典型场景是一套靠GUI校验业务逻辑的测试,从登录页面开始按导航顺序遍历到完成某个业务逻辑,这时任何针对登录页面或导航顺序的调整都会让大量测试出错;一旦开发者意识到简单改动会引爆一千个失败测试,他们自然会本能地抵制这类改动。解决办法回到软件设计的第一条原则——不管为了可测试性还是别的什么目的——都是不要依赖多变的东西:GUI往往是最易变的部分,靠GUI验证系统的测试注定脆弱,因此系统设计和测试设计都该让业务逻辑不必经过GUI就能被测试。
参考来源
- 位置:《架构整洁之道》第28章《测试边界》"测试也是一种系统组件""可测试性设计"(源文件:_epub-src/text/part0014_split_013.html)
- 结论依据:原文说明测试组件始终向内依赖被测代码、可视为架构最外圈且独立部署,指出忽视测试设计会导致脆弱测试问题(fragile tests problem),并用GUI导航变更牵连大量测试出错的例子说明解法是让业务逻辑不依赖GUI这类多变的东西,直接支撑本卡片结论。
- 原始内容:我们可以将测试组件视为系统架构中最外圈的程序……它们与应用程序变更……我们通常将这类问题称为脆弱的测试问题(fragile tests problem)……软件设计的第一条原则……就是不要依赖于多变的东西。