zoukankan      html  css  js  c++  java
  • 打造第二代测试框架TestDriven 2.0(七)—— 让测试驱动更加的自动吧!

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

    前言 Preface 

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

    本文介绍了一种新颖的测试思路,并制作了原型系统展示其效果。

    此技术将作为测试驱动框架2.0的一个部分(Testdriven 2.0) 。

    而测试驱动2.0的目的是:让代码之间沟通,让变化更加容易。 

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

    测试分类 与 本文的讨论对象 Catalog  

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

    测试包含了很多种,每一种需要特定的技术去解决,例如:

    1. Winform类的界面测试:通常使用钩子等Win32接口去捕捉用户的操作,然后模拟回放进行测试(此技术不在讨论范围) 

    2. Web界面测试:一般使用JS嵌入测试页面,同样模拟用户操作;或者使用IE内核等调用内部函数实现用户操作(此技术不讨论) 

    3. Web的Http模拟测试:在.net 2.0比较难实现,到了3.0之后的版本,微软对HttpContext这个庞然大物体做了重构,因此让测试变得稍微简单了。(此技术不讨论)

    4. 类库、代码测试:这个是我需要讨论的终点,包含了各种框架、逻辑应用等。现有的技术主要是UNit / Testdriven.net / Mock等。他们也貌似很好的解决了一些问题。但是。。。

    所以,本文接下来将针对第4种测试 (类库、代码测试),也是最常见的测试进行讨论。 

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

    现有的问题 Problem

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

    现在的测试,很大一部份是在回归。开发者梦想编写好自动测试代码,日后如果有变动,通过做回归,就知道是否破坏了之前的功能、是否产生了bug。朝着这个目标,诞生了很多测试工具。可是在我看来,他们只是从一个小坑跳到了另外一个大坑。(也就是我之前说的,掉入自己挖的坑里了)

    首先,测试的结果是否准确,完全取决于测试数据是否全面准确。 那么编写测试数据本身就存在了人为的bug。

    其次,测试代码和业务代码紧密联系,一旦业务代码修改,测试代码往往是全盘否定的。这就出现一个矛盾:如果测试代码写的马虎,日后基本上不能用;如果测试代码写的精细,一旦修改起来,之前的工作都白费了。

    所以,我们真正期望的是:能够自动分析业务代码,自动编写测试代码,而不是人去写。这个目标现在还很难实现(微软在VS2010里面已经大量引入了Code Gen等技术,可是。。)

    可是难,不等于不行,下面我将尝试迈出一小步。

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

    原理分析 Analysis

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

    要让测试变得自动,首先需要抽象出测试过程,然后逐一攻破。经过我分析,一段测试代码主要包含了三个方面:

    1. 测试数据生成。

    直接决定了测试代码是否有效;因此要求全面、准确、也业务逻辑精密绑定。 这部分工作目前是没有更好的思路。 

    2. 调用对应方法。

    这个很简单,就是调用一个方法,传入测试数据。没有优化的必要。

    3. 查看测试结果是否符合预期。

    这部分以往是写这非常无聊的Assert.IsEqual等。既无聊,又浪费时间。而恰恰这部分我发现了提升的空间。

    测试结果无非就是字符串、对象等。就是c#的ValueType / class。 而如果是对象,也一定是对象的某些属性(Property) 。而这些数据都是可以被序列化、反序列化的!

    因此 这个过程完全可以被机器代替,从而让测试代码变得更加灵活,立马减少50%的工作量!现在我就展示一下目前的原型系统效果。

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

    原型系统效果  ProtoType 

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

    首先是一段测试代码。

            public void test00001()
            {
                
    object pojo = CreatePojo();

                Assert.SaveOrVerify(
    "test000 create pojo", pojo);
            }

    这段代码的目的是 测试生成的pojo对象是否符合预期。 而一个Pojo对象可能是下面一个接口的实例:

    代码
        interface IinterfaceWithAllCollection
        {
            
    byte[] Image { get;set;}
            
    string Name { get;set;}
            
    double Fee { get;set;}
            
    int Age { get;set;}
            IinterfaceWithAllCollection[] pojos { 
    get;set;}
            List
    <IinterfaceWithAllCollection> pojos2 { get;set;}
            ObjectWithValue objPojo { 
    get;set;}
            ObjectWithValue[] objPojos { 
    get;set;}
            List
    <ObjectWithValue> objPojos2 { get;set;}
        }

    按照以往的做法,一定是要展开这个对象,获取每一个属性,然后做Assert。现在我仅仅需要一句话就完成了测试结果验证
    Assert.SaveOrVerify("test000 create pojo", pojo); 

    不知道您感受到了其中的魅力和惊喜没有? 

    调用了这句话, 框架首先会搜索保存在磁盘的结果数据,一般是xml文件;这些数据本质上就是预期结果的序列化值。然后逐一和这些值做对比。

    那么您一定好奇,这些期望的值从哪里来?答案就是,代码本身生成。当第一次执行的时候,是没有预期值的,那么框架会给出警告,然后将当前数据持久到磁盘。例如:

    代码
    ------ Test started: Assembly: Pixysoft.Framework.Configurations.dll ------

    WARNING: expected value do not existed. create new one for test000 create pojo
    Verifying IinterfaceWithAllCollection.Image.
    TRUE: expected
    =%01, actual=%01

    Verifying IinterfaceWithAllCollection.Name.
    TRUE: expected
    =hello, actual=hello

    Verifying IinterfaceWithAllCollection.Fee.

    。。。。。 省略

    这个时候,我调用一个配置界面,就可以查看第一次生成的值,然后修改成为预期值:

     

     

    这样一个序列化结构就可以通过 树形结构 展示出来。 现在我们只要查看第一次运行的结果是否正确,调整ExpectedValue。 这样这段测试代码就可以永远被重复调用了。

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

    小结 Summary 

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

    因为是原型系统,目前还不能发出第一个release,不过很快就可以完成了。主要是我写的代码和屎一样烂,需要进行优化才好意思拿出来。

    等release出来时候,所有代码都会采取开源的策略。不过是一种新的开源策略。

    如果各位有急着需要的,咱们可以相互讨论交流下。希望大家多提供些思路,多提供您期望的需求。谢谢! 

  • 相关阅读:
    CXF JaxWsDynamicClientFactory 错误:编码GBK的不可映射字符
    关于springboot配置DataSource
    Spring Boot2.0加载多个数据源
    Kettle配置发送邮件
    推荐几个不错的VUE UI框架
    vue基础语法一
    Maven在Eclipse下构建多模块项目过程
    利用eclipse把jar包安装到本地仓库
    设计模式之策略模式
    设计模式之观察者模式
  • 原文地址:https://www.cnblogs.com/zc22/p/1753662.html
Copyright © 2011-2022 走看看