月度归档: 2018 年 1 月

  • Serverless服务提供商

    今天去更新了一下serverless的代码,突然发现又多了几个Serverless服务商。

    之前场内的玩家有AWS Lamabda和Azure Function。然后IBM有一个类似的,可以自己托管的OpenWhisk。

    今天新看到了几个小一点的

    https://webtask.io/
    
    https://spotinst.com/
    
    http://kubeless.io/

    前两个都是服务商,第三个比较有意思,是基于Kubernetes的,开源可以自己托管。…

  • 再谈多多猫插件开发

    今天找漫画的时候又想到多多猫了,之前用过一下,当时写插件还是用的记事本在xml中直接编写js,那个体验很差,而且代码测试也很复杂。

    今天又需要插件了,自然想换点花样来做,首先考虑的就是使用构建工具来处理大部分问题。这里用的是Gulp。

    模板替换和文件生成

    我们的目标文件只有一个,那就是index.sited.xml。而这个文件又分了两个部分,首先是xml的声明,包含了一些插件信息,其次是我们的js代码。

    首先做的是将这两者分开,分别创建index.xml和index.js文件。

    <?xml version="1.0" encoding="utf-8"?>
    <sited ver="1" debug="1" engine="32" schema="1">
        <meta guid="<%=app.guid%>">
            <title><%= app.title %></title>
            <intro><%= app.intro %></intro>
            <author><%= app.author %></author>
            <url><%= app.url %></url>
            <encode>utf-8</encode>
            <expr><%= app.expr%></expr>
        </meta>
        <main dtype="1" durl="<%= app.url %>">
            <home>
                <hots cache="1d" title="首页" 
  • 单元测试的纯度和脆弱性风险

    客户公司新来了一个CTO,新官上任三把火,他首先盯上了单元测试,他要求只为单个类编写单元测试。所有依赖项都被模拟,简单而言就是单元测试不跨类。

    然后客户展示了一段代码,表示按照这个规范很难操作,因为现在有需求要业务重构B类。

    class A(val b: B) {
    
       fun doSomething() {
           b.doSomethingElse()
           b.doSomethingElse2()
           b.doSomethingElse3()
       }
    }

    我们来简单分析下这个代码和对应的规范:

    按照规范A类和B类都有自己的单元测试,然后根据新的业务需求,类B进行重构并隐藏在接口后面,因此从技术上讲,类A可能会根据场景获得不同的行为。

    现在的问题是,当我们想要遵循项目的指导方针时,我们还应该重构A的单元测试。之前有一个测试,测试对象是B(当然是被mock的)。现在,当对B的引用消失时,测试将被重构,以验证与这个新接口的调用。

    这种情况是在测试重构过程中发生的信息丢失。当在实际系统中存在此类调用时,由于单元测试的纯度,我们不再验证A->B之间的任何通信。

    我认为这种情况是对于单元测试纯度的过度要求,进而增加了单元测试的脆弱性。

    单元测试的纯度

    周围打听下这种纯度要求其实很常见,特别见于新开始建设单元测试的团队,项目领袖对于单元测试对于质量保障有较高的期望,进而导致对于纯度有近乎象牙塔的规范要求,从而导致建设失败。

    这种纯度的建设方式可以用于项目初期开荒,一锤子买卖,快速搞定上级下发的KPI,但是对于项目质量保障毫无价值。

    对于纯度的争议并不少见,我理解其实更多是对于Unit这个外来词的定义问题,机械的将编程语言的类和方法作为一个Unit就是一个高纯度的要求。

    还有一种原因我认为是对于单元测试本质目标的忽略,进而陷入定义的混乱,然而这不是重要的事情。

    不可否认关于Unit的确切含义存在一些分歧。但是,单元测试测试的目的并不是为了符合某些任意的定义。目的是检测错误。或者更一般地说:验证代码的行为是否符合预期。

    重构时,单元测试应该确保变更没有引入错误或更改行为。因此,测试不应该与测试代码中的实现细节耦合。事实上,应该可以完全重写类的实现,并让测试验证行为是否仍然相同。

    因此,从这个角度来看,测试并不关心被测试类是否调用了其他类。这是一个实现细节。事实上,典型的重构是将方法中的一些内部代码提取到一个单独的类中,而这正是测试应该能够验证重构没有改变行为的场景。

    还有一个更简单的例子,一个验证Email地址的Utils类,它是一个static方法,签名如下

    public static bool isValid(string email)

    高纯度的规范要求mock这个方法,你只需要和任何一个最近三个月写过单元测试的研发工程师聊一聊,他就能告诉这个规范是多么愚蠢。

    因此,底线是:避免mock(除了外部服务或非确定性输入的情况),并让测试联动尽可能多的类来验证行为。

    就我个人而言,我喜欢将“单元”视为“行为单元”——规范中可以独立测试的最小部分。但这只是我的定义。

    Mock对脆弱性的影响

    其实公正的讲,这个例子本身是特殊的,因为这个例子正好证明了一个中间问题。让我们来回想一下常见的改动情况。

    当你做出向后不兼容的改变时,依赖于你所改变的东西就会崩溃。所以,如果你的测试现在报错了,那就太好了——一切都在按预期进行。在这一点上,你有几个选择:…