首页 测试 体会 查看内容

何时进行测试

2014-6-25 14:31| 发布者: tianzc| 查看: 750| 评论: 0

摘要:   大多数开发者都讨厌测试,他们往往会温和地测试,下意识的知道代码会在哪里出问题,并避开那些薄弱地方。注重实效的程序员与此不同。我们受到驱使,现在就要找到我们的bug,以免以后经受由别人找到我们的bug所带 ...
  怎样测试  我们已经考察了要测试什么,现在我们将把注意力转向怎样测试。包括:  ● 回归测试  ● 测试数据  ● 演练GUI系统  ● 对测试进行测试  ● 彻底测试  回归测试  回归测试把当前测试的输出与先前的(或已知的)值进行对比。我们可以确定我们今天对bug的修正没有破坏昨天可以工作的代码。这是一个重要的安全网,它能较少令人不快的意外。  我们到目前为止提到过的所有测试都可作为回归测试运行,确保我们再开发新代码时没有损失任何领地。我们可以运行回归测试,对性能、合约、有效性进行校验。  测试数据  我们从何处获取运行所有这些数据所需的数据?数据只有两种:现实世界的数据和合成的数据。实际上我们两者都需要,因为这两类数据的不同性质将揭示出我们软件中的不同bug。  现实世界的数据来自某种实际来源,它可能收集自己的系统,竞争者的系统,或是某种原型。它代表典型的用户数据。当你发现典型意味着什么时,你会大吃一惊。这最有可能揭示出需求分析中的缺陷和误解。  合成数据时人工生成的数据——或许受制于特定的统计约束,出于以下任何原因,你都有可能需要使用合成数据:  ●你需要大量数据,可能超过了任何现实世界样本所提供的数量,你也许可以用现实世界的数据做种子,生成更大的样本集,并且调整特定的有独特需要的字段。  ●你需要能强调边界条件的数据。这些数据可以完全由人工合成:含有1999年2月29日的日期字段,非常长的记录,或是带有外国邮政编码的地址。  ●你需要能展现出特定的统计属性的数据。想要看到如果每第三个事务都失败会发生什么?还记得在给予预先排好序的数据时会慢得像蜗牛的排序算法吗?你可以给出随机的或有序的数据,以暴露这种弱点。  演练GUI系统  测试GUI密集型系统常常需要专门的测试工具,这些工具可能基于简单的事情捕捉/重放模型,也可能需要专门编写的脚本驱动GUI,有些系统结合了这两者的基本要素。  不太完善的工具会在所测试的软件版本和测试脚本自身之间强加高度的耦合:如果你移动对话框,或是使按钮变小,测试也许就会找不到它,并且可能会失败。大多数现代的GUI测试工具都使用了一些不同的技术来绕开这一问题,并设法适应局部的布局变化。  但是,你无法使每一件事情都自动化。Andy开发过一个图形系统,允许用户创建并显示模拟各种自然现象的、非确定性的可视效果。遗憾的是,在测试过程中,你不能简单地抓取一个位图,把输出与先前的运行结果进行比较,因为它被设计成每一次都是不相同的。对于这样的情形,你也许别无选择,只能依赖于对测试结果进行人工解释。  编写解除了耦合的代码的诸多优点之一是更加模块化的测试。例如,对于有GUI前段的数据处理应用,你的设计应该足够地解耦,以使你无需使用GUI,就能对应用逻辑进行测试。这个主意与首先测试子组件类似,一旦应用逻辑得到了验证,就能更容易的定位在使用了用户界面的情况下出现的bug(bug很可能是用户界面代码制造的)。  对测试进行测试  因为我们不可能编写出完美的软件,所以我们也不可能编写出完美的测试软件。我们需要对测试进行测试。  把我们的测试套件集视为精心设计的保安系统,其用途是在出现bug时拉响警报。要测试保安系统,还有什么比设法闯入更好的办法呢?  在你先写了一个测试,用以检测特定的bug时,要故意引发bug,并确定测试会发出提示。这可以确保测试在bug真的出现时抓住它。  提示  Use Saboteurs to Test Your Testing 通过“蓄意破坏”测试你的测试  入股欧尼对测试真的而很认真,你可以指定一个项目破坏员(project saboteur),其职责是取源码树的一份单独的副本,故意引入bug,并证实测试能抓住它们。  在编写测试时,确保警报在应该响起时响起。  彻底测试  一旦你自信你的测试时正确的,并且正在找出你制造的bug,你怎么知道你已经足够彻底的对代码库进行了测试呢?  简短的回答是“你不知道”,而且你也不会知道。但市场上有一些产品能够提供帮助。这些覆盖分析(coverage analysis)工具会在测试过程中见识你的代码,追踪哪些代码行执行过,哪些没有。这些工具能帮助你从总体上了解测试的全面程度,但别指望看到100%的覆盖率。  即使你真的碰巧测试了每一行代码,那也并非是整个图景。重要的是你的程序可能具有的状态数。状态并非等同于代码行。例如,假定你有一个函数,用两个整数做参数,每个参数都可以是0到999的数。  int test(int a, int b){  return a < (a + b);  }  在理论上,这个三行代码的函数有1,000,000中逻辑状态,其中999,999种能正确工作,1种不能(当a和b都为0时)。只是知道你执行了这行代码并不会告诉你这一点——你需要确定程序所有可能的状态。遗憾的黑丝,一般而言这真的是一个困难的问题,就像是“太阳会在你解决它之前变成又冷又硬的块”一样困难。  提示  Test State Coverage,Not Code Coverage 测试状态覆盖,而不是代码覆盖  即使具有良好的代码覆盖,你用于测试的数据仍然会有巨大的影响。而且,更为重要的是,你遍历代码的次序的影响可能是最大的。  何时进行测试  许多项目往往会把测试留到最后一分钟——最后期限(dead-line)马上就要来临时。我们需要比这早得多地开始测试,任何产品代码一旦存在,就需要进行测试。  大多数测试都应该自动完成。注意到这一点很重要。我们所说的自动意味着对测试结果也进行自动解释。  我们喜欢尽可能频繁地进行测试,并且总是在我们把代码签入源码仓库之前。  通常,只要需要就回归地运行各个单元测试盒集成测试,这不成问题。  但是有些测试可能不容易这样频繁的运行。例如,压力测试可能需要特殊的设置或设备,以及某种手工操作,这些测试的运行可以不那么频繁——也许每周或每月一次,但让它们按照计划定期运行,这很重要。如果它无法自动完成,那就确保让它出现在计划中,并给这项任务分配所有必需的资源。  把网收紧  最后,我们想要揭示一个最重要的测试概念。这是个显而易见的概念,而且事实上每本教科书都说要这样做。但出于某种原因,大多数项目仍然没有这样做。  如果有bug漏过了现有测试网,你需要增加新的测试,以在下一次抓住它。  提示  Find Bugs Once 一个bug只抓一次  一旦测试人员找到了某个bug,这应该是测试人员最后一次发现这个bug。应该对自动化测试进行修改,从此每次都检查那个特定的bug。没有例外,不管多琐碎,也不管开发者会怎样抱怨说:”哦,那绝不会再发生了。”  因为它会再次发生,而我们完全没有时间去追踪自动化测试本可以为我们找到的bug。我们必须把时间花在编写新的代码——以及新的bug——上。
123

鲜花

握手

雷人

路过

鸡蛋

扫一扫关注最新动态

毒镜头:老镜头、摄影器材资料库、老镜头样片、摄影
爱评测 aipingce.com  
返回顶部