分布式程序的自动化回归测试

发表于:2011-5-05 10:59

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:陈硕    来源:51Testing软件测试网采编

分享:

  稍微复杂一点的测试要用 mock object。ChatServer 用 TcpServer 和 TcpConenction 来收发消息,为了能单元测试,我们要为 TcpServer 和 TcpConnection 提供 mock 实现,原本一个具体类 TcpServer 就变成了一个 interface TcpServer 加两个实现 TcpServerImpl 和 TcpServerMock,同理 TcpConnection 也一化为三。ChatServer 本身的代码也变得复杂,我们要设法把 TcpServer 和 TcpConnection 注入到其中,ChatServer 不能自己初始化 TcpServer 对象。

  这恐怕是在 C++ 中使用单元测试的主要困难之一。Java 有动态代理,还可以用 cglib 来操作字节码以实现注入。而 C++ 比较原始,只能自己手工实现 interface 和 implementations。这样原本紧凑的以 concrete class 构成的代码结构因为单元测试的需要而变得松散(所谓“面向接口编程”嘛),而这么做的目的仅仅是为了满足“源码级的可测试性”,是不是有一点因小失大呢?(这里且暂时忽略虚函数和普通函数在性能上的些微差别。)对于不同的 test case,可能还需要不同的 mock 对象,比如 TcpServerMock 和 TcpServerFailureMock,这又增加了编码的工作量。

  此外,如果程序中用到的涉及 IO 的第三方库没有以 interface 方式暴露接口,而是直接提供的 concrete class (这是对的,因为C++中应该《避免使用虚函数作为库的接口》),这也让编写单元变得困难,因为总不能自己挨个 wrapper 一遍吧?难道用 link-time 的注入技术?

  ● 某些 failure 场景难以测试,而考察这些场景对编写稳定的分布式系统有重要作用。比方说:网络连不上、数据库超时、系统资源不足。

  ● 对多线程程序无能为力。如果一个程序的功能涉及多个线程合作,那么就比较难用单元测试来验证其正确性。

  ● 如果程序涉及比较多的交互(指和其他程序交互,不是指图形用户界面),用单元测试来构造测试场景比较麻烦,每个场景要写一堆无趣的代码。而这正是分布式系统最需要测试的地方。

  总的来说,单元测试是一个值得掌握的技术,用在适当的地方确实能提高生产力。同时,在分布式系统中,我们还需要其他的自动化测试手段。

  分布式系统测试的要点

  在分布式系统中,class 与 function 级别的单元测试对整个系统的帮助不大,当然,这种单元测试对单个程序的质量有帮助;但是,一堆砖头垒在一起是变不成大楼的。

  分布式系统测试的要点是测试进程间的交互:一个进程收到客户请求,该如何处理,然后转发给其他进程;收到响应之后,又修改并应答客户。测试这些多进程协作的场景才算测到了点子上。

  假设一个分布式系统由四五种进程组成,每个程序有各自的开发人员。对于整个系统,我们可以用脚本来模拟客户,自动化地测试系统的整体运作情况,这种测试通常由 QA 团队来执行,也可以作为系统的冒烟测试。

  对于其中每个程序的开发人员,上述测试方法对日常的开发帮助不大,因为测试要能通过必须整个系统都正常运转才行,在开发阶段,这一点不是时时刻刻都能满足(有可能你用到的新功能对方还没有实现,这反过来影响了你的进度)。另一方面,如果出现测试失败,开发人员不能立刻知道这是自己的程序出错,有可能是环境原因造成的错误,这通常要去读程序日志才能判定。还有,作为开发者测试,我们希望它无副作用,每天反复多次运行也不会增加整个环境的负担,以整个 QA 系统为测试平台不可避免要留下一些垃圾数据,而清理这些数据又会花一些宝贵的工作时间。(你得判断数据是自己的测试生成的还是别人的测试留下的,不能误删了别人的测试数据。)

  作为开发人员,我们需要一种单独针对自己编写的那个程序的自动化测试方案,一方面提高日常开发的效率,另一方面作为自己那个程序的功能验证测试集(即回归测试/regression tests)。

  分布式系统的抽象观点

  一台机器两根线

  形象地来看,一个分布式系统就是一堆机器,每台机器的屁股上拖着两根线:电源线和网线(不考虑 SAN 等存储设备),电源线插到电源插座上,网线插到交换机上。

  这个模型实际上说明,一台机器的表现出来的行为完全由它接出来的两根线展现,今天不谈电源线,只谈网线。(“在乎服务器的功耗”在我看来就是公司利润率很低的标志,要从电费上抠成本。)

  如果网络是普通的千兆以太网,那么吞吐量不大于 125MB/s。这个吞吐量比起现在的 CPU 运算速度和内存带宽简直小得可怜。这里我想提的是,对于不特别在意 latency 的应用,只要能让千兆以太网的吞吐量饱和或接近饱和,用什么编程语言其实无所谓。Java 做网络服务端开发也是很好的选择(不是指 web 开发,而是做一些基础的分布式组件,例如 ZooKeeper 和 Hadoop 之类)。尽管可能 C++ 只用了 15% 的 CPU,而 Java 用了 30% 的 CPU,Java 还占用更多的内存,但是千兆网卡带宽都已经跑满,那些省下在资源也只能浪费了;对于外界(从网线上看过来)而言,两种语言的效果是一样的,而通常 Java 的开发效率更高。(Java 是比 C++ 慢一些,但是透过千兆网络不一定还能看得出这个区别来。)

52/5<12345>
精选软件测试好文,快来阅读吧~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号