• 良好的设计应当是所有开发者的追求,然而对于遗留代码来说,良好的设计只是我们不断逼近的目标。

---我们通常先遇到是的已有的Project和产品代码,我们要对其做应用修改,开发新的功能,适应不同客户的需求。
 为什么一开始总是这样,而不是从无到有?

  • Seam,fake/mock object,解依赖技术

---总结了三大类方法,使测试代码独立于产品代码之外。

  • 介绍的修改软件的四个起因,在过去的月度release的流程都遇到过的问题。这些都是客户需求的变化。

1. 添加新特性---New feature introduced
2. 修正bug---Bug fixed

---这两者都有对代码的修改,客户通常会认为这都是功能上的问题,而开发会从代码修改上区分是新的行为还是bug的修正。开发之所以要区分:毕竟bug是task没有做好,而新功能是新的task。


3. 改善设计---Feature enhancement

重构(refactoring):在不改变软件行为的前提下改善其设计的举动
理念:1) 编写测试已确保现有行为不变
2) 进行一系列的结构上的调整,并通过测试的支持使得代码修改更容易着手
3)有可能会损失一部分性能

4. 优化资源使用---Peformance improvement
优化-时间与内存

  • Matrix table (结构、功能、资源使用) for software modification cause:

 添加特性修正bug重构优化
结构改变改变改变--
新功能改变------
功能--改变----
资源使用------改变

结论:添加特性、重构、优化都维持既有功能不变。

  • 修改代码为了减小风险所要考虑的三个问题,自我检查。

1)我们要进行哪些修改
2)我们如何得知已经正确地完成了修改
3)我们如何得知没有破坏任何(既有的)东西

=============================================================

  • 测试含义的衍生

通过测试来检验正确性---通过测试代码确认既定功能的正确性。
通过测试来检测变化---通过测试代码发现功能修改的变化,确认其合理性(行为改变 or 引入Bug)。

  •  回归性测试---周期性的运行测试来检验已知良好行为---软件夹钳

---在自动化daily run可以很快发现开发修改产生的问题。

  •  单元测试---最为原子的行为单元(过程:函数,面向对象:类)

---确定最小单元,使测试具备正交性。函数,接口,类方法调用,能够确定输入的测试数据和输出测试结果。

  • 单元测试的具备的品质

1)运行块
2)能帮助我们定位问题所在

  • 单元测试与大型测试

---测试分组:测试模块化,树形分层,可选择的测试策略。

  • 单元测试的效率

要求:十分之一秒对于单元测试来说简直就像一个世纪一样
---测试类的数量,或许以后就会碰到的问题。

  • 遗留代码处理过程:解除依赖性以便改动变得更容易

---遗留代码修改算法
1)确定改动点
2)找出测试点
3)解依赖
4)编写测试
5)修改、重构

  • TDD来往遗留代码中添加特性

---测试数据的增加导致测试时间的增加,测试数据模拟测试场景。

  • 感知---选择可以去依赖的类;分离---寻找一定的方法去除依赖
  • 源代码集成需要测试的类,重写内部的定义,并简化内部依赖,调用fake object和mock object,Mock object就是在内部进行断言检查的伪对象。

---fakeObject--->mockobject
Example:

--------------------------------------------------------

//需要测试的接口类;

class InterfaceCalss{
public:

  Method();
 };

--------------------------------------------------------

//接口类实现产品类定义的具体功能;

class ProductClass public: InterfaceCalss{
 

public:

  CalssA m_ObjA; 
  CalssB m_ObjB;
  CalssC m_ObjC;
 
};

---------------------------------------------------------

//定义虚拟类,用来解除对部分的代码调用依赖;

class FakeClass{

};

---------------------------------------------------------

class TestClass public:InterfaceCalss{
public:

//调用虚拟类,解除依赖
 FakeClassA m_ObjA;
 FakeClassB m_ObjB;
 FakeClassC m_ObjC;

//获取最后的结果反馈;
 int GetLastRresultMethod();

};

//TestClass相当于ProductClass一个测试副本

----------------------------------------------------------------

  • 非面向对象语言中,则可以通过定义一个替代函数来达到伪装的目的,改替代函数将某些值记录在全局数据结构中,从而我们可以在测试中访问这些值。

---预处理期接缝,宏替换。