发表于: 2018-11-14 22:39:28

1 555


今天完成的事:

上午请假,下午测试租人

你为什么应该测试你的软件?你应该如何测试软件?

有些人对这些问题有非常简单的回答。

及时享乐型的程序员根本懒得去测试,快乐地活在当下。更严肃的程序员会告诉你软件测试是为了开发出高质量的产品。为了可以开发出高质量的产品,必须始终编写单元测试和集成测试,并做 QA 测试。忽略这些,你的代码将会掉入 bug 为患的深渊。

尽管我更赞同第二种观点,但我认为这不是一个完美的答案。考虑到不同的软件项目的差异,一套答案似乎不可能适合每个人。

  • 移动游戏、医疗设备和在线商店三者各不相同。

  • 每个组织也不尽同的,初创公司和大型跨国企业所拥有的资源是无法相提并论的,和 NASA 也是完全不一样的。

  • 每个项目都会经历不同的阶段,没有用户的产品和有成千上万交易的产品有非常不同的地位

你需要的不仅仅是一个答案,而是如何去选择适合你情况和需要的答案。我们首先会考虑适合你的测试方法。然后我们会考虑为什么要测试你的软件。最后,我们将结合方法和目标,来看一下你可以选择什么方式去测试你的软件。

你可以用什么样的测试方法?

首先,我们考虑下可以使用的不同测试方法。下面的代码是测试吗?

def test_add():

    assert add(2, 2) == 5


我会说,是的,那就是一个测试。从函数名上可以看出来。这个测试证明了函数add() 做了什么:对两个数字做加法,然后将结果返回给我们。

你一定注意到了,这个测试是错误的。幸运的是,我们的开发过程有另一步骤:代码审查。亲爱的读者,你可以作为一个代码审查者并告诉我,我的代码是错误的,2加2是4,不是5。

代码审查是一种测试方法吗?如果你试图验证你的代码符合规范,那么这就是一种测试。你大脑中有算术规范(”2 + 2 = 4″),你就会检查你的代码是否符合这个规范。

让我们把代码审查和自动化单元测试都做分别作为一种测试方法。尽管他们都是测试,他们也非常不同。他们之间的主要区别是什么?

测试的一种方法是自动化的,另一种是由人类完成的。

自动化测试是连续的和可重复的,你可以这么写:

def test_add_twice():

    for i in range(10000000):

        assert add(i, i) == 2 * i


计算机将会每次运行完全相同的代码,该代码将会确保函数 add() 对于这些特定的输入返回特定的输出。人在手动验证一千万种不同的计算时会遇到一些困难:无聊、分心、错误、迟缓。

另一方面,人类在阅读这个代码时,会告诉你这是bug:

def add(a, b):

    return a + b + 1


计算机所做的事情,无论是好是坏,人类都能明白他的意义。只有人类才知道软件的意义是什么。

现在我们可以按照使用的方法来对测试进行分类:人类测试意义,自动化测试确保一致性。

你为什么要测试软件?

接下来,让我们考虑测试目标。

测试软件的第一个可能的目标就是确保它符合规范。这个目标是大多数程序员在讨论测试时想到的:它涵盖了单元测试和手工测试,它也包括代码审查。你的软件具有某些必须的功能、规范,你想确保它在现在和未来也确实是这样的。

一些需求是高层次的:一个在线商店想要顾客可以订购他们添加到购物车的产品。其他需求是低层次的实现细节,只有程序员感兴趣。你可能想要函数 verify_creditcard() 接收信用卡号码作为字符串,然后如果信用卡是无效的,抛出一个 InvalidCreditCard 异常。

所有的这些需求都是规范,他可以被写的非常详细,也可以是头脑中的一个概念(如 2 + 2 等于 4 )。无论如何,你测试你的软件是为了确保它做了它应该做的事。

软件测试第二个可能的目标就是为了获得知识。让我随着这个目标看一下另一种测试形式。“A/B测试”就是你使用两个变量,然后看哪个变量产生更好的结果。或许你正在测试重新设计的网站:你给 90% 的访客展现你目前的设计,10% 的访客展现你的新设计,然后看哪种会让你的产品有更多的用户注册。

注意,你有两套规范,并且已经实现了他们。测试的要点就是找到哪种规范更好,学习一些新的东西,而不是验证实现是否符合规范。

现在我们已经知道为什么你需要做测试:要么验证你的实现符合规范,要么获得新的知识。

你应该如何测试软件?

结合我们提出的那两个目标(获得新知识和满足规范)和两种测试方法(手工测试和自动化测试),你会得到四种不同的测试形式,每种都会有更详细的测试目标。

