[译]OOSE第4章:面向对象系统的研发 4.5 面向对象的测试

4.5 Object-oriented testing

4面向对象的测试

 

The testing of a system which has been developed with an object-oriented method does not differ considerably from the testing of a system developed by any other method. In both cases, we verify the system, namely check that we have correctly designed the system in accordance with a specification. This verification should start as early as possible. The program testing begins at the lowest level, with unit testing, and progresses to integration testing, where the units are tested together to see that they interact correctly. Finally, testing of the entire system is done.

Traditionally, integration testing is usually a 'big bang' event and is very critical during system development. It is at this stage that the developed parts are put together and we then see whether they actually work together. Such a 'big bang' event is not as dramatic in an object-oriented system.

针对面向对象开发方法产生的系统和基于其他方法开发的系统系统相比并没有明显的区别。在两种情况下,我们都会对系统进行校验,来确定是否根据前期的规范正确的实现了系统。这种校验工作必须尽可能早的开始。程序测试工作首先会在比较低的级别进行,也就是单元测试,单元测试完成以后就会进入到集成测试,在这个过程中会把一些单元放在一起测试,来观察他们是否能够正确的交互。最后,会对整个系统进行整体测试。在传统的设计过程中,集成测试通常会引发缺陷的大爆发,进而引发大量的工作量,所以这个环境非常关键。只有到了这个阶段,所有的不同的程序部分才集中放置在一起,同时设计者到了这个阶段才能够观察不同的部分是否在协作运行。而假如我们采用OO的设计方法,则不会在集成测试阶段遭遇如此严重的缺陷的大爆发

 

An object-oriented system consists of a number of objects which communicate with each other. These objects contain both data and behavior, which makes them larger units than the individual routines that one works with in a traditional system development method. An object's operations are developed around specific data and the same designers normally develop all operations for an object (see, nevertheless, the later discussion on inheritance). This leads to unit testing (that is, testing on the lowest level) becoming a test of a larger unit than in a traditionally developed system. Integration testing is carried out at an early stage, since communication is essential to the system development. All objects have predefined interfaces which also contribute to a less dramatic integration testing. The integration testing continues on higher levels and more and more objects are put together incrementally.

一个面向对象的系统包含一系列的对象,这些对象存在一定的交互关系。因为这些对象同时包含着数据和行为方法,所以OO系统中的单元会比传统开发方法中设计的个体单元individual routines要庞大一些。一个对象的操作通常会围绕对象所拥有的数据来设计,通常相同的设计者会设计一个对象所有的操作。(然而,在继承关系中会有所不同)。这种设计方法会导致在单元测试(最地层的测试)环节,OO方法所需要测试的是一个相对比较大的单元,相比较于传统的方法。而同时,集成测试需要提前开始,也就是对对象的操作,因为对象的通信关系是OO系统设计过程中的一个关键。因为所有的对象都有事先定义好的接口,这样一来后期集成测试的工作量会尽一步减少。后续的集成测试会在一个更高的级别开展,而更多的对象可以通过增量开发的方式加入进来。

However, inheritance between classes can create new difficulties with testing. Inheritance means, as you know, that the operations defined in one class are inherited by another class and can also be executed there. Therefore, there may be abstract classes of which there will never be instances, as they only contain common parts from other classes. Is it worth testing these abstract classes? Normally it is worthwhile, since you have then tested an operation once instead of testing it several times in all descendants. However, one must be aware of how the classes are to be used in order to be able to test them properly. An operation in an abstract class may use properties that are changed in the descendants, so, when the context of an operation is changed, the operation normally needs to be retested in the new context.

