47

Vert.x入坑须知(4.1):用Spock写异步测试 - DTeam 团队日志

 4 years ago
source link: https://blog.dteam.top/posts/2018-12/vert-x%E5%85%A5%E5%9D%91%E9%A1%BB%E7%9F%A54-1%E7%94%A8spock%E5%86%99%E5%BC%82%E6%AD%A5%E6%B5%8B%E8%AF%95.html?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Vert.x入坑须知(4.1):用Spock写异步测试

胡键 Posted at — Dec 29, 2018 阅读 227

点进来的老读者可能会对系列的数字感到奇怪:为何不是 5 而是 4.1?实话是,本篇内容足够重要,可以算得上入坑必须了解的内容。但从篇幅上来讲它实在又有点单薄,而我最近也没时间憋个大招去写长篇大论,权衡之下干脆采用小数计位,赶在 18 年最后一个工作日完稿。

之前在本系列的第三篇,我曾提到我们团队采用的测试框架是 Spock,也提到了为何我们坚持使用这个框架,即使是在 Vert.x 已经对测试有支持的情况下。

对于非异步场景,Spock 工作得很好,写测试的效率也很高。对于异步场景,之前我们一直采用的策略是加上“必要的 sleep”。就这样凑合了不短的时间之后,终于团队内有小伙伴开始抱怨了。

这也很容易理解,由于机器配置的不同,sleep 的时间很难把握得恰到好处。往往出现在一台机器上可以跑过的测试而在另一台机器上跑不过,再加上我们要求必须有自动化测试代码并配置了 pipeline,这样一来自然就有人受不了啦。

本着解决根本问题的精神,再辅以高超的搜索大法,最终我们摸索出了一套用 Spock 来测试 vertx 异步场景的方法。说来惭愧,这个方法一直就在那里,只是我们一直没有特别重点的去关注:Spock 对于异步测试的支持。

对于异步场景,Spock 已经提供了 3 个测试辅助类:

  • BlockingVariable
  • AsyncConditions
  • PollingConditions

BlockingVariable

顾名思义,这个类的作用就是一直阻塞,直到有值。它非常适合测试异步回调返回值的测试场景,如下例,测试一个数据库的返回值。

when:
BlockingVariable<Integer> rowCount = new BlockingVariable<>()
BlockingVariable<String> callback = new BlockingVariable<>()
pgUtils.simpleSql(NamedQuery.uncalledCallback) { rowSet ->
    rowCount.set(rowSet.size())
    callback.set(rowSet.asList()[0].getString('callback'))
}

then:
rowCount.get() == 1
callback.get() == 'callback2'

rowCount.get()会一直阻塞,直到其检测到有值,这样就避免的无谓的 sleep。

AsyncConditions

这个类用于测试异步条件是否,如下面的例子:

setup:
conditions = new AsyncConditions(1)  // 其中的数字为需要evaluate的个数,缺省为1
String source = "foo.txt";
String target = "bar.txt";
createFileWithJunk(source, 100);

when:
vertx.fileSystem().copy("$testDir$pathSep$source", "$testDir$pathSep$target") {
    conditions.evaluate {
        assert new File(testDir, source).exists()
        assert new File(testDir, target).exists()
    }
}

then:
conditions.await();

在这个例子中,await 将一直处于阻塞状态,直到 evaluate 部分的代码满足条件。但它的缺点也很明显,整个测试并不那么“spock style”,整个验证过程都放在了 when 部分。

PollingConditions

这个类的作用跟 AsyncConditions 非常类似,但它弥补了后者的不足,如下例:

setup:
def conditions = new PollingConditions(timeout: 10, initialDelay: 1.5, factor: 1.25)
def machine = new Machine()

when:
machine.start()

then:
conditions.eventually {
    assert machine.temperature >= 100
    assert machine.efficiency >= 0.9
}

从上面的代码可以看出来,验证部分就在 then 部分,完美。

至此,Spock 的这些工具类非常好地解决了 vertx 的异步场景测试问题,而且 gradle 输出的测试报告来看,测试时间也比之前要省不少!

那么,这些工具类也可以用于测试其他的异步场景么?当然,从上面的代码看,所有测试只依赖 Spock 的异步测试工具类,与 vertx 完全无关!并且,对于每个测试工具类,Spock 也提供了超时机制,具体细节可以参看它们的 JavaDoc


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK