首先是一个悲伤的故事...
我并不是一个经常做工程的人, 当然Test Case我是经常写的... (笑), 这几天放假了在TC上做了个简单的development challenge...
题目的内容很简单, 就是一堆的crud活, 限定的平台是RoR... RoR的经验我是有辣, 所以尽管deadline没几天我也就没细看要求然后register了... (反正没损失)
然后我就闷声撸代码... 今天早上写完准备交的时候, 我看到了这么一段:
Create scaffolds for User, Project, Image, Region and Payoff models, including Rspec specs (tests)
额...要Tests是吧...
虽然我没用过Rspec
这玩意, 但是我想随便糊弄一下并没有太大问题(反正怎么写都能pass), 反正我本来就弄了一堆边界嘛...
然后我发现这货设计的形式非常不对我的胃口... 虽然语义上看似很优美, 但是手感太蠢了...虽然在语法上试图直接写出这段代码要验证什么, 但是实际写起来还是要把具体的执行给表达出来.
嗯... 不过这没什么.
然后蛋疼的事情来了, 等我Copy & Paste把基本的可用性测试写完之后, 发现如果想要构造一个比较复杂的边界条件, 他对测试的划分似乎也不是很合理...于是...然后就是个悲伤的故事了...(反正等我发现的时候只剩下1分钟了, 幸好我交了一个没有任何tests的代码...不过没什么卵用)
这种测试的划分是不是可以做得更直观一些, 比如定义一些env, 然后每次测试的是在一个env下的完整流程, 而不是现在这种对单一模块的测试. 这是考虑到边界的存在并不是上下文无关的, 而是与整个操作流程相关的(特别是流程更为复杂的时候). 对过程的每一段进行预设前提的test, 似乎使得testcase的构造更加复杂, 而且一旦流程有所修改, 这里的边界也会随之变动(增加)(比如根本不存在的边界就要去掉, 因为filter是在流程之外的). 这似乎也使得test的功效下降了(可用性的test没有任何问题...不过test应该覆盖到不仅仅是可用性的问题吧).
这里的一个问题似乎是各个模块之间并不是毫无关系, 导致对层次较深的模块进行测试的时候会涉及到很多较浅层次的边界问题(一个简单但是没什么意义的例子, Project总要属于一个User). 这使得针对单一模块的测试, 不像很多C/C++程序, 或者是FP大法的程序那样, 可以更加独立的进行. (比如之前pass了, 但是并不能保证比如之前的时候某个值是nil没有影响, 而现在有影响的情况, 这就只能人工构造了, 而之前层次过多导致出现太多的这类情况就很痛苦了, helper不能解决所有问题...至少做起来不是很优雅)
以及, 针对RoR, 通过定义所有显式逻辑(比如filter, validates, 给出他们的形式化定义), 以及对model和controller中的逻辑结构的分析, 应该可以写出一个自动cover所有可能代码路径的tester... (不过这样的话就会有一些对类型的假设, 不过并不是什么大问题... 第三方组建似乎也会有点问题...)
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.