zoukankan      html  css  js  c++  java
  • 打造第二代测试框架TestDriven 2.0(六)—— 最新测试思路分析

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

    前言 Preface

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

    这几天正在做dynamic的时候,突然想到了测试框架的最新思路。

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

    思路介绍

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

    整个测试流程主要是:给出测试数据,查看符合的结果。

    测试种类非常多,例如CS界面测试(使用钩子等录制并回滚);BS界面测试(使用js直接调用) ;网站的测试(模拟http);普通类库测试(NUnit等)等等。

    如果是界面这种黑盒测试,我就不讨论;网站测试难度很大,应该尽量化简为类库测试;所以最终来到普通来库测试。

    因此一个非常典型的测试代码如下:

    代码
            public void test011()
            {
                ObjectWithInterfaceCollection pojo4 
    = new ObjectWithInterfaceCollection();
                pojo4.Age 
    = 321;
                pojo4.Fee 
    = 321.321;
                pojo4.Name 
    = "pojo";
                pojo4.Type 
    = EnumTYpe.B;

                ObjectWithInterfaceCollection subpojo 
    = new ObjectWithInterfaceCollection();
                subpojo.Age 
    = 456;
                subpojo.Pojo 
    = new ObjectWithCollecton();
                subpojo.Pojo.Age 
    = 789;

                pojo4.Pojos 
    = new ObjectWithCollecton[] { subpojo };

                pojo4.Pojo 
    = subpojo;

                pojo4.Ipojolist 
    = new List<IinterfaceWithValue>();
                pojo4.Ipojolist.Add(subpojo);

                pojo4.Ipojo 
    = subpojo;

                IXmlNode node 
    = XmlManager.DynamicSerialize(pojo4);

                ObjectWithInterfaceCollection rpojo4 
    = XmlManager.DynamicDeserialize<ObjectWithInterfaceCollection>(node.Serialize(true));

                Assert.IsEqual(pojo4.Age, rpojo4.Age);
                Assert.IsEqual(pojo4.Fee, rpojo4.Fee);
                Assert.IsEqual(pojo4.Name, rpojo4.Name);
                Assert.IsEqual(pojo4.Type, rpojo4.Type);

                Assert.IsEqual(pojo4.Pojos[
    0].Age, rpojo4.Pojos[0].Age);
                Assert.IsEqual(pojo4.Pojos[
    0].Pojo.Age, rpojo4.Pojos[0].Pojo.Age);

                Assert.IsEqual(pojo4.Pojo.Age, rpojo4.Pojo.Age);
                Assert.IsEqual(pojo4.Pojo.Pojo.Age, rpojo4.Pojo.Pojo.Age);

                Assert.IsEqual(pojo4.Ipojolist[
    0].Age, rpojo4.Ipojolist[0].Age);

                Assert.IsEqual(pojo4.Ipojo.Age, rpojo4.Ipojo.Age);

                Assert.Write(node.Serialize(
    true));
            }

    现在的测试存在的问题: 

    1. 由于测试代码和逻辑代码相互关联非常紧密;一旦逻辑代码变动,导致测试代码变动的非常厉害,甚至要重写。

    2. 测试代码如果书写不认真,那么在第一个问题上就会问题加重;可是如果写测试代码也使用了重构、设计模式,这样工作量倍增,一旦逻辑代码变动,测试代码变得没有意义。

    可见,如果要使用测试驱动,那么带来的问题是非常多的。

    测试驱动能解决的问题是:

    1. 通过回归测试,能够知道新开发的功能有没有违反原有的功能。

    貌似测试驱动能解决的问题和带来的问题相比较,微不足道。

    因为测试的正确取决与输入参数的正确和全面。可是如果对测试代码马虎对待,那么结果一定也有问题。这样导致了回归测试出现错误。产生一个恶性循环。所以到目前为止,我还没想到一个好的思路。不过有点转机。

    由于测试代码是逻辑代码的辅助代码,从理论上,逻辑代码变更后,测试代码应该非常容易变更。而目前无法做到,原因是,对整个测试流程无法抽象出一个简单的模型。我现在就尝试抽象。

    上文的代码包含了:

    1. 生成测试数据

    复杂、烦琐、而且重要。测试数据直接决定了本测试结果是否有效。因此这部分一定需要人去写。

    测试数据本身一定也是POJO对象(参考3);同时测试中,必须可见方便维护和分析。

    2. 调用对应的方法

    简单,仅仅一句话。完全可以机器代替,所以问题在于手写一个调用快,还是鼠标指定一个调用快。
     

    3. 查看测试数据是否符合期望。 

    工作量烦琐,而且毫无意义,所以很多人喜欢用console.write,但是这样又丢失了机器检测的优势。导致人为错误。 

    可是分析发现,测试数据一定是对象,例如string, 如果是类的对象,则一定需要继续展开,查看这个类的属性;因此可以看成是一个典型的POJO模型。

    如果有一种机制,能够对POJO进行展开和检查,而且不需要人为参与,那么就降低了很多工作量。

    唯一需要人为参与的地方,就是规定出某个变量 = XXXX / is null / throw exception. 这个规定的过程,可以抽象出来一种机制。

    根据分析,那么到底是使用IDE工具?还是使用代码?

    从程序员角度分析,使用代码>使用鼠标+键盘输入。!!

    结论:尽量使用代码。

    数据输入使用界面还是代码? 

    如果使用界面,那么接下来的也要界面。非常麻烦。仅仅制定一个对象,可能需要写一堆xml

    结论:使用代码。

    结果验证使用界面还是代码?

    结果验证的时候,第一次需要配置验证,可以参考noebe.global的思路,自动对输出进行截取+编译为xml,给出界面用户指定数据校验。

    之后如果再运行,就可以查看是否和第一次制定的一致。类似的效果:

    结论:Assert.Verify(object value); <---- 一句话就把所有结果都验证了。

    配置的文件放在什么地方? 

    放在项目的目录中。可以使用codelive.visual,也可以直接操作目录。目前第一个开放版本使用file。不集成在IDE。

    依赖性到底如何?

    1. 是否使用reflection? 如果不使用,那么就用reflection。这样可以不依赖reflection的dll

    2. 是否使用config?如果不进行序列化等操作,可以不用——》必须建立一个可以在核心框架解析的语法,例如:

    xxx.xxx.xxx = xxx;

    如果这2个问题解决了,那么整个Assert.Verify可以脱离framework直接运行。

    小结一下:

    之前所有代码都不变,例如attribute之类的。可以使用自己的,也可以使用testdriven的。

    然后来到验证的时候,首先获取当前method的一个id,作为搜索;

    如果发现文档不存在,则抛出异常。用户可以调用Assert.Save()创建一个验证文档。这个时候将递归获取所有数据。

    搜索到验证文档后,开始解析 并对比值是否正确。 

  • 相关阅读:
    Python垃圾回收机制 总结
    求二叉树中任意两个结点的距离
    Python 实现排序算法
    InnoDB 索引原理
    Linux常用脚本命令总结
    How Django works?
    RabbitMQ 知识总结
    最短路径之Dijkstra算法和Floyd-Warshall算法
    最小生成树之Prim算法和Kruskal算法
    Python collections模块总结
  • 原文地址:https://www.cnblogs.com/zc22/p/1753562.html
Copyright © 2011-2022 走看看