然而,对象之间的继承关系会为测试带来新的困难。前面大家已经知道,继承就意味者一个类定义的操作可以被其他的类所继承,并在其他类的空间中执行。这样就可能会存在一些抽象类,这些抽象类可能永远不会实例化,抽象类仅仅包含了其他类的公共部分。那么是否值得对抽象类进行测试呢?Normally it is worthwhile, since you have then tested an operation once instead of testing it several times in all descendants. However, one must be aware of how the classes are to be used in order to be able to test them properly. An operation in an abstract class may use properties that are changed in the descendants, so, when the context of an operation is changed, the operation normally needs to be retested in the new context.在大多数情况下,这种测试是值得的。因为您可以在父亲类中针对一个操作测试一次,而代替在所有的后代类descendants.中进行多次测试。然而,设计者还必须关注,这些类应该如何使用以便充分的进行测试。抽象类中的一个操作的一些特性(properties可能会在后代类中改变,所以当一个操作的上下文发生改变,这个操作通常需要在新的应用上下文中进行测试。

 

Testing of inheritance hierarchies thus requires a more exhaustive testing method; you must be aware of how the system will appear in operation. For instance, as we have pointed out, it is not always true that if you test an operation higher up in an inheritance hierarchy a test is not required lower down. An operation can find itself in another (new) environment and may not have been tested in that environment. This means that if we modify an operation in an ancestor, we may need to test this operation in the descendants. In the same way, if we add a new descendant, we may need to test all the operations inherited by this descendant, as they will find themselves in a new environment. Regression and automated testing therefore often play a larger role in the testing of systems developed using an object-oriented technique. Here one must, though, be careful about which test data is used. If you override operations in a descendant, the test data developed earlier may not be adequate for the new operation. As test data often starts by testing possible ways to use an operation, it is not certain that the old test data can test the new operation. In extreme cases we may therefore need to develop special test data for each level in the inheritance hierarchy. Other problems in testing object-oriented software include polymorphism. We shall discuss OO testing in greater detail later.

Another problem arises if the object sends stimuli to itself. Such stimuli, perhaps, are only relevant in a descendant and it is therefore not worthwhile testing the abstract class in this situation. It requires a lot of work to go up and down in a class hierarchy in order to understand the consequences of a message which is sent to the object itself. This problem is called the Yoyo problem (see Taenzer et at. (1989))

. 对层次化继承关系进行测试需要一个更加充分的测试方法;你必须关注系统是如何进行操作。举个例子来说,我们前面已经提到的,通常对祖先类的操作进行测试以后,往往还需要对后裔类的操作进行测试。一个操作可能会通过继承类在其他的环境中运行,然而在其他的环境中并没有进行充分的测试。这就往往意味着,如果我们对祖先类的功能进行了变更,所有的后代类也必须进行测试。基于同样的理由,如果我们添加了一个新的后裔类,我们必须针对这个后裔类继承的所有操作进行测试,因为这些操作将会在新的环境中运行。

回归测试和自动测试通常在面向对象的系统测试中发挥了非常重要的作用。在这里,测试者必须非常关注如何选择正确的测试数据。假如你针对后裔类的操作进行了重构,那么前期准备的测试数据针对新的操作就不再适合。因为我们会基于所有可能的方式来使用操作来准备测试数据,所以很多时候我们不确定旧的测试数据可以用来测试新的操作。再一些极端的情况下,我们可能需要设计特殊的测试数据,能够针对继承层次的每一层进行测试。再OO测试中还有一个麻烦的问题是针对多态进行测试,后续我们还会详细的讨论。

了  另外一个问题是对象可能会对自己发送激励(反身操作),可能这种操作仅仅是对后裔类有帮助,所以就不值得对抽象类进行测试。有时候,测试者需要花费大量的工作对层次化继承关系进行反复分析,以便最后能够理解那些消息是对象自己进行收发的。

With an object-oriented approach, we can more or less consider a test to be an object. The test thus has a class (the test specification) and one or more instances (when we carry out the test). The test is encapsulated, since we are only concerned with the test result and not with how it runs internally. We can even inherit common parts of I ho test specification when we either write the test specification or further develop a test (see Figure 4.6). In the first case, similar parts of test specifications, such as start-up sequences, can be reused. In the latter case, a test specification can evolve in different versions for different versions of the system.

在面向对象的方法中,我们可以或多,或少的把一个测试当作是一个对象。这个测试可以是看成一个类(基于测试的定义)和很多个实例(当我们开始执行这个测试)。测试具有封装encapsulated的特性,因为我们仅仅关系测试的结果,但是我们并不关心这个测试是如何内部运行的。我们还可以使用继承的特性,来使用其他测试的公共部分来设计一些新的测试(见图4.6).在开始的案例中,测试定义的公共部分,比如开始顺序测试,就可以被重新使用。在后续的案例中,一个测试定义可以面向系统的不同版本封装不同的测试用例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值