V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
这是一个专门讨论 idea 的地方。

每个人的时间,资源是有限的,有的时候你或许能够想到很多 idea,但是由于现实的限制,却并不是所有的 idea 都能够成为现实。

那这个时候,不妨可以把那些 idea 分享出来,启发别人。
yangff
V2EX  ›  奇思妙想

关于自动化测试的一些想法(主要是 Rspec)

  •  
  •   yangff · 2015-06-19 14:59:20 +08:00 · 2074 次点击
    这是一个创建于 3463 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    1. 首先是一个悲伤的故事...

    2. 我并不是一个经常做工程的人, 当然Test Case我是经常写的... (笑), 这几天放假了在TC上做了个简单的development challenge...

    3. 题目的内容很简单, 就是一堆的crud活, 限定的平台是RoR... RoR的经验我是有辣, 所以尽管deadline没几天我也就没细看要求然后register了... (反正没损失)

    4. 然后我就闷声撸代码... 今天早上写完准备交的时候, 我看到了这么一段:

      Create scaffolds for User, Project, Image, Region and Payoff models, including Rspec specs (tests)
      额...要Tests是吧...

    5. 虽然我没用过Rspec这玩意, 但是我想随便糊弄一下并没有太大问题(反正怎么写都能pass), 反正我本来就弄了一堆边界嘛...

    然后我发现这货设计的形式非常不对我的胃口... 虽然语义上看似很优美, 但是手感太蠢了...虽然在语法上试图直接写出这段代码要验证什么, 但是实际写起来还是要把具体的执行给表达出来.

    嗯... 不过这没什么.

    然后蛋疼的事情来了, 等我Copy & Paste把基本的可用性测试写完之后, 发现如果想要构造一个比较复杂的边界条件, 他对测试的划分似乎也不是很合理...于是...然后就是个悲伤的故事了...(反正等我发现的时候只剩下1分钟了, 幸好我交了一个没有任何tests的代码...不过没什么卵用)

    想法

    1. 这种测试的划分是不是可以做得更直观一些, 比如定义一些env, 然后每次测试的是在一个env下的完整流程, 而不是现在这种对单一模块的测试. 这是考虑到边界的存在并不是上下文无关的, 而是与整个操作流程相关的(特别是流程更为复杂的时候). 对过程的每一段进行预设前提的test, 似乎使得testcase的构造更加复杂, 而且一旦流程有所修改, 这里的边界也会随之变动(增加)(比如根本不存在的边界就要去掉, 因为filter是在流程之外的). 这似乎也使得test的功效下降了(可用性的test没有任何问题...不过test应该覆盖到不仅仅是可用性的问题吧).

    2. 这里的一个问题似乎是各个模块之间并不是毫无关系, 导致对层次较深的模块进行测试的时候会涉及到很多较浅层次的边界问题(一个简单但是没什么意义的例子, Project总要属于一个User). 这使得针对单一模块的测试, 不像很多C/C++程序, 或者是FP大法的程序那样, 可以更加独立的进行. (比如之前pass了, 但是并不能保证比如之前的时候某个值是nil没有影响, 而现在有影响的情况, 这就只能人工构造了, 而之前层次过多导致出现太多的这类情况就很痛苦了, helper不能解决所有问题...至少做起来不是很优雅)

    3. 以及, 针对RoR, 通过定义所有显式逻辑(比如filter, validates, 给出他们的形式化定义), 以及对model和controller中的逻辑结构的分析, 应该可以写出一个自动cover所有可能代码路径的tester... (不过这样的话就会有一些对类型的假设, 不过并不是什么大问题... 第三方组建似乎也会有点问题...)

    6 条回复    2015-06-23 11:41:41 +08:00
    msg7086
        1
    msg7086  
       2015-06-19 20:16:55 +08:00
    不上代码你说个……
    RSpec更多的是在写文档而不是在写测试(虽然测试也是其很重要的功能)
    跨模块测试可以mock走起。
    yangff
        2
    yangff  
    OP
       2015-06-19 20:23:59 +08:00
    @msg7086 所以发到奇思妙想了嘛...
    至于RSpec是Topcoder要求的...
    msg7086
        3
    msg7086  
       2015-06-19 20:31:01 +08:00
    context Server do
    describe 'update_ip' do
    it 'solves IP address on valid domain' do ... end
    it 'does not change IP address on invalid domain' do ... end
    it 'uses the IP address if domain is an IP address' do ... end
    end
    end

    你看,这样的代码看似是测试,实际上是文档。
    很多时候有了这样的Spec,你都不需要写很多文档或者注释了,因为要理解这段代码的含义,只要找相应的Spec稍微读一下就行了。
    (上面这段实际上正是我前几天刚写的Spec)
    yangff
        4
    yangff  
    OP
       2015-06-19 20:34:53 +08:00
    @msg7086 ...
    额...
    那测试不管了吗, 比如如果我要加入一段测试多次异常ip登陆后转账的测试, 那不就很蛋疼了...
    以及文档不是有rdoc直接从注释里面提取吗...
    msg7086
        5
    msg7086  
       2015-06-19 22:19:43 +08:00
    @yangff 上面的是单元测试啊。
    你要做集成/功能测试的话当然也可以,capybara webkit 走起,模拟浏览器请求嘛。
    点这里,点那里,然后expect弹出了对话框,etc

    文档从注释里提是一方面啦。
    但是注释肯定不如Spec代码来得精准。
    你可能改了代码忘记改注释,但是如果忘记改Spec结果就是测试Boooom。
    Bluecoda
        6
    Bluecoda  
       2015-06-23 11:41:41 +08:00
    我也喜欢T::U多过rspec,rspec没有T::U直观啊
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3123 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 04:51 · PVG 12:51 · LAX 20:51 · JFK 23:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.