对于你特定的需求和情况,你必须选择一种合适的测试方式。让我们逐个介绍这四种测试类型,看看每种测试类型应该在什么情况下使用。

理解用户

  • 用户会购买你的产品吗?

  • 一个设计的改变会带来有更多的注册吗?

  • 用户会理解你的软件是如何工作的吗?

这些问题都无法通过对比你的软件是否满足规范来得到回答。相反,你需要经验知识:你需要观察当你的软件展现给用户时,用户真正做了什么操作。

相关的测试技术包括:

  • 可用性测试

  • 最低可行产品测试(《精益创业》)

  • A/B测试

理解运行时行为

  • 你的软件在负载下的表现如何?

  • 你的软件有资源竞争吗?

  • 当有非法输入时,你的软件是否会崩溃?

这些问题不能总是通过比较你的软件是否符合规范来回答。一旦你的软件足够复杂,你无法完全理解或者预测它的回应。你需要观察它的实际运行来理解其行为。

相关的测试技术包括:

  • 压力测试和浸泡测试

  • 从产品日志中收集异常及跟踪信息

功能的正确性

  • 你的软件是否真正符合规范?

  • 你的软件是否做了它应该做的事?

很容易可以看到,自动化测试可以证明这些,但是请记住检查2+2等于5的单元测试。在更基本的层面上,软件可以在技术上满足规范,但是不能达到规范的目标。只有我们理解规范背后的含义,然后才能确定软件是否达到了目标。

相关的测试技术包括:

  • 手动用户界面测试(如:QA人员使用您的网站)

  • 代码审查

功能的稳定性

  • 对于同样的输入,你的公开接口(API)是否总能返回相同的结果?

  • 你的代码是否提供了它应该提供的保证?

人类很不擅长测试这些情况。人类非常容易忽略小的变化:如果一个按钮从“Send Now”改变为“Send now”,你可能根本就不会注意到。相反,如果你的接口从sendNow() 变为 send_now(),或者返回值的类型有轻微变化,你的软件就会崩溃。

这意味着一个公开接口,尤其是其他软件依赖的接口,为了保证正确性必须要稳定。当你不断更新你的测试时,为改变频繁的私有接口或者代码编写自动化测试,将会导致非常高的维护成本

相关的测试技术包括:

  • 单元测试、集成测试和其他类似的自动化接口测试

  • 自动化用户界面测试(如:网站的Selenium测试)

  • 编译器检查和静态检查

模型的应用

那么这一切有什么好处呢?

选择如何去测试

首先,我们最初的目标:基于你的目标,这个模型可以帮助选择测试形式。

考虑一个新建立的产品,不确定什么样的人愿意使用这个产品。自动化测试的重点在于确保代码符合规范,因此在搞清楚用户真正的需求之前,编写自动化测试用例可能是浪费时间。

精益创业(Lean Startup)是一种可行的替代方法,它的目标是找到什么样的产品可以满足用户的需求,它侧重于实验或者尝试。这意味着专注理解用户这个象限。一旦选定了产品,你就可以花费时间在确认“最低可行性”之外的地方,比如投入更多的资源保证软件功能的正确性和稳定性。

辨别你是否选择了错误的测试类型

第二,当你选择了错误的测试类型时,这个模型可以帮你改变航向。比如假设编写税收软件(细节源自一个真实案例),他们为他们的web界面编写了Selenium测试,与此同时他们的web界面做了重大的改变。

即使做了测试,他们的程序依然是有bug的,每次改变界面这些测试用例就不能使用了。测试似乎没有提升质量,但是它浪费了开发者的时间进行维护。他们做错了什么?

这个问题就是他们的系统实际上有两部分:

  1. 税收引擎相当稳定,税法每年只改变一次。对于用户来说税收引擎中的错误是一个主要问题,对于开发者来说不兼容的接口改变是一个问题。这表明需要稳定的功能测试,比如针对税收计算引擎的单元测试。正确的功能可以通过代码审和查税务会计的反馈来保证。

  2. 基于web的用户界面。UI界面频繁的变更,这表明稳定的功能测试现在还不是目标。现在的目标是功能的正确性,所以UI界面应该进行手工测试(比如:当程序员写代码时进行测试)

讨论测试的基础

最后,这个模型提供了一个共享的术语,这个术语可以帮助你在广泛的意义和不同的目标下讨论测试。

  • 可以不必再对手工测试和单元测试哪个更好进行无休止的争论,从这个模型中可以非常清楚的展示出他们之间的差异。

  • 你还可以与公司的其他部门(如市场营销)讨论测试,这会是一个非常不同的测试视角。

  • 明天计划的事:

  • 测试租人


返回列表 返回列表
评论

    分享到